xref: /netbsd-src/sys/arch/amiga/dev/grf_cl.c (revision 23e63c4b5cecc703250c97faac1ad970f4954821)
1 /*	$NetBSD: grf_cl.c,v 1.58 2023/12/20 00:40:42 thorpej Exp $ */
2 
3 /*
4  * Copyright (c) 1997 Klaus Burkert
5  * Copyright (c) 1995 Ezra Story
6  * Copyright (c) 1995 Kari Mettinen
7  * Copyright (c) 1994 Markus Wild
8  * Copyright (c) 1994 Lutz Vieweg
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *      This product includes software developed by Lutz Vieweg.
22  * 4. The name of the author may not be used to endorse or promote products
23  *    derived from this software without specific prior written permission
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
36 #include "opt_amigacons.h"
37 
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: grf_cl.c,v 1.58 2023/12/20 00:40:42 thorpej Exp $");
40 
41 #include "grfcl.h"
42 #include "ite.h"
43 #include "wsdisplay.h"
44 #if NGRFCL > 0
45 
46 /*
47  * Graphics routines for Cirrus CL GD 5426 boards,
48  *
49  * This code offers low-level routines to access Cirrus Cl GD 5426
50  * graphics-boards from within NetBSD for the Amiga.
51  * No warranties for any kind of function at all - this
52  * code may crash your hardware and scratch your harddisk.  Use at your
53  * own risk.  Freely distributable.
54  *
55  * Modified for Cirrus CL GD 5426 from
56  * Lutz Vieweg's retina driver by Kari Mettinen 08/94
57  * Contributions by Ill, ScottE, MiL
58  * Extensively hacked and rewritten by Ezra Story (Ezy) 01/95
59  * Picasso/040 patches (wee!) by crest 01/96
60  *
61  * PicassoIV support bz Klaus "crest" Burkert.
62  * Fixed interlace and doublescan, added clockdoubling and
63  * HiColor&TrueColor support by crest 01/97
64  *
65  * Thanks to Village Tronic Marketing Gmbh for providing me with
66  * a Picasso-II board.
67  * Thanks for Integrated Electronics Oy Ab for providing me with
68  * Cirrus CL GD 542x family documentation.
69  *
70  * TODO:
71  *    Mouse support (almost there! :-))
72  *    Blitter support
73  *
74  */
75 
76 #include <sys/param.h>
77 #include <sys/systm.h>
78 #include <sys/errno.h>
79 #include <sys/ioctl.h>
80 #include <sys/device.h>
81 #include <sys/device_impl.h>	/* XXX autoconf abuse */
82 
83 #include <machine/cpu.h>
84 #include <dev/cons.h>
85 #if NWSDISPLAY > 0
86 #include <dev/wscons/wsconsio.h>
87 #include <dev/wscons/wsdisplayvar.h>
88 #include <dev/rasops/rasops.h>
89 #include <dev/wscons/wsdisplay_vconsvar.h>
90 #endif
91 #include <amiga/dev/itevar.h>
92 #include <amiga/amiga/device.h>
93 #include <amiga/dev/grfioctl.h>
94 #include <amiga/dev/grfvar.h>
95 #include <amiga/dev/grf_clreg.h>
96 #include <amiga/dev/zbusvar.h>
97 
98 int	cl_mondefok(struct grfvideo_mode *);
99 void	cl_boardinit(struct grf_softc *);
100 static void cl_CompFQ(u_int, u_char *, u_char *, u_char *);
101 int	cl_getvmode(struct grf_softc *, struct grfvideo_mode *);
102 int	cl_setvmode(struct grf_softc *, unsigned int);
103 int	cl_toggle(struct grf_softc *, unsigned short);
104 int	cl_getcmap(struct grf_softc *, struct grf_colormap *);
105 int	cl_putcmap(struct grf_softc *, struct grf_colormap *);
106 #ifndef CL5426CONSOLE
107 void	cl_off(struct grf_softc *);
108 #endif
109 void	cl_inittextmode(struct grf_softc *);
110 int	cl_ioctl(register struct grf_softc *, u_long, void *);
111 int	cl_getmousepos(struct grf_softc *, struct grf_position *);
112 int	cl_setmousepos(struct grf_softc *, struct grf_position *);
113 static int cl_setspriteinfo(struct grf_softc *, struct grf_spriteinfo *);
114 int	cl_getspriteinfo(struct grf_softc *, struct grf_spriteinfo *);
115 static int cl_getspritemax(struct grf_softc *, struct grf_position *);
116 int	cl_blank(struct grf_softc *, int);
117 int	cl_isblank(struct grf_softc *);
118 int	cl_setmonitor(struct grf_softc *, struct grfvideo_mode *);
119 void	cl_writesprpos(volatile char *, short, short);
120 void	writeshifted(volatile char *, signed char, signed char);
121 
122 static void	RegWakeup(volatile void *);
123 static void	RegOnpass(volatile void *);
124 static void	RegOffpass(volatile void *);
125 
126 void	grfclattach(device_t, device_t, void *);
127 int	grfclprint(void *, const char *);
128 int	grfclmatch(device_t, cfdata_t, void *);
129 void	cl_memset(unsigned char *, unsigned char, int);
130 
131 #if NWSDISPLAY > 0
132 /* wsdisplay acessops, emulops */
133 static int	cl_wsioctl(void *, void *, u_long, void *, int, struct lwp *);
134 static int	cl_get_fbinfo(struct grf_softc *, struct wsdisplayio_fbinfo *);
135 
136 static void	cl_wscursor(void *, int, int, int);
137 static void	cl_wsputchar(void *, int, int, u_int, long);
138 static void	cl_wscopycols(void *, int, int, int, int);
139 static void	cl_wserasecols(void *, int, int, int, long);
140 static void	cl_wscopyrows(void *, int, int, int);
141 static void	cl_wseraserows(void *, int, int, long);
142 static int	cl_wsallocattr(void *, int, int, int, long *);
143 static int	cl_wsmapchar(void *, int, unsigned int *);
144 #endif  /* NWSDISPLAY > 0 */
145 
146 /* Graphics display definitions.
147  * These are filled by 'grfconfig' using GRFIOCSETMON.
148  */
149 #define monitor_def_max 24
150 static struct grfvideo_mode monitor_def[24] = {
151 	{0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
152 	{0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
153 	{0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}
154 };
155 static struct grfvideo_mode *monitor_current = &monitor_def[0];
156 
157 /* Patchable maximum pixel clock */
158 unsigned long cl_maxpixelclock = 86000000;
159 
160 /* Console display definition.
161  *   Default hardcoded text mode.  This grf_cl is set up to
162  *   use one text mode only, and this is it.  You may use
163  *   grfconfig to change the mode after boot.
164  */
165 /* Console font */
166 #ifdef KFONT_8X11
167 #define CIRRUSFONT kernel_font_8x11
168 #define CIRRUSFONTY 11
169 #else
170 #define CIRRUSFONT kernel_font_8x8
171 #define CIRRUSFONTY 8
172 #endif
173 extern unsigned char CIRRUSFONT[];
174 
175 struct grfcltext_mode clconsole_mode = {
176 	{255, "", 25000000, 640, 480, 4, 640/8, 680/8, 768/8, 800/8,
177 	 481, 490, 498, 522, 0},
178 	8, CIRRUSFONTY, 80, 480 / CIRRUSFONTY, CIRRUSFONT, 32, 255
179 };
180 /* Console colors */
181 unsigned char clconscolors[3][3] = {	/* background, foreground, hilite */
182 	{0, 0x40, 0x50}, {152, 152, 152}, {255, 255, 255}
183 };
184 
185 int	cltype = 0;		/* Picasso, Spectrum or Piccolo */
186 int	cl_64bit = 0;		/* PiccoloSD64 or PicassoIV */
187 unsigned char cl_pass_toggle;	/* passthru status tracker */
188 static int cl_blanked;		/* true when video is currently blanked out */
189 
190 /*
191  * because all 542x-boards have 2 configdev entries, one for
192  * framebuffer mem and the other for regs, we have to hold onto
193  * the pointers globally until we match on both.  This and 'cltype'
194  * are the primary obsticles to multiple board support, but if you
195  * have multiple boards you have bigger problems than grf_cl.
196  */
197 static void *cl_fbaddr = 0;	/* framebuffer */
198 static void *cl_regaddr = 0;	/* registers */
199 static int cl_fbsize;		/* framebuffer size */
200 static int cl_fbautosize;	/* framebuffer autoconfig size */
201 
202 
203 /*
204  * current sprite info, if you add support for multiple boards
205  * make this an array or something
206  */
207 struct grf_spriteinfo cl_cursprite;
208 
209 /* sprite bitmaps in kernel stack, you'll need to arrayize these too if
210  * you add multiple board support
211  */
212 static unsigned char cl_imageptr[8 * 64], cl_maskptr[8 * 64];
213 static unsigned char cl_sprred[2], cl_sprgreen[2], cl_sprblue[2];
214 
215 #if NWSDISPLAY > 0
216 static struct wsdisplay_accessops cl_accessops = {
217 	.ioctl		= cl_wsioctl,
218 	.mmap		= grf_wsmmap
219 };
220 
221 static struct wsdisplay_emulops cl_textops = {
222 	.cursor		= cl_wscursor,
223 	.mapchar	= cl_wsmapchar,
224 	.putchar	= cl_wsputchar,
225 	.copycols	= cl_wscopycols,
226 	.erasecols	= cl_wserasecols,
227 	.copyrows	= cl_wscopyrows,
228 	.eraserows	= cl_wseraserows,
229 	.allocattr	= cl_wsallocattr
230 };
231 
232 static struct wsscreen_descr cl_defaultscreen = {
233 	.name		= "default",
234 	.textops	= &cl_textops,
235 	.fontwidth	= 8,
236 	.fontheight	= CIRRUSFONTY,
237 	.capabilities	= WSSCREEN_HILIT | WSSCREEN_BLINK |
238 			  WSSCREEN_REVERSE | WSSCREEN_UNDERLINE
239 };
240 
241 static const struct wsscreen_descr *cl_screens[] = {
242 	&cl_defaultscreen,
243 };
244 
245 static struct wsscreen_list cl_screenlist = {
246 	sizeof(cl_screens) / sizeof(struct wsscreen_descr *), cl_screens
247 };
248 #endif  /* NWSDISPLAY > 0 */
249 
250 /* standard driver stuff */
251 CFATTACH_DECL_NEW(grfcl, sizeof(struct grf_softc),
252     grfclmatch, grfclattach, NULL, NULL);
253 
254 static struct cfdata *cfdata;
255 
256 int
grfclmatch(device_t parent,cfdata_t cf,void * aux)257 grfclmatch(device_t parent, cfdata_t cf, void *aux)
258 {
259 	struct zbus_args *zap;
260 	static int regprod, fbprod;
261 	int error;
262 
263 	zap = aux;
264 
265 #ifndef CL5426CONSOLE
266 	if (amiga_realconfig == 0)
267 		return (0);
268 #endif
269 
270 	/* Grab the first board we encounter as the preferred one.  This will
271 	 * allow one board to work in a multiple 5426 board system, but not
272 	 * multiple boards at the same time.  */
273 	if (cltype == 0) {
274 		switch (zap->manid) {
275 		    case PICASSO:
276 			switch (zap->prodid) {
277 			    case 11:
278 			    case 12:
279 				regprod = 12;
280 				fbprod = 11;
281 				error = 0;
282 				break;
283 			    case 22:
284 				error = 0;
285 				break;
286 			    case 21:
287 			    case 23:
288 				regprod = 23;
289 				fbprod = 21;
290 				cl_64bit = 1;
291 				error = 0;
292 				break;
293 			    case 24:
294 				regprod = 24;
295 				fbprod = 24;
296 				cl_64bit = 1;
297 				error = 0;
298 				break;
299 		    	    default:
300 				error = 1;
301 				break;
302 			}
303 			if (error == 1)
304 			    return (0);
305 			else
306 			    break;
307 		    case SPECTRUM:
308 			if (zap->prodid != 2 && zap->prodid != 1)
309 				return (0);
310 			regprod = 2;
311 			fbprod = 1;
312 			break;
313 		    case PICCOLO:
314 			switch (zap->prodid) {
315 			    case 5:
316 			    case 6:
317 				regprod = 6;
318 				fbprod = 5;
319 				error = 0;
320 				break;
321 			    case 10:
322 			    case 11:
323 				regprod = 11;
324 				fbprod = 10;
325 				cl_64bit = 1;
326 				error = 0;
327 				break;
328 		    	    default:
329 				error = 1;
330 				break;
331 			}
332 			if (error == 1)
333 			    return (0);
334 			else
335 			    break;
336 		    default:
337 			return (0);
338 		}
339 		cltype = zap->manid;
340 	} else {
341 		if (cltype != zap->manid) {
342 			return (0);
343 		}
344 	}
345 
346 	/* Configure either registers or framebuffer in any order */
347 	if ((cltype == PICASSO) && (cl_64bit == 1)) {
348 		switch (zap->prodid) {
349 		    case 21:
350 			cl_fbaddr = zap->va;
351 			cl_fbautosize = zap->size;
352 			break;
353 		    case 22:
354 			cl_fbautosize += zap->size;
355 			break;
356 		    case 23:
357 			cl_regaddr = (void *)((unsigned long)(zap->va) + 0x10000);
358 			break;
359 		    case 24:
360 			cl_regaddr = (void *)((unsigned long)(zap->va) + 0x600000);
361 			/* check for PicassoIV with 64MB config and handle it */
362 			if (zap->size == 0x04000000) {
363 			    cl_fbaddr = (void *)((unsigned long)(zap->va) + 0x02000000);
364 			} else {
365 			    cl_fbaddr = (void *)((unsigned long)(zap->va) + 0x01000000);
366 			}
367 			cl_fbautosize = 0x400000;
368 			break;
369 		    default:
370 			return (0);
371 		}
372 	}
373 	else {
374 		if (zap->prodid == regprod)
375 			cl_regaddr = zap->va;
376 		else
377 			if (zap->prodid == fbprod) {
378 				cl_fbaddr = zap->va;
379 				cl_fbautosize = zap->size;
380 			} else
381 				return (0);
382 	}
383 
384 #ifdef CL5426CONSOLE
385 		if (amiga_realconfig == 0) {
386 			cfdata = cf;
387 		}
388 #endif
389 
390 	return (1);
391 }
392 
393 void
grfclattach(device_t parent,device_t self,void * aux)394 grfclattach(device_t parent, device_t self, void *aux)
395 {
396 	static struct grf_softc congrf;
397 	struct zbus_args *zap;
398 	struct grf_softc *gp;
399 	struct device temp;
400 	static char attachflag = 0;
401 
402 	zap = aux;
403 
404 	printf("\n");
405 
406 	/* make sure both halves have matched */
407 	if (!cl_regaddr || !cl_fbaddr)
408 		return;
409 
410 	/* do all that messy console/grf stuff */
411 	if (self == NULL) {
412 		gp = &congrf;
413 		gp->g_device = &temp;
414 		temp.dv_private = gp;
415 	} else {
416 		gp = device_private(self);
417 		gp->g_device = self;
418 	}
419 
420 	if (self != NULL && congrf.g_regkva != 0) {
421 		/*
422 		 * inited earlier, just copy (not device struct)
423 		 */
424 		memcpy(&gp->g_display, &congrf.g_display,
425 		    (char *) &gp[1] - (char *) &gp->g_display);
426 	} else {
427 		gp->g_regkva = (volatile void *) cl_regaddr;
428 		gp->g_fbkva = (volatile void *) cl_fbaddr;
429 
430 		gp->g_unit = GRF_CL5426_UNIT;
431 		gp->g_mode = cl_mode;
432 #if NITE > 0
433 		gp->g_conpri = grfcl_cnprobe();
434 #endif
435 		gp->g_flags = GF_ALIVE;
436 
437 		/* wakeup the board */
438 		cl_boardinit(gp);
439 
440 #ifdef CL5426CONSOLE
441 #if NWSDISPLAY > 0
442 		gp->g_accessops = &cl_accessops;
443 		gp->g_emulops = &cl_textops;
444 		gp->g_defaultscr = &cl_defaultscreen;
445 		gp->g_scrlist = &cl_screenlist;
446 #else
447 #if NITE > 0
448 		grfcl_iteinit(gp);
449 #endif
450 #endif  /* NWSDISPLAY > 0 */
451 		(void) cl_load_mon(gp, &clconsole_mode);
452 #endif
453 	}
454 
455 	/*
456 	 * attach grf (once)
457 	 */
458 	if (amiga_config_found(cfdata, gp->g_device, gp, grfclprint,
459 			       CFARGS_NONE)) {
460 		attachflag = 1;
461 		printf("grfcl: %dMB ", cl_fbsize / 0x100000);
462 		switch (cltype) {
463 		    case PICASSO:
464 			if (cl_64bit == 1) {
465 				printf("Picasso IV");
466 				/* 135MHz will be supported if we
467 				 * have a palette doubling mode.
468 				 */
469 				cl_maxpixelclock = 86000000;
470 			}
471 			else {
472 				printf("Picasso II");
473 
474 				/* check for PicassoII+ (crest) */
475 				if(zap->serno == 0x00100000)
476 				    printf("+");
477 
478 				/* determine used Gfx/chipset (crest) */
479 				vgaw(gp->g_regkva, CRT_ADDRESS, 0x27); /* Chip ID */
480 				switch(vgar(gp->g_regkva, CRT_ADDRESS_R)>>2) {
481 				    case 0x24:
482 					printf(" (with CL-GD5426)");
483 					break;
484 				    case 0x26:
485 					printf(" (with CL-GD5428)");
486 					break;
487 				    case 0x27:
488 					printf(" (with CL-GD5429)");
489 					break;
490 				}
491 	                        cl_maxpixelclock = 86000000;
492 			}
493 			break;
494 		    case SPECTRUM:
495 			printf("Spectrum");
496                         cl_maxpixelclock = 90000000;
497 			break;
498 		    case PICCOLO:
499 			if (cl_64bit == 1) {
500 				printf("Piccolo SD64");
501 				/* 110MHz will be supported if we
502 				 * have a palette doubling mode.
503 				 */
504 				cl_maxpixelclock = 90000000;
505 			} else {
506 				printf("Piccolo");
507 				cl_maxpixelclock = 90000000;
508 			}
509 			break;
510 		}
511 		printf(" being used\n");
512 #ifdef CL_OVERCLOCK
513                 cl_maxpixelclock = 115000000;
514 #endif
515 	} else {
516 		if (!attachflag)
517 			printf("grfcl unattached!!\n");
518 	}
519 }
520 
521 int
grfclprint(void * aux,const char * pnp)522 grfclprint(void *aux, const char *pnp)
523 {
524 	if (pnp)
525 		aprint_normal("ite at %s: ", pnp);
526 	return (UNCONF);
527 }
528 
529 void
cl_boardinit(struct grf_softc * gp)530 cl_boardinit(struct grf_softc *gp)
531 {
532 	volatile unsigned char *ba = gp->g_regkva;
533 	int     x;
534 
535 	if ((cltype == PICASSO) && (cl_64bit == 1)) { /* PicassoIV */
536 		WCrt(ba, 0x51, 0x00);		/* disable capture (FlickerFixer) */
537 		delay(200000);		/* wait some time (two frames as of now) */
538 		WGfx(ba, 0x2f, 0x00);			/* get Blitter into 542x  */
539 		WGfx(ba, GCT_ID_RESERVED, 0x00);	/* compatibility mode     */
540 		WGfx(ba, GCT_ID_BLT_STAT_START, 0x00);	/* or at least, try so... */
541 		cl_fbsize = cl_fbautosize;
542 	} else {
543 
544 		/* wakeup board and flip passthru OFF */
545 		RegWakeup(ba);
546 		RegOnpass(ba);
547 
548 		vgaw(ba, 0x46e8, 0x16);
549 		vgaw(ba, 0x102, 1);
550 		vgaw(ba, 0x46e8, 0x0e);
551 		if (cl_64bit != 1)
552 			vgaw(ba, 0x3c3, 1);
553 
554 		cl_fbsize = cl_fbautosize;
555 
556 		/* setup initial unchanging parameters */
557 
558 		cl_blanked = 1;
559 		WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21);	/* 8 dot - display off */
560 		vgaw(ba, GREG_MISC_OUTPUT_W, 0xed);	/* mem disable */
561 
562 		WGfx(ba, GCT_ID_OFFSET_1, 0xec);	/* magic cookie */
563 		WSeq(ba, SEQ_ID_UNLOCK_EXT, 0x12);	/* yum! cookies! */
564 
565 		if (cl_64bit == 1) {
566 			WSeq(ba, SEQ_ID_CONF_RBACK, 0x00);
567 			WSeq(ba, SEQ_ID_DRAM_CNTL, (cl_fbsize / 0x100000 == 2) ? 0x38 : 0xb8);
568 		} else {
569 			WSeq(ba, SEQ_ID_DRAM_CNTL, 0xb0);
570 		}
571 		WSeq(ba, SEQ_ID_RESET, 0x03);
572 		WSeq(ba, SEQ_ID_MAP_MASK, 0xff);
573 		WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
574 		WSeq(ba, SEQ_ID_MEMORY_MODE, 0x0e);	/* a or 6? */
575 		WSeq(ba, SEQ_ID_EXT_SEQ_MODE, (cltype == PICASSO) ? 0x21 : 0x81);
576 		WSeq(ba, SEQ_ID_EEPROM_CNTL, 0x00);
577 		if (cl_64bit == 1)
578 			WSeq(ba, SEQ_ID_PERF_TUNE, 0x5a);
579 		else
580 			WSeq(ba, SEQ_ID_PERF_TUNE, 0x0a);	/* mouse 0a fa */
581 		WSeq(ba, SEQ_ID_SIG_CNTL, 0x02);
582 		WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x04);
583 
584 		if (cl_64bit == 1)
585 			WSeq(ba, SEQ_ID_MCLK_SELECT, 0x1c);
586 		else
587 		WSeq(ba, SEQ_ID_MCLK_SELECT, 0x22);
588 
589 		WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00);
590 		WCrt(ba, CRT_ID_CURSOR_START, 0x00);
591 		WCrt(ba, CRT_ID_CURSOR_END, 0x08);
592 		WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
593 		WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
594 		WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
595 		WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
596 
597 		WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x07);
598 		WCrt(ba, CRT_ID_MODE_CONTROL, 0xe3);
599 		WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);	/* ff */
600 		WCrt(ba, CRT_ID_EXT_DISP_CNTL, 0x22);
601 		if (cl_64bit == 1) {
602 			WCrt(ba, CRT_ID_SYNC_ADJ_GENLOCK, 0x00);
603 			WCrt(ba, CRT_ID_OVERLAY_EXT_CTRL_REG, 0x40);
604 		}
605 		WSeq(ba, SEQ_ID_CURSOR_STORE, 0x3c);	/* mouse 0x00 */
606 
607 		WGfx(ba, GCT_ID_SET_RESET, 0x00);
608 		WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
609 		WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
610 		WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
611 		WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x00);
612 		WGfx(ba, GCT_ID_MISC, 0x01);
613 		WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f);
614 		WGfx(ba, GCT_ID_BITMASK, 0xff);
615 		WGfx(ba, GCT_ID_MODE_EXT, 0x28);
616 
617 		for (x = 0; x < 0x10; x++)
618 			WAttr(ba, x, x);
619 		WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x01);
620 		WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00);
621 		WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
622 		WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
623 		WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
624 		WAttr(ba, 0x34, 0x00);
625 
626 		vgaw(ba, VDAC_MASK, 0xff);
627 		vgaw(ba, GREG_MISC_OUTPUT_W, 0xef);
628 
629 		WGfx(ba, GCT_ID_BLT_STAT_START, 0x04);
630 		WGfx(ba, GCT_ID_BLT_STAT_START, 0x00);
631 	}
632 
633 	/* colors initially set to greyscale */
634 	vgaw(ba, VDAC_ADDRESS_W, 0);
635 	for (x = 255; x >= 0; x--) {
636 		vgaw(ba, VDAC_DATA, x);
637 		vgaw(ba, VDAC_DATA, x);
638 		vgaw(ba, VDAC_DATA, x);
639 	}
640 	/* set sprite bitmap pointers */
641 	cl_cursprite.image = cl_imageptr;
642 	cl_cursprite.mask = cl_maskptr;
643 	cl_cursprite.cmap.red = cl_sprred;
644 	cl_cursprite.cmap.green = cl_sprgreen;
645 	cl_cursprite.cmap.blue = cl_sprblue;
646 
647 	if (cl_64bit == 0) {
648 
649 		/* check for 1MB or 2MB board (crest) */
650 		volatile unsigned long *cl_fbtestaddr;
651 		cl_fbtestaddr = (volatile unsigned long *)gp->g_fbkva;
652 
653 		WGfx(ba, GCT_ID_OFFSET_0, 0x40);
654 		*cl_fbtestaddr = 0x12345678;
655 
656 		if (*cl_fbtestaddr != 0x12345678) {
657 			WSeq(ba, SEQ_ID_DRAM_CNTL, 0x30);
658 			cl_fbsize = 0x100000;
659 		}
660 		else
661 		{
662 			cl_fbsize = 0x200000;
663 		}
664 	}
665 	WGfx(ba, GCT_ID_OFFSET_0, 0x00);
666 }
667 
668 
669 int
cl_getvmode(struct grf_softc * gp,struct grfvideo_mode * vm)670 cl_getvmode(struct grf_softc *gp, struct grfvideo_mode *vm)
671 {
672 	struct grfvideo_mode *gv;
673 
674 #ifdef CL5426CONSOLE
675 	/* Handle grabbing console mode */
676 	if (vm->mode_num == 255) {
677 		memcpy(vm, &clconsole_mode, sizeof(struct grfvideo_mode));
678 		/* XXX so grfconfig can tell us the correct text dimensions. */
679 		vm->depth = clconsole_mode.fy;
680 	} else
681 #endif
682         {
683                 if (vm->mode_num == 0)
684                         vm->mode_num = (monitor_current - monitor_def) + 1;
685                 if (vm->mode_num < 1 || vm->mode_num > monitor_def_max)
686                         return (EINVAL);
687                 gv = monitor_def + (vm->mode_num - 1);
688                 if (gv->mode_num == 0)
689                         return (EINVAL);
690 
691                 memcpy(vm, gv, sizeof(struct grfvideo_mode));
692         }
693 
694         /* adjust internal values to pixel values */
695 
696         vm->hblank_start *= 8;
697         vm->hsync_start *= 8;
698         vm->hsync_stop *= 8;
699         vm->htotal *= 8;
700 
701 	return (0);
702 }
703 
704 
705 int
cl_setvmode(struct grf_softc * gp,unsigned mode)706 cl_setvmode(struct grf_softc *gp, unsigned mode)
707 {
708 	if (!mode || (mode > monitor_def_max) ||
709 	    monitor_def[mode - 1].mode_num == 0)
710 		return (EINVAL);
711 
712 	monitor_current = monitor_def + (mode - 1);
713 
714 	return (0);
715 }
716 
717 #ifndef CL5426CONSOLE
718 void
cl_off(struct grf_softc * gp)719 cl_off(struct grf_softc *gp)
720 {
721 	char   *ba = gp->g_regkva;
722 
723 	/*
724 	 * we'll put the pass-through on for cc ite and set Full Bandwidth bit
725 	 * on just in case it didn't work...but then it doesn't matter does
726 	 * it? =)
727 	 */
728 	RegOnpass(ba);
729 	vgaw(ba, SEQ_ADDRESS, SEQ_ID_CLOCKING_MODE);
730 	vgaw(ba, SEQ_ADDRESS_W, vgar(ba, SEQ_ADDRESS_W) | 0x20);
731 	cl_blanked = 1;
732 }
733 #endif
734 
735 int
cl_blank(struct grf_softc * gp,int on)736 cl_blank(struct grf_softc *gp, int on)
737 {
738 
739 	WSeq(gp->g_regkva, SEQ_ID_CLOCKING_MODE, on ? 0x01 : 0x21);
740 	cl_blanked = !on;
741 	return 0;
742 }
743 
744 int
cl_isblank(struct grf_softc * gp)745 cl_isblank(struct grf_softc *gp)
746 {
747 
748 	return cl_blanked;
749 }
750 
751 /*
752  * Change the mode of the display.
753  * Return a UNIX error number or 0 for success.
754  */
755 int
cl_mode(register struct grf_softc * gp,u_long cmd,void * arg,u_long a2,int a3)756 cl_mode(register struct grf_softc *gp, u_long cmd, void *arg, u_long a2, int a3)
757 {
758 	int     error;
759 
760 	switch (cmd) {
761 	    case GM_GRFON:
762 		error = cl_load_mon(gp,
763 		    (struct grfcltext_mode *) monitor_current) ? 0 : EINVAL;
764 		return (error);
765 
766 	    case GM_GRFOFF:
767 #ifndef CL5426CONSOLE
768 		cl_off(gp);
769 #else
770 		cl_load_mon(gp, &clconsole_mode);
771 #endif
772 		return (0);
773 
774 	    case GM_GRFCONFIG:
775 		return (0);
776 
777 	    case GM_GRFGETVMODE:
778 		return (cl_getvmode(gp, (struct grfvideo_mode *) arg));
779 
780 	    case GM_GRFSETVMODE:
781 		error = cl_setvmode(gp, *(unsigned *) arg);
782 		if (!error && (gp->g_flags & GF_GRFON))
783 			cl_load_mon(gp,
784 			    (struct grfcltext_mode *) monitor_current);
785 		return (error);
786 
787 	    case GM_GRFGETNUMVM:
788 		*(int *) arg = monitor_def_max;
789 		return (0);
790 
791 	    case GM_GRFIOCTL:
792 		return (cl_ioctl(gp, a2, arg));
793 
794 	    default:
795 		break;
796 	}
797 
798 	return (EPASSTHROUGH);
799 }
800 
801 int
cl_ioctl(register struct grf_softc * gp,u_long cmd,void * data)802 cl_ioctl(register struct grf_softc *gp, u_long cmd, void *data)
803 {
804 	switch (cmd) {
805 	    case GRFIOCGSPRITEPOS:
806 		return (cl_getmousepos(gp, (struct grf_position *) data));
807 
808 	    case GRFIOCSSPRITEPOS:
809 		return (cl_setmousepos(gp, (struct grf_position *) data));
810 
811 	    case GRFIOCSSPRITEINF:
812 		return (cl_setspriteinfo(gp, (struct grf_spriteinfo *) data));
813 
814 	    case GRFIOCGSPRITEINF:
815 		return (cl_getspriteinfo(gp, (struct grf_spriteinfo *) data));
816 
817 	    case GRFIOCGSPRITEMAX:
818 		return (cl_getspritemax(gp, (struct grf_position *) data));
819 
820 	    case GRFIOCGETCMAP:
821 		return (cl_getcmap(gp, (struct grf_colormap *) data));
822 
823 	    case GRFIOCPUTCMAP:
824 		return (cl_putcmap(gp, (struct grf_colormap *) data));
825 
826 	    case GRFIOCBITBLT:
827 		break;
828 
829 	    case GRFTOGGLE:
830 		return (cl_toggle(gp, 0));
831 
832 	    case GRFIOCSETMON:
833 		return (cl_setmonitor(gp, (struct grfvideo_mode *) data));
834 
835             case GRFIOCBLANK:
836                 return (cl_blank(gp, *(int *)data));
837 
838 	}
839 	return (EPASSTHROUGH);
840 }
841 
842 int
cl_getmousepos(struct grf_softc * gp,struct grf_position * data)843 cl_getmousepos(struct grf_softc *gp, struct grf_position *data)
844 {
845 	data->x = cl_cursprite.pos.x;
846 	data->y = cl_cursprite.pos.y;
847 	return (0);
848 }
849 
850 void
cl_writesprpos(volatile char * ba,short x,short y)851 cl_writesprpos(volatile char *ba, short x, short y)
852 {
853 	/* we want to use a 16-bit write to 3c4 so no macros used */
854 	volatile unsigned char *cwp;
855         volatile unsigned short *wp;
856 
857 	cwp = ba + 0x3c4;
858         wp = (volatile unsigned short *)cwp;
859 
860 	/*
861 	 * don't ask me why, but apparently you can't do a 16-bit write with
862 	 * x-position like with y-position below (dagge)
863 	 */
864         cwp[0] = 0x10 | ((x << 5) & 0xff);
865         cwp[1] = (x >> 3) & 0xff;
866 
867         *wp = 0x1100 | ((y & 7) << 13) | ((y >> 3) & 0xff);
868 }
869 
870 void
writeshifted(volatile char * to,signed char shiftx,signed char shifty)871 writeshifted(volatile char *to, signed char shiftx, signed char shifty)
872 {
873 	int y;
874 	unsigned long long *tptr, *iptr, *mptr, line;
875 
876 	tptr = (unsigned long long *) __UNVOLATILE(to);
877         iptr = (unsigned long long *) cl_cursprite.image;
878         mptr = (unsigned long long *) cl_cursprite.mask;
879 
880         shiftx = shiftx < 0 ? 0 : shiftx;
881         shifty = shifty < 0 ? 0 : shifty;
882 
883         /* start reading shifty lines down, and
884          * shift each line in by shiftx
885          */
886         for (y = shifty; y < 64; y++) {
887 
888                 /* image */
889                 line = iptr[y];
890 		*tptr++ = line << shiftx;
891 
892                 /* mask */
893                 line = mptr[y];
894 		*tptr++ = line << shiftx;
895 	}
896 
897         /* clear the remainder */
898         for (y = shifty; y > 0; y--) {
899                 *tptr++ = 0;
900                 *tptr++ = 0;
901         }
902 }
903 
904 int
cl_setmousepos(struct grf_softc * gp,struct grf_position * data)905 cl_setmousepos(struct grf_softc *gp, struct grf_position *data)
906 {
907 	volatile char *ba = gp->g_regkva;
908         short rx, ry;
909 #ifdef CL_SHIFTSPRITE
910 	short prx, pry;
911 	volatile char *fb = gp->g_fbkva;
912         volatile char *sprite = fb + (cl_fbsize - 1024);
913 #endif
914 
915         /* no movement */
916 	if (cl_cursprite.pos.x == data->x && cl_cursprite.pos.y == data->y)
917 		return (0);
918 
919         /* current and previous real coordinates */
920 	rx = data->x - cl_cursprite.hot.x;
921 	ry = data->y - cl_cursprite.hot.y;
922 
923         /*
924 	 * if we are/were on an edge, create (un)shifted bitmap --
925          * ripped out optimization (not extremely worthwhile,
926          * and kind of buggy anyhow).
927          */
928 #ifdef CL_SHIFTSPRITE
929 	prx = cl_cursprite.pos.x - cl_cursprite.hot.x;
930 	pry = cl_cursprite.pos.y - cl_cursprite.hot.y;
931         if (rx < 0 || ry < 0 || prx < 0 || pry < 0) {
932                 writeshifted(sprite, rx < 0 ? -rx : 0, ry < 0 ? -ry : 0);
933         }
934 #endif
935 
936         /* do movement, save position */
937         cl_writesprpos(ba, rx < 0 ? 0 : rx, ry < 0 ? 0 : ry);
938 	cl_cursprite.pos.x = data->x;
939 	cl_cursprite.pos.y = data->y;
940 
941 	return (0);
942 }
943 
944 int
cl_getspriteinfo(struct grf_softc * gp,struct grf_spriteinfo * data)945 cl_getspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *data)
946 {
947 	copyout(&cl_cursprite, data, sizeof(struct grf_spriteinfo));
948 	copyout(cl_cursprite.image, data->image, 64 * 8);
949 	copyout(cl_cursprite.mask, data->mask, 64 * 8);
950 	return (0);
951 }
952 
953 static int
cl_setspriteinfo(struct grf_softc * gp,struct grf_spriteinfo * data)954 cl_setspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *data)
955 {
956 	volatile unsigned char *ba = gp->g_regkva, *fb = gp->g_fbkva;
957         volatile char *sprite = fb + (cl_fbsize - 1024);
958 
959 	if (data->set & GRFSPRSET_SHAPE) {
960 
961                 unsigned short dsx, dsy, i;
962                 unsigned long *di, *dm, *si, *sm;
963                 unsigned long ssi[128], ssm[128];
964                 struct grf_position gpos;
965 
966 
967                 /* check for a too large sprite (no clipping!) */
968                 dsy = data->size.y;
969                 dsx = data->size.x;
970                 if (dsy > 64 || dsx > 64)
971                         return(EINVAL);
972 
973                 /* prepare destination */
974                 di = (unsigned long *)cl_cursprite.image;
975                 dm = (unsigned long *)cl_cursprite.mask;
976                 cl_memset((unsigned char *)di, 0, 8*64);
977                 cl_memset((unsigned char *)dm, 0, 8*64);
978 
979                 /* two alternatives:  64 across, then it's
980                  * the same format we use, just copy.  Otherwise,
981                  * copy into tmp buf and recopy skipping the
982                  * unused 32 bits.
983                  */
984                 if ((dsx - 1) / 32) {
985                         copyin(data->image, di, 8 * dsy);
986                         copyin(data->mask, dm, 8 * dsy);
987                 } else {
988                         si = ssi; sm = ssm;
989                         copyin(data->image, si, 4 * dsy);
990                         copyin(data->mask, sm, 4 * dsy);
991                         for (i = 0; i < dsy; i++) {
992                                 *di = *si++;
993                                 *dm = *sm++;
994                                 di += 2;
995                                 dm += 2;
996                         }
997                 }
998 
999                 /* set size */
1000 		cl_cursprite.size.x = data->size.x;
1001 		cl_cursprite.size.y = data->size.y;
1002 
1003                 /* forcably load into board */
1004                 gpos.x = cl_cursprite.pos.x;
1005                 gpos.y = cl_cursprite.pos.y;
1006                 cl_cursprite.pos.x = -1;
1007                 cl_cursprite.pos.y = -1;
1008                 writeshifted(sprite, 0, 0);
1009                 cl_setmousepos(gp, &gpos);
1010 
1011 	}
1012 	if (data->set & GRFSPRSET_HOT) {
1013 
1014 		cl_cursprite.hot = data->hot;
1015 
1016 	}
1017 	if (data->set & GRFSPRSET_CMAP) {
1018 
1019 		u_char  red[2], green[2], blue[2];
1020 
1021 		copyin(data->cmap.red, red, 2);
1022 		copyin(data->cmap.green, green, 2);
1023 		copyin(data->cmap.blue, blue, 2);
1024 		memcpy(cl_cursprite.cmap.red, red, 2);
1025 		memcpy(cl_cursprite.cmap.green, green, 2);
1026 		memcpy(cl_cursprite.cmap.blue, blue, 2);
1027 
1028                 /* enable and load colors 256 & 257 */
1029 		WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x06);
1030 
1031                 /* 256 */
1032 		vgaw(ba, VDAC_ADDRESS_W, 0x00);
1033 		if (cltype == PICASSO) {
1034 			vgaw(ba, VDAC_DATA, (u_char) (red[0] >> 2));
1035 			vgaw(ba, VDAC_DATA, (u_char) (green[0] >> 2));
1036 			vgaw(ba, VDAC_DATA, (u_char) (blue[0] >> 2));
1037 		} else {
1038 			vgaw(ba, VDAC_DATA, (u_char) (blue[0] >> 2));
1039 			vgaw(ba, VDAC_DATA, (u_char) (green[0] >> 2));
1040 			vgaw(ba, VDAC_DATA, (u_char) (red[0] >> 2));
1041 		}
1042 
1043                 /* 257 */
1044 		vgaw(ba, VDAC_ADDRESS_W, 0x0f);
1045 		if (cltype == PICASSO) {
1046 			vgaw(ba, VDAC_DATA, (u_char) (red[1] >> 2));
1047 			vgaw(ba, VDAC_DATA, (u_char) (green[1] >> 2));
1048 			vgaw(ba, VDAC_DATA, (u_char) (blue[1] >> 2));
1049 		} else {
1050 			vgaw(ba, VDAC_DATA, (u_char) (blue[1] >> 2));
1051 			vgaw(ba, VDAC_DATA, (u_char) (green[1] >> 2));
1052 			vgaw(ba, VDAC_DATA, (u_char) (red[1] >> 2));
1053 		}
1054 
1055                 /* turn on/off sprite */
1056 		if (cl_cursprite.enable) {
1057 			WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x05);
1058 		} else {
1059 			WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x04);
1060 		}
1061 
1062 	}
1063 	if (data->set & GRFSPRSET_ENABLE) {
1064 
1065 		if (data->enable == 1) {
1066 			WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x05);
1067 			cl_cursprite.enable = 1;
1068 		} else {
1069 			WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x04);
1070 			cl_cursprite.enable = 0;
1071 		}
1072 
1073 	}
1074 	if (data->set & GRFSPRSET_POS) {
1075 
1076                 /* force placement */
1077                 cl_cursprite.pos.x = -1;
1078                 cl_cursprite.pos.y = -1;
1079 
1080                 /* do it */
1081                 cl_setmousepos(gp, &data->pos);
1082 
1083 	}
1084 	return (0);
1085 }
1086 
1087 static int
cl_getspritemax(struct grf_softc * gp,struct grf_position * data)1088 cl_getspritemax(struct grf_softc *gp, struct grf_position *data)
1089 {
1090 	if (gp->g_display.gd_planes == 24)
1091 		return (EINVAL);
1092 	data->x = 64;
1093 	data->y = 64;
1094 	return (0);
1095 }
1096 
1097 int
cl_setmonitor(struct grf_softc * gp,struct grfvideo_mode * gv)1098 cl_setmonitor(struct grf_softc *gp, struct grfvideo_mode *gv)
1099 {
1100 	struct grfvideo_mode *md;
1101 
1102         if (!cl_mondefok(gv))
1103                 return(EINVAL);
1104 
1105 #ifdef CL5426CONSOLE
1106 	/* handle interactive setting of console mode */
1107 	if (gv->mode_num == 255) {
1108 		memcpy(&clconsole_mode.gv, gv, sizeof(struct grfvideo_mode));
1109 		clconsole_mode.gv.hblank_start /= 8;
1110 		clconsole_mode.gv.hsync_start /= 8;
1111 		clconsole_mode.gv.hsync_stop /= 8;
1112 		clconsole_mode.gv.htotal /= 8;
1113 		clconsole_mode.rows = gv->disp_height / clconsole_mode.fy;
1114 		clconsole_mode.cols = gv->disp_width / clconsole_mode.fx;
1115 		if (!(gp->g_flags & GF_GRFON))
1116 			cl_load_mon(gp, &clconsole_mode);
1117 #if NITE > 0
1118 		ite_reinit(gp->g_itedev);
1119 #endif
1120 		return (0);
1121 	}
1122 #endif
1123 
1124 	md = monitor_def + (gv->mode_num - 1);
1125 	memcpy(md, gv, sizeof(struct grfvideo_mode));
1126 
1127 	/* adjust pixel oriented values to internal rep. */
1128 
1129 	md->hblank_start /= 8;
1130 	md->hsync_start /= 8;
1131 	md->hsync_stop /= 8;
1132 	md->htotal /= 8;
1133 
1134 	return (0);
1135 }
1136 
1137 int
cl_getcmap(struct grf_softc * gfp,struct grf_colormap * cmap)1138 cl_getcmap(struct grf_softc *gfp, struct grf_colormap *cmap)
1139 {
1140 	volatile unsigned char *ba;
1141 	u_char  red[256], green[256], blue[256], *rp, *gp, *bp;
1142 	short   x;
1143 	int     error;
1144 
1145 	if (cmap->count == 0 || cmap->index >= 256)
1146 		return 0;
1147 
1148 	if (cmap->count > 256 - cmap->index)
1149 		cmap->count = 256 - cmap->index;
1150 
1151 	ba = gfp->g_regkva;
1152 	/* first read colors out of the chip, then copyout to userspace */
1153 	vgaw(ba, VDAC_ADDRESS_R, cmap->index);
1154 	x = cmap->count - 1;
1155 
1156 /*
1157  * Some sort 'o Magic. Spectrum has some changes on the board to speed
1158  * up 15 and 16Bit modes. They can access these modes with easy-to-program
1159  * rgbrgbrgb instead of rrrgggbbb. Side effect: when in 8Bit mode, rgb
1160  * is swapped to bgr. I wonder if we need to check for 8Bit though, ill
1161  */
1162 
1163 /*
1164  * The source for the above comment is somewhat unknown to me.
1165  * The Spectrum, Piccolo and PiccoloSD64 have the analog Red and Blue
1166  * lines swapped. In 24BPP this provides RGB instead of BGR as it would
1167  * be native to the chipset. This requires special programming for the
1168  * CLUT in 8BPP to compensate and avoid false colors.
1169  * I didn't find any special stuff for 15 and 16BPP though, crest.
1170  */
1171 
1172 	switch (cltype) {
1173 	    case SPECTRUM:
1174 	    case PICCOLO:
1175 		rp = blue + cmap->index;
1176 		gp = green + cmap->index;
1177 		bp = red + cmap->index;
1178 		break;
1179 	    case PICASSO:
1180 		rp = red + cmap->index;
1181 		gp = green + cmap->index;
1182 		bp = blue + cmap->index;
1183 		break;
1184 	    default:
1185 		rp = gp = bp = 0;
1186 		break;
1187 	}
1188 
1189 	do {
1190 		*rp++ = vgar(ba, VDAC_DATA) << 2;
1191 		*gp++ = vgar(ba, VDAC_DATA) << 2;
1192 		*bp++ = vgar(ba, VDAC_DATA) << 2;
1193 	} while (x-- > 0);
1194 
1195 	if (!(error = copyout(red + cmap->index, cmap->red, cmap->count))
1196 	    && !(error = copyout(green + cmap->index, cmap->green, cmap->count))
1197 	    && !(error = copyout(blue + cmap->index, cmap->blue, cmap->count)))
1198 		return (0);
1199 
1200 	return (error);
1201 }
1202 
1203 int
cl_putcmap(struct grf_softc * gfp,struct grf_colormap * cmap)1204 cl_putcmap(struct grf_softc *gfp, struct grf_colormap *cmap)
1205 {
1206 	volatile unsigned char *ba;
1207 	u_char  red[256], green[256], blue[256], *rp, *gp, *bp;
1208 	short   x;
1209 	int     error;
1210 
1211 	if (cmap->count == 0 || cmap->index >= 256)
1212 		return (0);
1213 
1214 	if (cmap->count > 256 - cmap->index)
1215 		cmap->count = 256 - cmap->index;
1216 
1217 	/* first copy the colors into kernelspace */
1218 	if (!(error = copyin(cmap->red, red + cmap->index, cmap->count))
1219 	    && !(error = copyin(cmap->green, green + cmap->index, cmap->count))
1220 	    && !(error = copyin(cmap->blue, blue + cmap->index, cmap->count))) {
1221 		ba = gfp->g_regkva;
1222 		vgaw(ba, VDAC_ADDRESS_W, cmap->index);
1223 		x = cmap->count - 1;
1224 
1225 		switch (cltype) {
1226 		    case SPECTRUM:
1227 		    case PICCOLO:
1228 			rp = blue + cmap->index;
1229 			gp = green + cmap->index;
1230 			bp = red + cmap->index;
1231 			break;
1232 		    case PICASSO:
1233 			rp = red + cmap->index;
1234 			gp = green + cmap->index;
1235 			bp = blue + cmap->index;
1236 			break;
1237 		    default:
1238 			rp = gp = bp = 0;
1239 			break;
1240 		}
1241 
1242 		do {
1243 			vgaw(ba, VDAC_DATA, *rp++ >> 2);
1244 			vgaw(ba, VDAC_DATA, *gp++ >> 2);
1245 			vgaw(ba, VDAC_DATA, *bp++ >> 2);
1246 		} while (x-- > 0);
1247 		return (0);
1248 	} else
1249 		return (error);
1250 }
1251 
1252 
1253 int
cl_toggle(struct grf_softc * gp,unsigned short wopp)1254 cl_toggle(struct grf_softc *gp, unsigned short wopp)
1255 	/* wopp:	 don't need that one yet, ill */
1256 {
1257 	volatile void *ba;
1258 
1259 	ba = gp->g_regkva;
1260 
1261 	if (cl_pass_toggle) {
1262 		RegOffpass(ba);
1263 	} else {
1264 		RegOnpass(ba);
1265 	}
1266 	return (0);
1267 }
1268 
1269 static void
cl_CompFQ(u_int fq,u_char * num,u_char * denom,u_char * clkdoub)1270 cl_CompFQ(u_int fq, u_char *num, u_char *denom, u_char *clkdoub)
1271 {
1272 #define OSC     14318180
1273 /* OK, here's what we're doing here:
1274  *
1275  *             OSC * NUMERATOR
1276  *      VCLK = -------------------  Hz
1277  *             DENOMINATOR * (1+P)
1278  *
1279  * so we're given VCLK and we should give out some useful
1280  * values....
1281  *
1282  * NUMERATOR is 7 bits wide
1283  * DENOMINATOR is 5 bits wide with bit P in the same char as bit 0.
1284  *
1285  * We run through all the possible combinations and
1286  * return the values which deviate the least from the chosen frequency.
1287  *
1288  */
1289 #define OSC     14318180
1290 #define count(n,d,p)    ((OSC * n)/(d * (1+p)))
1291 
1292 	unsigned char n, d, p, minn, mind, minp = 0;
1293 	unsigned long err, minerr;
1294 
1295 /*
1296 numer = 0x00 - 0x7f
1297 denom = 0x00 - 0x1f (1) 0x20 - 0x3e (even)
1298 */
1299 
1300 	/* find lowest error in 6144 iterations. */
1301 	minerr = fq;
1302 	minn = 0;
1303 	mind = 0;
1304 	p = 0;
1305 
1306 	if ((cl_64bit == 1) && (fq >= 86000000))
1307 	{
1308 		for (d = 1; d < 0x20; d++) {
1309 			for (n = 1; n < 0x80; n++) {
1310 				err = abs(count(n, d, 0) - fq);
1311 				if (err < minerr) {
1312 					minerr = err;
1313 					minn = n;
1314 					mind = d;
1315 					minp = 1;
1316 				}
1317 			}
1318 		}
1319 		*clkdoub = 1;
1320 	}
1321 	else {
1322 		for (d = 1; d < 0x20; d++) {
1323 			for (n = 1; n < 0x80; n++) {
1324 				err = abs(count(n, d, p) - fq);
1325 				if (err < minerr) {
1326 					minerr = err;
1327 					minn = n;
1328 					mind = d;
1329 					minp = p;
1330 				}
1331 			}
1332 			if (d == 0x1f && p == 0) {
1333 				p = 1;
1334 				d = 0x0f;
1335 			}
1336 		}
1337 		*clkdoub = 0;
1338 	}
1339 
1340 	*num = minn;
1341 	*denom = (mind << 1) | minp;
1342 	if (minerr > 500000)
1343 		printf("Warning: CompFQ minimum error = %ld\n", minerr);
1344 	return;
1345 }
1346 
1347 int
cl_mondefok(struct grfvideo_mode * gv)1348 cl_mondefok(struct grfvideo_mode *gv)
1349 {
1350         unsigned long maxpix;
1351 
1352 	if (gv->mode_num < 1 || gv->mode_num > monitor_def_max)
1353                 if (gv->mode_num != 255 || gv->depth != 4)
1354                         return(0);
1355 
1356 	switch (gv->depth) {
1357 	    case 4:
1358                 if (gv->mode_num != 255)
1359                         return(0);
1360 	    case 1:
1361 	    case 8:
1362 		maxpix = cl_maxpixelclock;
1363 		if (cl_64bit == 1)
1364 		{
1365 			if (cltype == PICASSO) /* Picasso IV */
1366 				maxpix = 135000000;
1367 			else                   /* Piccolo SD64 */
1368 				maxpix = 110000000;
1369 		}
1370                 break;
1371 	    case 15:
1372 	    case 16:
1373 		if (cl_64bit == 1)
1374 	                maxpix = 85000000;
1375 		else
1376 	                maxpix = cl_maxpixelclock - (cl_maxpixelclock / 3);
1377                 break;
1378 	    case 24:
1379 		if ((cltype == PICASSO) && (cl_64bit == 1))
1380 	                maxpix = 85000000;
1381 		else
1382 	                maxpix = cl_maxpixelclock / 3;
1383                 break;
1384 	    case 32:
1385 		if ((cltype == PICCOLO) && (cl_64bit == 1))
1386 	                maxpix = 50000000;
1387 		else
1388 	                maxpix = 0;
1389                 break;
1390 	default:
1391 		printf("grfcl: Illegal depth in mode %d\n",
1392 			(int) gv->mode_num);
1393 		return (0);
1394 	}
1395 
1396         if (gv->pixel_clock > maxpix) {
1397 		printf("grfcl: Pixelclock too high in mode %d\n",
1398 			(int) gv->mode_num);
1399                 return (0);
1400 	}
1401 
1402 	if (gv->disp_flags & GRF_FLAGS_SYNC_ON_GREEN) {
1403 		printf("grfcl: sync-on-green is not supported\n");
1404 		return (0);
1405 	}
1406 
1407         return (1);
1408 }
1409 
1410 int
cl_load_mon(struct grf_softc * gp,struct grfcltext_mode * md)1411 cl_load_mon(struct grf_softc *gp, struct grfcltext_mode *md)
1412 {
1413 	struct grfvideo_mode *gv;
1414 	struct grfinfo *gi;
1415 	volatile void *ba, *fb;
1416 	unsigned char num0, denom0, clkdoub;
1417 	unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS,
1418 	        VSE, VT;
1419 	int	clkmul, clkmode;
1420 	int	vmul;
1421 	int	sr15;
1422 	unsigned char hvsync_pulse;
1423 	char    TEXT;
1424 
1425 	/* identity */
1426 	gv = &md->gv;
1427 	TEXT = (gv->depth == 4);
1428 
1429 	if (!cl_mondefok(gv)) {
1430 		printf("grfcl: Monitor definition not ok\n");
1431 		return (0);
1432 	}
1433 
1434 	ba = gp->g_regkva;
1435 	fb = gp->g_fbkva;
1436 
1437 	/* provide all needed information in grf device-independent locations */
1438 	gp->g_data = (void *) gv;
1439 	gi = &gp->g_display;
1440 	gi->gd_regaddr = (void *) kvtop(__UNVOLATILE(ba));
1441 	gi->gd_regsize = 64 * 1024;
1442 	gi->gd_fbaddr = (void *) kvtop(__UNVOLATILE(fb));
1443 	gi->gd_fbsize = cl_fbsize;
1444 	gi->gd_colors = 1 << gv->depth;
1445 	gi->gd_planes = gv->depth;
1446 	gi->gd_fbwidth = gv->disp_width;
1447 	gi->gd_fbheight = gv->disp_height;
1448 	gi->gd_fbx = 0;
1449 	gi->gd_fby = 0;
1450 	if (TEXT) {
1451 		gi->gd_dwidth = md->fx * md->cols;
1452 		gi->gd_dheight = md->fy * md->rows;
1453 	} else {
1454 		gi->gd_dwidth = gv->disp_width;
1455 		gi->gd_dheight = gv->disp_height;
1456 	}
1457 	gi->gd_dx = 0;
1458 	gi->gd_dy = 0;
1459 
1460 	/* get display mode parameters */
1461 
1462 	HBS = gv->hblank_start;
1463 	HSS = gv->hsync_start;
1464 	HSE = gv->hsync_stop;
1465 	HBE = gv->htotal - 1;
1466 	HT = gv->htotal;
1467 	VBS = gv->vblank_start;
1468 	VSS = gv->vsync_start;
1469 	VSE = gv->vsync_stop;
1470 	VBE = gv->vtotal - 1;
1471 	VT = gv->vtotal;
1472 
1473 	if (TEXT)
1474 		HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1;
1475 	else
1476 		HDE = (gv->disp_width + 3) / 8 - 1;	/* HBS; */
1477 	VDE = gv->disp_height - 1;
1478 
1479 	/* adjustments */
1480 	switch (gv->depth) {
1481 	    case 8:
1482 		clkmul = 1;
1483 		clkmode = 0x0;
1484 		break;
1485 	    case 15:
1486 	    case 16:
1487 		clkmul = 1;
1488 		clkmode = 0x6;
1489 		break;
1490 	    case 24:
1491 		if ((cltype == PICASSO) && (cl_64bit == 1))	/* Picasso IV */
1492 			clkmul = 1;
1493 		else
1494 			clkmul = 3;
1495 		clkmode = 0x4;
1496 		break;
1497 	    case 32:
1498 		clkmul = 1;
1499 		clkmode = 0x8;
1500 		break;
1501 	    default:
1502 		clkmul = 1;
1503 		clkmode = 0x0;
1504 		break;
1505 	}
1506 
1507 	if ((VT > 1023) && (!(gv->disp_flags & GRF_FLAGS_LACE))) {
1508 		WCrt(ba, CRT_ID_MODE_CONTROL, 0xe7);
1509 	} else
1510 		WCrt(ba, CRT_ID_MODE_CONTROL, 0xe3);
1511 
1512 	vmul = 2;
1513 	if ((VT > 1023) || (gv->disp_flags & GRF_FLAGS_LACE))
1514 		vmul = 1;
1515 	if (gv->disp_flags & GRF_FLAGS_DBLSCAN)
1516 		vmul = 4;
1517 
1518 	VDE = VDE * vmul / 2;
1519 	VBS = VBS * vmul / 2;
1520 	VSS = VSS * vmul / 2;
1521 	VSE = VSE * vmul / 2;
1522 	VBE = VBE * vmul / 2;
1523 	VT  = VT * vmul / 2;
1524 
1525 	WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e);
1526 	if (cl_64bit == 1) {
1527 	    if (TEXT || (gv->depth == 1))
1528 		sr15 = 0xd0;
1529 	    else
1530 		sr15 = ((cl_fbsize / 0x100000 == 2) ? 0x38 : 0xb8);
1531 	    WSeq(ba, SEQ_ID_CONF_RBACK, 0x00);
1532 	} else {
1533 		sr15 = (TEXT || (gv->depth == 1)) ? 0xd0 : 0xb0;
1534 		sr15 &= ((cl_fbsize / 0x100000) == 2) ? 0xff : 0x7f;
1535 	}
1536 	WSeq(ba, SEQ_ID_DRAM_CNTL, sr15);
1537 	WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
1538 	WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff);
1539 	WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
1540 
1541 	/* Set clock */
1542 
1543 	cl_CompFQ(gv->pixel_clock * clkmul, &num0, &denom0, &clkdoub);
1544 
1545 	/* Horizontal/Vertical Sync Pulse */
1546 	hvsync_pulse = vgar(ba, GREG_MISC_OUTPUT_R);
1547 	if (gv->disp_flags & GRF_FLAGS_PHSYNC)
1548 		hvsync_pulse &= ~0x40;
1549 	else
1550 		hvsync_pulse |= 0x40;
1551 	if (gv->disp_flags & GRF_FLAGS_PVSYNC)
1552 		hvsync_pulse &= ~0x80;
1553 	else
1554 		hvsync_pulse |= 0x80;
1555 	vgaw(ba, GREG_MISC_OUTPUT_W, hvsync_pulse);
1556 
1557 	if (clkdoub) {
1558 		HDE /= 2;
1559 		HBS /= 2;
1560 		HSS /= 2;
1561 		HSE /= 2;
1562 		HBE /= 2;
1563 		HT  /= 2;
1564 		clkmode = 0x6;
1565 	}
1566 
1567 	WSeq(ba, SEQ_ID_VCLK_3_NUM, num0);
1568 	WSeq(ba, SEQ_ID_VCLK_3_DENOM, denom0);
1569 
1570 	/* load display parameters into board */
1571 
1572 	WCrt(ba, CRT_ID_HOR_TOTAL, HT);
1573 	WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? HBS - 1 : HDE));
1574 	WCrt(ba, CRT_ID_START_HOR_BLANK, HBS);
1575 	WCrt(ba, CRT_ID_END_HOR_BLANK, (HBE & 0x1f) | 0x80);	/* | 0x80? */
1576 	WCrt(ba, CRT_ID_START_HOR_RETR, HSS);
1577 	WCrt(ba, CRT_ID_END_HOR_RETR,
1578 	    (HSE & 0x1f) |
1579 	    ((HBE & 0x20) ? 0x80 : 0x00));
1580 	WCrt(ba, CRT_ID_VER_TOTAL, VT);
1581 	WCrt(ba, CRT_ID_OVERFLOW,
1582 	    0x10 |
1583 	    ((VT & 0x100) ? 0x01 : 0x00) |
1584 	    ((VDE & 0x100) ? 0x02 : 0x00) |
1585 	    ((VSS & 0x100) ? 0x04 : 0x00) |
1586 	    ((VBS & 0x100) ? 0x08 : 0x00) |
1587 	    ((VT & 0x200) ? 0x20 : 0x00) |
1588 	    ((VDE & 0x200) ? 0x40 : 0x00) |
1589 	    ((VSS & 0x200) ? 0x80 : 0x00));
1590 
1591 	WCrt(ba, CRT_ID_CHAR_HEIGHT,
1592 	    0x40 |		/* TEXT ? 0x00 ??? */
1593 	    ((gv->disp_flags & GRF_FLAGS_DBLSCAN) ? 0x80 : 0x00) |
1594 	    ((VBS & 0x200) ? 0x20 : 0x00) |
1595 	    (TEXT ? ((md->fy - 1) & 0x1f) : 0x00));
1596 
1597 	/* text cursor */
1598 
1599 	if (TEXT) {
1600 #if CL_ULCURSOR
1601 		WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2);
1602 		WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1);
1603 #else
1604 		WCrt(ba, CRT_ID_CURSOR_START, 0x00);
1605 		WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f);
1606 #endif
1607 		WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->fy - 1) & 0x1f);
1608 
1609 		WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
1610 		WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
1611 	}
1612 	WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
1613 	WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
1614 
1615 	WCrt(ba, CRT_ID_START_VER_RETR, VSS);
1616 	WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f) | 0x20);
1617 	WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE);
1618 	WCrt(ba, CRT_ID_START_VER_BLANK, VBS);
1619 	WCrt(ba, CRT_ID_END_VER_BLANK, VBE);
1620 
1621 	WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
1622 	WCrt(ba, CRT_ID_LACE_END, HT / 2);	/* MW/16 */
1623 	WCrt(ba, CRT_ID_LACE_CNTL,
1624 	    ((gv->disp_flags & GRF_FLAGS_LACE) ? 0x01 : 0x00) |
1625 	    ((HBE & 0x40) ? 0x10 : 0x00) |
1626 	    ((HBE & 0x80) ? 0x20 : 0x00) |
1627 	    ((VBE & 0x100) ? 0x40 : 0x00) |
1628 	    ((VBE & 0x200) ? 0x80 : 0x00));
1629 
1630 	WGfx(ba, GCT_ID_GRAPHICS_MODE,
1631 	    ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40));
1632 	WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
1633 
1634 	WSeq(ba, SEQ_ID_EXT_SEQ_MODE,
1635 	    ((TEXT || (gv->depth == 1)) ? 0x00 : 0x01) |
1636 	    ((cltype == PICASSO) ? 0x20 : 0x80) | clkmode);
1637 
1638 	/* write 0x00 to VDAC_MASK before accessing HDR this helps
1639 	   sometimes, out of "secret" application note (crest) */
1640 	vgaw(ba, VDAC_MASK, 0);
1641 	/* reset HDR "magic" access counter (crest) */
1642 	vgar(ba, VDAC_ADDRESS);
1643 
1644 	delay(200000);
1645 	vgar(ba, VDAC_MASK);
1646 	delay(200000);
1647 	vgar(ba, VDAC_MASK);
1648 	delay(200000);
1649 	vgar(ba, VDAC_MASK);
1650 	delay(200000);
1651 	vgar(ba, VDAC_MASK);
1652 	delay(200000);
1653 	switch (gv->depth) {
1654 	    case 1:
1655 	    case 4:		/* text */
1656 		vgaw(ba, VDAC_MASK, 0);
1657 		HDE = gv->disp_width / 16;
1658 		break;
1659 	    case 8:
1660 		if (clkdoub)
1661 			vgaw(ba, VDAC_MASK, 0x4a); /* Clockdouble Magic */
1662 		else
1663 			vgaw(ba, VDAC_MASK, 0);
1664 		HDE = gv->disp_width / 8;
1665 		break;
1666 	    case 15:
1667 		vgaw(ba, VDAC_MASK, 0xd0);
1668 		HDE = gv->disp_width / 4;
1669 		break;
1670 	    case 16:
1671 		vgaw(ba, VDAC_MASK, 0xc1);
1672 		HDE = gv->disp_width / 4;
1673 		break;
1674 	    case 24:
1675 		vgaw(ba, VDAC_MASK, 0xc5);
1676 		HDE = (gv->disp_width / 8) * 3;
1677 		break;
1678 	    case 32:
1679 		vgaw(ba, VDAC_MASK, 0xc5);
1680 		HDE = (gv->disp_width / 4);
1681 		break;
1682 	}
1683 
1684 	/* reset HDR "magic" access counter (crest) */
1685 	vgar(ba, VDAC_ADDRESS);
1686 	/* then enable all bit in VDAC_MASK afterwards (crest) */
1687 	vgaw(ba, VDAC_MASK, 0xff);
1688 
1689 	WCrt(ba, CRT_ID_OFFSET, HDE);
1690 	if (cl_64bit == 1) {
1691 		WCrt(ba, CRT_ID_SYNC_ADJ_GENLOCK, 0x00);
1692 		WCrt(ba, CRT_ID_OVERLAY_EXT_CTRL_REG, 0x40);
1693 	}
1694 	WCrt(ba, CRT_ID_EXT_DISP_CNTL,
1695 	    ((TEXT && gv->pixel_clock > 29000000) ? 0x40 : 0x00) |
1696 	    0x22 |
1697 	    ((HDE > 0xff) ? 0x10 : 0x00));
1698 
1699 	WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x0a : 0x01));
1700 	WAttr(ba, 0x20 | ACT_ID_COLOR_PLANE_ENA,
1701 	    (gv->depth == 1) ? 0x01 : 0x0f);
1702 
1703 	/* text initialization */
1704 
1705 	if (TEXT) {
1706 		cl_inittextmode(gp);
1707 	}
1708 	WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x14);
1709 	WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01);
1710 	cl_blanked = 0;
1711 
1712 	/* Pass-through */
1713 
1714 	RegOffpass(ba);
1715 
1716 	return (1);
1717 }
1718 
1719 void
cl_inittextmode(struct grf_softc * gp)1720 cl_inittextmode(struct grf_softc *gp)
1721 {
1722 	struct grfcltext_mode *tm = (struct grfcltext_mode *) gp->g_data;
1723 	volatile unsigned char *ba = gp->g_regkva;
1724 	unsigned char *fb = __UNVOLATILE(gp->g_fbkva);
1725 	unsigned char *c, *f, y;
1726 	unsigned short z;
1727 
1728 
1729 	/* load text font into beginning of display memory. Each character
1730 	 * cell is 32 bytes long (enough for 4 planes) */
1731 
1732 	SetTextPlane(ba, 0x02);
1733         cl_memset(fb, 0, 256 * 32);
1734 	c = (unsigned char *) (fb) + (32 * tm->fdstart);
1735 	f = tm->fdata;
1736 	for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy))
1737 		for (y = 0; y < tm->fy; y++)
1738 			*c++ = *f++;
1739 
1740 	/* clear out text/attr planes (three screens worth) */
1741 
1742 	SetTextPlane(ba, 0x01);
1743 	cl_memset(fb, 0x07, tm->cols * tm->rows * 3);
1744 	SetTextPlane(ba, 0x00);
1745 	cl_memset(fb, 0x20, tm->cols * tm->rows * 3);
1746 
1747 	/* print out a little init msg */
1748 
1749 	c = (unsigned char *) (fb) + (tm->cols - 16);
1750 	strcpy(c, "CIRRUS");
1751 	c[6] = 0x20;
1752 
1753 	/* set colors (B&W) */
1754 
1755 	vgaw(ba, VDAC_ADDRESS_W, 0);
1756 	for (z = 0; z < 256; z++) {
1757 		unsigned char r, g, b;
1758 
1759 		y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
1760 
1761 		if (cltype == PICASSO) {
1762 			r = clconscolors[y][0];
1763 			g = clconscolors[y][1];
1764 			b = clconscolors[y][2];
1765 		} else {
1766 			b = clconscolors[y][0];
1767 			g = clconscolors[y][1];
1768 			r = clconscolors[y][2];
1769 		}
1770 		vgaw(ba, VDAC_DATA, r >> 2);
1771 		vgaw(ba, VDAC_DATA, g >> 2);
1772 		vgaw(ba, VDAC_DATA, b >> 2);
1773 	}
1774 }
1775 
1776 void
cl_memset(unsigned char * d,unsigned char c,int l)1777 cl_memset(unsigned char *d, unsigned char c, int l)
1778 {
1779 	for (; l > 0; l--)
1780 		*d++ = c;
1781 }
1782 
1783 /*
1784  * Special wakeup/passthrough registers on graphics boards
1785  *
1786  * The methods have diverged a bit for each board, so
1787  * WPass(P) has been converted into a set of specific
1788  * inline functions.
1789  */
1790 static void
RegWakeup(volatile void * ba)1791 RegWakeup(volatile void *ba)
1792 {
1793 
1794 	switch (cltype) {
1795 	    case SPECTRUM:
1796 		vgaw(ba, PASS_ADDRESS_W, 0x1f);
1797 		break;
1798 	    case PICASSO:
1799 		/* Picasso needs no wakeup */
1800 		break;
1801 	    case PICCOLO:
1802 		if (cl_64bit == 1)
1803 			vgaw(ba, PASS_ADDRESS_W, 0x1f);
1804 		else
1805 			vgaw(ba, PASS_ADDRESS_W, vgar(ba, PASS_ADDRESS) | 0x10);
1806 		break;
1807 	}
1808 	delay(200000);
1809 }
1810 
1811 static void
RegOnpass(volatile void * ba)1812 RegOnpass(volatile void *ba)
1813 {
1814 
1815 	switch (cltype) {
1816 	    case SPECTRUM:
1817 		vgaw(ba, PASS_ADDRESS_W, 0x4f);
1818 		break;
1819 	    case PICASSO:
1820 		if (cl_64bit == 0)
1821 			vgaw(ba, PASS_ADDRESS_WP, 0x01);
1822 		break;
1823 	    case PICCOLO:
1824 		if (cl_64bit == 1)
1825 			vgaw(ba, PASS_ADDRESS_W, 0x4f);
1826 		else
1827 			vgaw(ba, PASS_ADDRESS_W, vgar(ba, PASS_ADDRESS) & 0xdf);
1828 		break;
1829 	}
1830 	cl_pass_toggle = 1;
1831 	delay(200000);
1832 }
1833 
1834 static void
RegOffpass(volatile void * ba)1835 RegOffpass(volatile void *ba)
1836 {
1837 
1838 	switch (cltype) {
1839 	    case SPECTRUM:
1840 		vgaw(ba, PASS_ADDRESS_W, 0x6f);
1841 		break;
1842 	    case PICASSO:
1843 		if (cl_64bit == 0)
1844 			vgaw(ba, PASS_ADDRESS_W, 0xff);
1845 		break;
1846 	    case PICCOLO:
1847 		if (cl_64bit == 1)
1848 			vgaw(ba, PASS_ADDRESS_W, 0x6f);
1849 		else
1850 			vgaw(ba, PASS_ADDRESS_W, vgar(ba, PASS_ADDRESS) | 0x20);
1851 		break;
1852 	}
1853 	cl_pass_toggle = 0;
1854 	delay(200000);
1855 }
1856 
1857 #if NWSDISPLAY > 0
1858 static void
cl_wscursor(void * c,int on,int row,int col)1859 cl_wscursor(void *c, int on, int row, int col)
1860 {
1861 	struct rasops_info *ri;
1862 	struct vcons_screen *scr;
1863 	struct grf_softc *gp;
1864 	volatile void *ba;
1865 	int offs;
1866 
1867 	ri = c;
1868 	scr = ri->ri_hw;
1869 	gp = scr->scr_cookie;
1870 	ba = gp->g_regkva;
1871 
1872 	if ((ri->ri_flg & RI_CURSOR) && !on) {
1873 		/* cursor was visible, but we want to remove it */
1874 		/*WCrt(ba, CRT_ID_CURSOR_START, | 0x20);*/
1875 		ri->ri_flg &= ~RI_CURSOR;
1876 	}
1877 
1878 	ri->ri_crow = row;
1879 	ri->ri_ccol = col;
1880 
1881 	if (on) {
1882 		/* move cursor to new location */
1883 		if (!(ri->ri_flg & RI_CURSOR)) {
1884 			/*WCrt(ba, CRT_ID_CURSOR_START, | 0x20);*/
1885 			ri->ri_flg |= RI_CURSOR;
1886 		}
1887 		offs = gp->g_rowoffset[row] + col;
1888 		WCrt(ba, CRT_ID_CURSOR_LOC_LOW, offs & 0xff);
1889 		WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, offs >> 8);
1890 	}
1891 }
1892 
1893 static void
cl_wsputchar(void * c,int row,int col,u_int ch,long attr)1894 cl_wsputchar(void *c, int row, int col, u_int ch, long attr)
1895 {
1896 	struct rasops_info *ri;
1897 	struct vcons_screen *scr;
1898 	struct grf_softc *gp;
1899 	volatile unsigned char *ba, *cp;
1900 
1901 	ri = c;
1902 	scr = ri->ri_hw;
1903 	gp = scr->scr_cookie;
1904 	ba = gp->g_regkva;
1905 	cp = gp->g_fbkva;
1906 
1907 	cp += gp->g_rowoffset[row] + col;
1908 	SetTextPlane(ba, 0x00);
1909 	*cp = ch;
1910 	SetTextPlane(ba, 0x01);
1911 	*cp = attr;
1912 }
1913 
1914 static void
cl_wscopycols(void * c,int row,int srccol,int dstcol,int ncols)1915 cl_wscopycols(void *c, int row, int srccol, int dstcol, int ncols)
1916 {
1917 	volatile unsigned char *ba, *dst, *src;
1918 	struct rasops_info *ri;
1919 	struct vcons_screen *scr;
1920 	struct grf_softc *gp;
1921 	int i;
1922 
1923 	KASSERT(ncols > 0);
1924 	ri = c;
1925 	scr = ri->ri_hw;
1926 	gp = scr->scr_cookie;
1927 	ba = gp->g_regkva;
1928 	src = gp->g_fbkva;
1929 
1930 	src += gp->g_rowoffset[row];
1931 	dst = src;
1932 	src += srccol;
1933 	dst += dstcol;
1934 	if (srccol < dstcol) {
1935 		/* need to copy backwards */
1936 		src += ncols;
1937 		dst += ncols;
1938 		SetTextPlane(ba, 0x00);
1939 		for (i = 0; i < ncols; i++)
1940 			*(--dst) = *(--src);
1941 		src += ncols;
1942 		dst += ncols;
1943 		SetTextPlane(ba, 0x01);
1944 		for (i = 0; i < ncols; i++)
1945 			*(--dst) = *(--src);
1946 	} else {
1947 		SetTextPlane(ba, 0x00);
1948 		for (i = 0; i < ncols; i++)
1949 			*dst++ = *src++;
1950 		src -= ncols;
1951 		dst -= ncols;
1952 		SetTextPlane(ba, 0x01);
1953 		for (i = 0; i < ncols; i++)
1954 			*dst++ = *src++;
1955 	}
1956 }
1957 
1958 static void
cl_wserasecols(void * c,int row,int startcol,int ncols,long fillattr)1959 cl_wserasecols(void *c, int row, int startcol, int ncols, long fillattr)
1960 {
1961 	volatile unsigned char *ba, *cp;
1962 	struct rasops_info *ri;
1963 	struct vcons_screen *scr;
1964 	struct grf_softc *gp;
1965 	int i;
1966 
1967 	ri = c;
1968 	scr = ri->ri_hw;
1969 	gp = scr->scr_cookie;
1970 	ba = gp->g_regkva;
1971 	cp = gp->g_fbkva;
1972 
1973 	cp += gp->g_rowoffset[row] + startcol;
1974 	SetTextPlane(ba, 0x00);
1975 	for (i = 0; i < ncols; i++)
1976 		*cp++ = 0x20;
1977 	cp -= ncols;
1978 	SetTextPlane(ba, 0x01);
1979 	for (i = 0; i < ncols; i++)
1980 		*cp++ = 0x07;
1981 }
1982 
1983 static void
cl_wscopyrows(void * c,int srcrow,int dstrow,int nrows)1984 cl_wscopyrows(void *c, int srcrow, int dstrow, int nrows)
1985 {
1986 	volatile unsigned char *ba, *dst, *src;
1987 	struct rasops_info *ri;
1988 	struct vcons_screen *scr;
1989 	struct grf_softc *gp;
1990 	int i, n;
1991 
1992 	KASSERT(nrows > 0);
1993 	ri = c;
1994 	scr = ri->ri_hw;
1995 	gp = scr->scr_cookie;
1996 	ba = gp->g_regkva;
1997 	src = dst = gp->g_fbkva;
1998 	n = ri->ri_cols * nrows;
1999 
2000 	if (srcrow < dstrow) {
2001 		/* need to copy backwards */
2002 		src += gp->g_rowoffset[srcrow + nrows];
2003 		dst += gp->g_rowoffset[dstrow + nrows];
2004 		SetTextPlane(ba, 0x00);
2005 		for (i = 0; i < n; i++)
2006 			*(--dst) = *(--src);
2007 		src += n;
2008 		dst += n;
2009 		SetTextPlane(ba, 0x01);
2010 		for (i = 0; i < n; i++)
2011 			*(--dst) = *(--src);
2012 	} else {
2013 		src += gp->g_rowoffset[srcrow];
2014 		dst += gp->g_rowoffset[dstrow];
2015 		SetTextPlane(ba, 0x00);
2016 		for (i = 0; i < n; i++)
2017 			*dst++ = *src++;
2018 		src -= n;
2019 		dst -= n;
2020 		SetTextPlane(ba, 0x01);
2021 		for (i = 0; i < n; i++)
2022 			*dst++ = *src++;
2023 	}
2024 }
2025 
2026 static void
cl_wseraserows(void * c,int row,int nrows,long fillattr)2027 cl_wseraserows(void *c, int row, int nrows, long fillattr)
2028 {
2029 	volatile unsigned char *ba, *cp;
2030 	struct rasops_info *ri;
2031 	struct vcons_screen *scr;
2032 	struct grf_softc *gp;
2033 	int i, n;
2034 
2035 	ri = c;
2036 	scr = ri->ri_hw;
2037 	gp = scr->scr_cookie;
2038 	ba = gp->g_regkva;
2039 	cp = gp->g_fbkva;
2040 
2041 	cp += gp->g_rowoffset[row];
2042 	n = ri->ri_cols * nrows;
2043 	SetTextPlane(ba, 0x00);
2044 	for (i = 0; i < n; i++)
2045 		*cp++ = 0x20;
2046 	cp -= n;
2047 	SetTextPlane(ba, 0x01);
2048 	for (i = 0; i < n; i++)
2049 		*cp++ = 0x07;
2050 }
2051 
2052 static int
cl_wsallocattr(void * c,int fg,int bg,int flg,long * attr)2053 cl_wsallocattr(void *c, int fg, int bg, int flg, long *attr)
2054 {
2055 
2056 	/* XXX color support? */
2057 	*attr = (flg & WSATTR_REVERSE) ? 0x70 : 0x07;
2058 	if (flg & WSATTR_UNDERLINE)	*attr = 0x01;
2059 	if (flg & WSATTR_HILIT)		*attr |= 0x08;
2060 	if (flg & WSATTR_BLINK)		*attr |= 0x80;
2061 	return 0;
2062 }
2063 
2064 /* our font does not support unicode extensions */
2065 static int
cl_wsmapchar(void * c,int ch,unsigned int * cp)2066 cl_wsmapchar(void *c, int ch, unsigned int *cp)
2067 {
2068 
2069 	if (ch > 0 && ch < 256) {
2070 		*cp = ch;
2071 		return 5;
2072 	}
2073 	*cp = ' ';
2074 	return 0;
2075 }
2076 
2077 static int
cl_wsioctl(void * v,void * vs,u_long cmd,void * data,int flag,struct lwp * l)2078 cl_wsioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
2079 {
2080 	struct vcons_data *vd;
2081 	struct grf_softc *gp;
2082 
2083 	vd = v;
2084 	gp = vd->cookie;
2085 
2086 	switch (cmd) {
2087 	case WSDISPLAYIO_GETCMAP:
2088 		/* Note: wsdisplay_cmap and grf_colormap have same format */
2089 		if (gp->g_display.gd_planes == 8)
2090 			return cl_getcmap(gp, (struct grf_colormap *)data);
2091 		return EINVAL;
2092 
2093 	case WSDISPLAYIO_PUTCMAP:
2094 		/* Note: wsdisplay_cmap and grf_colormap have same format */
2095 		if (gp->g_display.gd_planes == 8)
2096 			return cl_putcmap(gp, (struct grf_colormap *)data);
2097 		return EINVAL;
2098 
2099 	case WSDISPLAYIO_GVIDEO:
2100 		if (cl_isblank(gp))
2101 			*(u_int *)data = WSDISPLAYIO_VIDEO_OFF;
2102 		else
2103 			*(u_int *)data = WSDISPLAYIO_VIDEO_ON;
2104 		return 0;
2105 
2106 	case WSDISPLAYIO_SVIDEO:
2107 		return cl_blank(gp, *(u_int *)data == WSDISPLAYIO_VIDEO_ON);
2108 
2109 	case WSDISPLAYIO_SMODE:
2110 		if ((*(int *)data) != gp->g_wsmode) {
2111 			if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
2112 				/* load console text mode, redraw screen */
2113 				(void)cl_load_mon(gp, &clconsole_mode);
2114 				if (vd->active != NULL)
2115 					vcons_redraw_screen(vd->active);
2116 			} else {
2117 				/* switch to current graphics mode */
2118 				if (!cl_load_mon(gp,
2119 				    (struct grfcltext_mode *)monitor_current))
2120 					return EINVAL;
2121 			}
2122 			gp->g_wsmode = *(int *)data;
2123 		}
2124 		return 0;
2125 
2126 	case WSDISPLAYIO_GET_FBINFO:
2127 		return cl_get_fbinfo(gp, data);
2128 	}
2129 
2130 	/* handle this command hw-independent in grf(4) */
2131 	return grf_wsioctl(v, vs, cmd, data, flag, l);
2132 }
2133 
2134 /*
2135  * Fill the wsdisplayio_fbinfo structure with information from the current
2136  * graphics mode. Even when text mode is active.
2137  */
2138 static int
cl_get_fbinfo(struct grf_softc * gp,struct wsdisplayio_fbinfo * fbi)2139 cl_get_fbinfo(struct grf_softc *gp, struct wsdisplayio_fbinfo *fbi)
2140 {
2141 	struct grfvideo_mode *md;
2142 	uint32_t rbits, gbits, bbits;
2143 
2144 	md = monitor_current;
2145 
2146 	switch (md->depth) {
2147 	case 8:
2148 		fbi->fbi_bitsperpixel = 8;
2149 		rbits = gbits = bbits = 6;  /* keep gcc happy */
2150 		break;
2151 	case 15:
2152 		fbi->fbi_bitsperpixel = 16;
2153 		rbits = gbits = bbits = 5;
2154 		break;
2155 	case 16:
2156 		fbi->fbi_bitsperpixel = 16;
2157 		rbits = bbits = 5;
2158 		gbits = 6;
2159 		break;
2160 	case 24:
2161 		fbi->fbi_bitsperpixel = 24;
2162 		rbits = gbits = bbits = 8;
2163 		break;
2164 	default:
2165 		return EINVAL;
2166 	}
2167 
2168 	fbi->fbi_stride = (fbi->fbi_bitsperpixel / 8) * md->disp_width;
2169 	fbi->fbi_width = md->disp_width;
2170 	fbi->fbi_height = md->disp_height;
2171 
2172 	if (md->depth > 8) {
2173 		fbi->fbi_pixeltype = WSFB_RGB;
2174 		fbi->fbi_subtype.fbi_rgbmasks.red_offset = bbits + gbits;
2175 		fbi->fbi_subtype.fbi_rgbmasks.red_size = rbits;
2176 		fbi->fbi_subtype.fbi_rgbmasks.green_offset = bbits;
2177 		fbi->fbi_subtype.fbi_rgbmasks.green_size = gbits;
2178 		fbi->fbi_subtype.fbi_rgbmasks.blue_offset = 0;
2179 		fbi->fbi_subtype.fbi_rgbmasks.blue_size = bbits;
2180 		fbi->fbi_subtype.fbi_rgbmasks.alpha_offset = 0;
2181 		fbi->fbi_subtype.fbi_rgbmasks.alpha_size = 0;
2182 	} else {
2183 		fbi->fbi_pixeltype = WSFB_CI;
2184 		fbi->fbi_subtype.fbi_cmapinfo.cmap_entries = 1 << md->depth;
2185 	}
2186 
2187 	fbi->fbi_flags = 0;
2188 	fbi->fbi_fbsize = fbi->fbi_stride * fbi->fbi_height;
2189 	fbi->fbi_fboffset = 0;
2190 	return 0;
2191 }
2192 #endif	/* NWSDISPLAY > 0 */
2193 
2194 #endif /* NGRFCL */
2195