xref: /netbsd-src/sys/arch/amiga/dev/grf_cl.c (revision 627f7eb200a4419d89b531d55fccd2ee3ffdcde0)
1 /*	$NetBSD: grf_cl.c,v 1.50 2015/11/16 21:25:34 phx 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.50 2015/11/16 21:25:34 phx 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 suuport 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/malloc.h>
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
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
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 		attachflag = 1;
460 		printf("grfcl: %dMB ", cl_fbsize / 0x100000);
461 		switch (cltype) {
462 		    case PICASSO:
463 			if (cl_64bit == 1) {
464 				printf("Picasso IV");
465 				/* 135MHz will be supported if we
466 				 * have a palette doubling mode.
467 				 */
468 				cl_maxpixelclock = 86000000;
469 			}
470 			else {
471 				printf("Picasso II");
472 
473 				/* check for PicassoII+ (crest) */
474 				if(zap->serno == 0x00100000)
475 				    printf("+");
476 
477 				/* determine used Gfx/chipset (crest) */
478 				vgaw(gp->g_regkva, CRT_ADDRESS, 0x27); /* Chip ID */
479 				switch(vgar(gp->g_regkva, CRT_ADDRESS_R)>>2) {
480 				    case 0x24:
481 					printf(" (with CL-GD5426)");
482 					break;
483 				    case 0x26:
484 					printf(" (with CL-GD5428)");
485 					break;
486 				    case 0x27:
487 					printf(" (with CL-GD5429)");
488 					break;
489 				}
490 	                        cl_maxpixelclock = 86000000;
491 			}
492 			break;
493 		    case SPECTRUM:
494 			printf("Spectrum");
495                         cl_maxpixelclock = 90000000;
496 			break;
497 		    case PICCOLO:
498 			if (cl_64bit == 1) {
499 				printf("Piccolo SD64");
500 				/* 110MHz will be supported if we
501 				 * have a palette doubling mode.
502 				 */
503 				cl_maxpixelclock = 90000000;
504 			} else {
505 				printf("Piccolo");
506 				cl_maxpixelclock = 90000000;
507 			}
508 			break;
509 		}
510 		printf(" being used\n");
511 #ifdef CL_OVERCLOCK
512                 cl_maxpixelclock = 115000000;
513 #endif
514 	} else {
515 		if (!attachflag)
516 			printf("grfcl unattached!!\n");
517 	}
518 }
519 
520 int
521 grfclprint(void *aux, const char *pnp)
522 {
523 	if (pnp)
524 		aprint_normal("ite at %s: ", pnp);
525 	return (UNCONF);
526 }
527 
528 void
529 cl_boardinit(struct grf_softc *gp)
530 {
531 	volatile unsigned char *ba = gp->g_regkva;
532 	int     x;
533 
534 	if ((cltype == PICASSO) && (cl_64bit == 1)) { /* PicassoIV */
535 		WCrt(ba, 0x51, 0x00);		/* disable capture (FlickerFixer) */
536 		delay(200000);		/* wait some time (two frames as of now) */
537 		WGfx(ba, 0x2f, 0x00);			/* get Blitter into 542x  */
538 		WGfx(ba, GCT_ID_RESERVED, 0x00);	/* compatibility mode     */
539 		WGfx(ba, GCT_ID_BLT_STAT_START, 0x00);	/* or at least, try so... */
540 		cl_fbsize = cl_fbautosize;
541 	} else {
542 
543 		/* wakeup board and flip passthru OFF */
544 		RegWakeup(ba);
545 		RegOnpass(ba);
546 
547 		vgaw(ba, 0x46e8, 0x16);
548 		vgaw(ba, 0x102, 1);
549 		vgaw(ba, 0x46e8, 0x0e);
550 		if (cl_64bit != 1)
551 			vgaw(ba, 0x3c3, 1);
552 
553 		cl_fbsize = cl_fbautosize;
554 
555 		/* setup initial unchanging parameters */
556 
557 		cl_blanked = 1;
558 		WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21);	/* 8 dot - display off */
559 		vgaw(ba, GREG_MISC_OUTPUT_W, 0xed);	/* mem disable */
560 
561 		WGfx(ba, GCT_ID_OFFSET_1, 0xec);	/* magic cookie */
562 		WSeq(ba, SEQ_ID_UNLOCK_EXT, 0x12);	/* yum! cookies! */
563 
564 		if (cl_64bit == 1) {
565 			WSeq(ba, SEQ_ID_CONF_RBACK, 0x00);
566 			WSeq(ba, SEQ_ID_DRAM_CNTL, (cl_fbsize / 0x100000 == 2) ? 0x38 : 0xb8);
567 		} else {
568 			WSeq(ba, SEQ_ID_DRAM_CNTL, 0xb0);
569 		}
570 		WSeq(ba, SEQ_ID_RESET, 0x03);
571 		WSeq(ba, SEQ_ID_MAP_MASK, 0xff);
572 		WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
573 		WSeq(ba, SEQ_ID_MEMORY_MODE, 0x0e);	/* a or 6? */
574 		WSeq(ba, SEQ_ID_EXT_SEQ_MODE, (cltype == PICASSO) ? 0x21 : 0x81);
575 		WSeq(ba, SEQ_ID_EEPROM_CNTL, 0x00);
576 		if (cl_64bit == 1)
577 			WSeq(ba, SEQ_ID_PERF_TUNE, 0x5a);
578 		else
579 			WSeq(ba, SEQ_ID_PERF_TUNE, 0x0a);	/* mouse 0a fa */
580 		WSeq(ba, SEQ_ID_SIG_CNTL, 0x02);
581 		WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x04);
582 
583 		if (cl_64bit == 1)
584 			WSeq(ba, SEQ_ID_MCLK_SELECT, 0x1c);
585 		else
586 		WSeq(ba, SEQ_ID_MCLK_SELECT, 0x22);
587 
588 		WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00);
589 		WCrt(ba, CRT_ID_CURSOR_START, 0x00);
590 		WCrt(ba, CRT_ID_CURSOR_END, 0x08);
591 		WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
592 		WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
593 		WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
594 		WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
595 
596 		WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x07);
597 		WCrt(ba, CRT_ID_MODE_CONTROL, 0xe3);
598 		WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);	/* ff */
599 		WCrt(ba, CRT_ID_EXT_DISP_CNTL, 0x22);
600 		if (cl_64bit == 1) {
601 			WCrt(ba, CRT_ID_SYNC_ADJ_GENLOCK, 0x00);
602 			WCrt(ba, CRT_ID_OVERLAY_EXT_CTRL_REG, 0x40);
603 		}
604 		WSeq(ba, SEQ_ID_CURSOR_STORE, 0x3c);	/* mouse 0x00 */
605 
606 		WGfx(ba, GCT_ID_SET_RESET, 0x00);
607 		WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
608 		WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
609 		WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
610 		WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x00);
611 		WGfx(ba, GCT_ID_MISC, 0x01);
612 		WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f);
613 		WGfx(ba, GCT_ID_BITMASK, 0xff);
614 		WGfx(ba, GCT_ID_MODE_EXT, 0x28);
615 
616 		for (x = 0; x < 0x10; x++)
617 			WAttr(ba, x, x);
618 		WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x01);
619 		WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00);
620 		WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
621 		WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
622 		WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
623 		WAttr(ba, 0x34, 0x00);
624 
625 		vgaw(ba, VDAC_MASK, 0xff);
626 		vgaw(ba, GREG_MISC_OUTPUT_W, 0xef);
627 
628 		WGfx(ba, GCT_ID_BLT_STAT_START, 0x04);
629 		WGfx(ba, GCT_ID_BLT_STAT_START, 0x00);
630 	}
631 
632 	/* colors initially set to greyscale */
633 	vgaw(ba, VDAC_ADDRESS_W, 0);
634 	for (x = 255; x >= 0; x--) {
635 		vgaw(ba, VDAC_DATA, x);
636 		vgaw(ba, VDAC_DATA, x);
637 		vgaw(ba, VDAC_DATA, x);
638 	}
639 	/* set sprite bitmap pointers */
640 	cl_cursprite.image = cl_imageptr;
641 	cl_cursprite.mask = cl_maskptr;
642 	cl_cursprite.cmap.red = cl_sprred;
643 	cl_cursprite.cmap.green = cl_sprgreen;
644 	cl_cursprite.cmap.blue = cl_sprblue;
645 
646 	if (cl_64bit == 0) {
647 
648 		/* check for 1MB or 2MB board (crest) */
649 		volatile unsigned long *cl_fbtestaddr;
650 		cl_fbtestaddr = (volatile unsigned long *)gp->g_fbkva;
651 
652 		WGfx(ba, GCT_ID_OFFSET_0, 0x40);
653 		*cl_fbtestaddr = 0x12345678;
654 
655 		if (*cl_fbtestaddr != 0x12345678) {
656 			WSeq(ba, SEQ_ID_DRAM_CNTL, 0x30);
657 			cl_fbsize = 0x100000;
658 		}
659 		else
660 		{
661 			cl_fbsize = 0x200000;
662 		}
663 	}
664 	WGfx(ba, GCT_ID_OFFSET_0, 0x00);
665 }
666 
667 
668 int
669 cl_getvmode(struct grf_softc *gp, struct grfvideo_mode *vm)
670 {
671 	struct grfvideo_mode *gv;
672 
673 #ifdef CL5426CONSOLE
674 	/* Handle grabbing console mode */
675 	if (vm->mode_num == 255) {
676 		memcpy(vm, &clconsole_mode, sizeof(struct grfvideo_mode));
677 		/* XXX so grfconfig can tell us the correct text dimensions. */
678 		vm->depth = clconsole_mode.fy;
679 	} else
680 #endif
681         {
682                 if (vm->mode_num == 0)
683                         vm->mode_num = (monitor_current - monitor_def) + 1;
684                 if (vm->mode_num < 1 || vm->mode_num > monitor_def_max)
685                         return (EINVAL);
686                 gv = monitor_def + (vm->mode_num - 1);
687                 if (gv->mode_num == 0)
688                         return (EINVAL);
689 
690                 memcpy(vm, gv, sizeof(struct grfvideo_mode));
691         }
692 
693         /* adjust internal values to pixel values */
694 
695         vm->hblank_start *= 8;
696         vm->hsync_start *= 8;
697         vm->hsync_stop *= 8;
698         vm->htotal *= 8;
699 
700 	return (0);
701 }
702 
703 
704 int
705 cl_setvmode(struct grf_softc *gp, unsigned mode)
706 {
707 	if (!mode || (mode > monitor_def_max) ||
708 	    monitor_def[mode - 1].mode_num == 0)
709 		return (EINVAL);
710 
711 	monitor_current = monitor_def + (mode - 1);
712 
713 	return (0);
714 }
715 
716 #ifndef CL5426CONSOLE
717 void
718 cl_off(struct grf_softc *gp)
719 {
720 	char   *ba = gp->g_regkva;
721 
722 	/*
723 	 * we'll put the pass-through on for cc ite and set Full Bandwidth bit
724 	 * on just in case it didn't work...but then it doesn't matter does
725 	 * it? =)
726 	 */
727 	RegOnpass(ba);
728 	vgaw(ba, SEQ_ADDRESS, SEQ_ID_CLOCKING_MODE);
729 	vgaw(ba, SEQ_ADDRESS_W, vgar(ba, SEQ_ADDRESS_W) | 0x20);
730 	cl_blanked = 1;
731 }
732 #endif
733 
734 int
735 cl_blank(struct grf_softc *gp, int on)
736 {
737 
738 	WSeq(gp->g_regkva, SEQ_ID_CLOCKING_MODE, on ? 0x01 : 0x21);
739 	cl_blanked = !on;
740 	return 0;
741 }
742 
743 int
744 cl_isblank(struct grf_softc *gp)
745 {
746 
747 	return cl_blanked;
748 }
749 
750 /*
751  * Change the mode of the display.
752  * Return a UNIX error number or 0 for success.
753  */
754 int
755 cl_mode(register struct grf_softc *gp, u_long cmd, void *arg, u_long a2, int a3)
756 {
757 	int     error;
758 
759 	switch (cmd) {
760 	    case GM_GRFON:
761 		error = cl_load_mon(gp,
762 		    (struct grfcltext_mode *) monitor_current) ? 0 : EINVAL;
763 		return (error);
764 
765 	    case GM_GRFOFF:
766 #ifndef CL5426CONSOLE
767 		cl_off(gp);
768 #else
769 		cl_load_mon(gp, &clconsole_mode);
770 #endif
771 		return (0);
772 
773 	    case GM_GRFCONFIG:
774 		return (0);
775 
776 	    case GM_GRFGETVMODE:
777 		return (cl_getvmode(gp, (struct grfvideo_mode *) arg));
778 
779 	    case GM_GRFSETVMODE:
780 		error = cl_setvmode(gp, *(unsigned *) arg);
781 		if (!error && (gp->g_flags & GF_GRFON))
782 			cl_load_mon(gp,
783 			    (struct grfcltext_mode *) monitor_current);
784 		return (error);
785 
786 	    case GM_GRFGETNUMVM:
787 		*(int *) arg = monitor_def_max;
788 		return (0);
789 
790 	    case GM_GRFIOCTL:
791 		return (cl_ioctl(gp, a2, arg));
792 
793 	    default:
794 		break;
795 	}
796 
797 	return (EPASSTHROUGH);
798 }
799 
800 int
801 cl_ioctl(register struct grf_softc *gp, u_long cmd, void *data)
802 {
803 	switch (cmd) {
804 	    case GRFIOCGSPRITEPOS:
805 		return (cl_getmousepos(gp, (struct grf_position *) data));
806 
807 	    case GRFIOCSSPRITEPOS:
808 		return (cl_setmousepos(gp, (struct grf_position *) data));
809 
810 	    case GRFIOCSSPRITEINF:
811 		return (cl_setspriteinfo(gp, (struct grf_spriteinfo *) data));
812 
813 	    case GRFIOCGSPRITEINF:
814 		return (cl_getspriteinfo(gp, (struct grf_spriteinfo *) data));
815 
816 	    case GRFIOCGSPRITEMAX:
817 		return (cl_getspritemax(gp, (struct grf_position *) data));
818 
819 	    case GRFIOCGETCMAP:
820 		return (cl_getcmap(gp, (struct grf_colormap *) data));
821 
822 	    case GRFIOCPUTCMAP:
823 		return (cl_putcmap(gp, (struct grf_colormap *) data));
824 
825 	    case GRFIOCBITBLT:
826 		break;
827 
828 	    case GRFTOGGLE:
829 		return (cl_toggle(gp, 0));
830 
831 	    case GRFIOCSETMON:
832 		return (cl_setmonitor(gp, (struct grfvideo_mode *) data));
833 
834             case GRFIOCBLANK:
835                 return (cl_blank(gp, *(int *)data));
836 
837 	}
838 	return (EPASSTHROUGH);
839 }
840 
841 int
842 cl_getmousepos(struct grf_softc *gp, struct grf_position *data)
843 {
844 	data->x = cl_cursprite.pos.x;
845 	data->y = cl_cursprite.pos.y;
846 	return (0);
847 }
848 
849 void
850 cl_writesprpos(volatile char *ba, short x, short y)
851 {
852 	/* we want to use a 16-bit write to 3c4 so no macros used */
853 	volatile unsigned char *cwp;
854         volatile unsigned short *wp;
855 
856 	cwp = ba + 0x3c4;
857         wp = (volatile unsigned short *)cwp;
858 
859 	/*
860 	 * don't ask me why, but apparently you can't do a 16-bit write with
861 	 * x-position like with y-position below (dagge)
862 	 */
863         cwp[0] = 0x10 | ((x << 5) & 0xff);
864         cwp[1] = (x >> 3) & 0xff;
865 
866         *wp = 0x1100 | ((y & 7) << 13) | ((y >> 3) & 0xff);
867 }
868 
869 void
870 writeshifted(volatile char *to, signed char shiftx, signed char shifty)
871 {
872 	int y;
873 	unsigned long long *tptr, *iptr, *mptr, line;
874 
875 	tptr = (unsigned long long *) __UNVOLATILE(to);
876         iptr = (unsigned long long *) cl_cursprite.image;
877         mptr = (unsigned long long *) cl_cursprite.mask;
878 
879         shiftx = shiftx < 0 ? 0 : shiftx;
880         shifty = shifty < 0 ? 0 : shifty;
881 
882         /* start reading shifty lines down, and
883          * shift each line in by shiftx
884          */
885         for (y = shifty; y < 64; y++) {
886 
887                 /* image */
888                 line = iptr[y];
889 		*tptr++ = line << shiftx;
890 
891                 /* mask */
892                 line = mptr[y];
893 		*tptr++ = line << shiftx;
894 	}
895 
896         /* clear the remainder */
897         for (y = shifty; y > 0; y--) {
898                 *tptr++ = 0;
899                 *tptr++ = 0;
900         }
901 }
902 
903 int
904 cl_setmousepos(struct grf_softc *gp, struct grf_position *data)
905 {
906 	volatile char *ba = gp->g_regkva;
907         short rx, ry;
908 #ifdef CL_SHIFTSPRITE
909 	volatile char *fb = gp->g_fbkva;
910         volatile char *sprite = fb + (cl_fbsize - 1024);
911 #endif
912 
913         /* no movement */
914 	if (cl_cursprite.pos.x == data->x && cl_cursprite.pos.y == data->y)
915 		return (0);
916 
917         /* current and previous real coordinates */
918 	rx = data->x - cl_cursprite.hot.x;
919 	ry = data->y - cl_cursprite.hot.y;
920 
921         /*
922 	 * if we are/were on an edge, create (un)shifted bitmap --
923          * ripped out optimization (not extremely worthwhile,
924          * and kind of buggy anyhow).
925          */
926 #ifdef CL_SHIFTSPRITE
927         if (rx < 0 || ry < 0 || prx < 0 || pry < 0) {
928                 writeshifted(sprite, rx < 0 ? -rx : 0, ry < 0 ? -ry : 0);
929         }
930 #endif
931 
932         /* do movement, save position */
933         cl_writesprpos(ba, rx < 0 ? 0 : rx, ry < 0 ? 0 : ry);
934 	cl_cursprite.pos.x = data->x;
935 	cl_cursprite.pos.y = data->y;
936 
937 	return (0);
938 }
939 
940 int
941 cl_getspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *data)
942 {
943 	copyout(&cl_cursprite, data, sizeof(struct grf_spriteinfo));
944 	copyout(cl_cursprite.image, data->image, 64 * 8);
945 	copyout(cl_cursprite.mask, data->mask, 64 * 8);
946 	return (0);
947 }
948 
949 static int
950 cl_setspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *data)
951 {
952 	volatile unsigned char *ba = gp->g_regkva, *fb = gp->g_fbkva;
953         volatile char *sprite = fb + (cl_fbsize - 1024);
954 
955 	if (data->set & GRFSPRSET_SHAPE) {
956 
957                 unsigned short dsx, dsy, i;
958                 unsigned long *di, *dm, *si, *sm;
959                 unsigned long ssi[128], ssm[128];
960                 struct grf_position gpos;
961 
962 
963                 /* check for a too large sprite (no clipping!) */
964                 dsy = data->size.y;
965                 dsx = data->size.x;
966                 if (dsy > 64 || dsx > 64)
967                         return(EINVAL);
968 
969                 /* prepare destination */
970                 di = (unsigned long *)cl_cursprite.image;
971                 dm = (unsigned long *)cl_cursprite.mask;
972                 cl_memset((unsigned char *)di, 0, 8*64);
973                 cl_memset((unsigned char *)dm, 0, 8*64);
974 
975                 /* two alternatives:  64 across, then it's
976                  * the same format we use, just copy.  Otherwise,
977                  * copy into tmp buf and recopy skipping the
978                  * unused 32 bits.
979                  */
980                 if ((dsx - 1) / 32) {
981                         copyin(data->image, di, 8 * dsy);
982                         copyin(data->mask, dm, 8 * dsy);
983                 } else {
984                         si = ssi; sm = ssm;
985                         copyin(data->image, si, 4 * dsy);
986                         copyin(data->mask, sm, 4 * dsy);
987                         for (i = 0; i < dsy; i++) {
988                                 *di = *si++;
989                                 *dm = *sm++;
990                                 di += 2;
991                                 dm += 2;
992                         }
993                 }
994 
995                 /* set size */
996 		cl_cursprite.size.x = data->size.x;
997 		cl_cursprite.size.y = data->size.y;
998 
999                 /* forcably load into board */
1000                 gpos.x = cl_cursprite.pos.x;
1001                 gpos.y = cl_cursprite.pos.y;
1002                 cl_cursprite.pos.x = -1;
1003                 cl_cursprite.pos.y = -1;
1004                 writeshifted(sprite, 0, 0);
1005                 cl_setmousepos(gp, &gpos);
1006 
1007 	}
1008 	if (data->set & GRFSPRSET_HOT) {
1009 
1010 		cl_cursprite.hot = data->hot;
1011 
1012 	}
1013 	if (data->set & GRFSPRSET_CMAP) {
1014 
1015 		u_char  red[2], green[2], blue[2];
1016 
1017 		copyin(data->cmap.red, red, 2);
1018 		copyin(data->cmap.green, green, 2);
1019 		copyin(data->cmap.blue, blue, 2);
1020 		memcpy(cl_cursprite.cmap.red, red, 2);
1021 		memcpy(cl_cursprite.cmap.green, green, 2);
1022 		memcpy(cl_cursprite.cmap.blue, blue, 2);
1023 
1024                 /* enable and load colors 256 & 257 */
1025 		WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x06);
1026 
1027                 /* 256 */
1028 		vgaw(ba, VDAC_ADDRESS_W, 0x00);
1029 		if (cltype == PICASSO) {
1030 			vgaw(ba, VDAC_DATA, (u_char) (red[0] >> 2));
1031 			vgaw(ba, VDAC_DATA, (u_char) (green[0] >> 2));
1032 			vgaw(ba, VDAC_DATA, (u_char) (blue[0] >> 2));
1033 		} else {
1034 			vgaw(ba, VDAC_DATA, (u_char) (blue[0] >> 2));
1035 			vgaw(ba, VDAC_DATA, (u_char) (green[0] >> 2));
1036 			vgaw(ba, VDAC_DATA, (u_char) (red[0] >> 2));
1037 		}
1038 
1039                 /* 257 */
1040 		vgaw(ba, VDAC_ADDRESS_W, 0x0f);
1041 		if (cltype == PICASSO) {
1042 			vgaw(ba, VDAC_DATA, (u_char) (red[1] >> 2));
1043 			vgaw(ba, VDAC_DATA, (u_char) (green[1] >> 2));
1044 			vgaw(ba, VDAC_DATA, (u_char) (blue[1] >> 2));
1045 		} else {
1046 			vgaw(ba, VDAC_DATA, (u_char) (blue[1] >> 2));
1047 			vgaw(ba, VDAC_DATA, (u_char) (green[1] >> 2));
1048 			vgaw(ba, VDAC_DATA, (u_char) (red[1] >> 2));
1049 		}
1050 
1051                 /* turn on/off sprite */
1052 		if (cl_cursprite.enable) {
1053 			WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x05);
1054 		} else {
1055 			WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x04);
1056 		}
1057 
1058 	}
1059 	if (data->set & GRFSPRSET_ENABLE) {
1060 
1061 		if (data->enable == 1) {
1062 			WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x05);
1063 			cl_cursprite.enable = 1;
1064 		} else {
1065 			WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x04);
1066 			cl_cursprite.enable = 0;
1067 		}
1068 
1069 	}
1070 	if (data->set & GRFSPRSET_POS) {
1071 
1072                 /* force placement */
1073                 cl_cursprite.pos.x = -1;
1074                 cl_cursprite.pos.y = -1;
1075 
1076                 /* do it */
1077                 cl_setmousepos(gp, &data->pos);
1078 
1079 	}
1080 	return (0);
1081 }
1082 
1083 static int
1084 cl_getspritemax(struct grf_softc *gp, struct grf_position *data)
1085 {
1086 	if (gp->g_display.gd_planes == 24)
1087 		return (EINVAL);
1088 	data->x = 64;
1089 	data->y = 64;
1090 	return (0);
1091 }
1092 
1093 int
1094 cl_setmonitor(struct grf_softc *gp, struct grfvideo_mode *gv)
1095 {
1096 	struct grfvideo_mode *md;
1097 
1098         if (!cl_mondefok(gv))
1099                 return(EINVAL);
1100 
1101 #ifdef CL5426CONSOLE
1102 	/* handle interactive setting of console mode */
1103 	if (gv->mode_num == 255) {
1104 		memcpy(&clconsole_mode.gv, gv, sizeof(struct grfvideo_mode));
1105 		clconsole_mode.gv.hblank_start /= 8;
1106 		clconsole_mode.gv.hsync_start /= 8;
1107 		clconsole_mode.gv.hsync_stop /= 8;
1108 		clconsole_mode.gv.htotal /= 8;
1109 		clconsole_mode.rows = gv->disp_height / clconsole_mode.fy;
1110 		clconsole_mode.cols = gv->disp_width / clconsole_mode.fx;
1111 		if (!(gp->g_flags & GF_GRFON))
1112 			cl_load_mon(gp, &clconsole_mode);
1113 #if NITE > 0
1114 		ite_reinit(gp->g_itedev);
1115 #endif
1116 		return (0);
1117 	}
1118 #endif
1119 
1120 	md = monitor_def + (gv->mode_num - 1);
1121 	memcpy(md, gv, sizeof(struct grfvideo_mode));
1122 
1123 	/* adjust pixel oriented values to internal rep. */
1124 
1125 	md->hblank_start /= 8;
1126 	md->hsync_start /= 8;
1127 	md->hsync_stop /= 8;
1128 	md->htotal /= 8;
1129 
1130 	return (0);
1131 }
1132 
1133 int
1134 cl_getcmap(struct grf_softc *gfp, struct grf_colormap *cmap)
1135 {
1136 	volatile unsigned char *ba;
1137 	u_char  red[256], green[256], blue[256], *rp, *gp, *bp;
1138 	short   x;
1139 	int     error;
1140 
1141 	if (cmap->count == 0 || cmap->index >= 256)
1142 		return 0;
1143 
1144 	if (cmap->count > 256 - cmap->index)
1145 		cmap->count = 256 - cmap->index;
1146 
1147 	ba = gfp->g_regkva;
1148 	/* first read colors out of the chip, then copyout to userspace */
1149 	vgaw(ba, VDAC_ADDRESS_R, cmap->index);
1150 	x = cmap->count - 1;
1151 
1152 /*
1153  * Some sort 'o Magic. Spectrum has some changes on the board to speed
1154  * up 15 and 16Bit modes. They can access these modes with easy-to-programm
1155  * rgbrgbrgb instead of rrrgggbbb. Side effect: when in 8Bit mode, rgb
1156  * is swapped to bgr. I wonder if we need to check for 8Bit though, ill
1157  */
1158 
1159 /*
1160  * The source for the above comment is somewhat unknow to me.
1161  * The Spectrum, Piccolo and PiccoloSD64 have the analog Red and Blue
1162  * lines swapped. In 24BPP this provides RGB instead of BGR as it would
1163  * be native to the chipset. This requires special programming for the
1164  * CLUT in 8BPP to compensate and avoid false colors.
1165  * I didn't find any special stuff for 15 and 16BPP though, crest.
1166  */
1167 
1168 	switch (cltype) {
1169 	    case SPECTRUM:
1170 	    case PICCOLO:
1171 		rp = blue + cmap->index;
1172 		gp = green + cmap->index;
1173 		bp = red + cmap->index;
1174 		break;
1175 	    case PICASSO:
1176 		rp = red + cmap->index;
1177 		gp = green + cmap->index;
1178 		bp = blue + cmap->index;
1179 		break;
1180 	    default:
1181 		rp = gp = bp = 0;
1182 		break;
1183 	}
1184 
1185 	do {
1186 		*rp++ = vgar(ba, VDAC_DATA) << 2;
1187 		*gp++ = vgar(ba, VDAC_DATA) << 2;
1188 		*bp++ = vgar(ba, VDAC_DATA) << 2;
1189 	} while (x-- > 0);
1190 
1191 	if (!(error = copyout(red + cmap->index, cmap->red, cmap->count))
1192 	    && !(error = copyout(green + cmap->index, cmap->green, cmap->count))
1193 	    && !(error = copyout(blue + cmap->index, cmap->blue, cmap->count)))
1194 		return (0);
1195 
1196 	return (error);
1197 }
1198 
1199 int
1200 cl_putcmap(struct grf_softc *gfp, struct grf_colormap *cmap)
1201 {
1202 	volatile unsigned char *ba;
1203 	u_char  red[256], green[256], blue[256], *rp, *gp, *bp;
1204 	short   x;
1205 	int     error;
1206 
1207 	if (cmap->count == 0 || cmap->index >= 256)
1208 		return (0);
1209 
1210 	if (cmap->count > 256 - cmap->index)
1211 		cmap->count = 256 - cmap->index;
1212 
1213 	/* first copy the colors into kernelspace */
1214 	if (!(error = copyin(cmap->red, red + cmap->index, cmap->count))
1215 	    && !(error = copyin(cmap->green, green + cmap->index, cmap->count))
1216 	    && !(error = copyin(cmap->blue, blue + cmap->index, cmap->count))) {
1217 		ba = gfp->g_regkva;
1218 		vgaw(ba, VDAC_ADDRESS_W, cmap->index);
1219 		x = cmap->count - 1;
1220 
1221 		switch (cltype) {
1222 		    case SPECTRUM:
1223 		    case PICCOLO:
1224 			rp = blue + cmap->index;
1225 			gp = green + cmap->index;
1226 			bp = red + cmap->index;
1227 			break;
1228 		    case PICASSO:
1229 			rp = red + cmap->index;
1230 			gp = green + cmap->index;
1231 			bp = blue + cmap->index;
1232 			break;
1233 		    default:
1234 			rp = gp = bp = 0;
1235 			break;
1236 		}
1237 
1238 		do {
1239 			vgaw(ba, VDAC_DATA, *rp++ >> 2);
1240 			vgaw(ba, VDAC_DATA, *gp++ >> 2);
1241 			vgaw(ba, VDAC_DATA, *bp++ >> 2);
1242 		} while (x-- > 0);
1243 		return (0);
1244 	} else
1245 		return (error);
1246 }
1247 
1248 
1249 int
1250 cl_toggle(struct grf_softc *gp, unsigned short wopp)
1251 	/* wopp:	 don't need that one yet, ill */
1252 {
1253 	volatile void *ba;
1254 
1255 	ba = gp->g_regkva;
1256 
1257 	if (cl_pass_toggle) {
1258 		RegOffpass(ba);
1259 	} else {
1260 		RegOnpass(ba);
1261 	}
1262 	return (0);
1263 }
1264 
1265 static void
1266 cl_CompFQ(u_int fq, u_char *num, u_char *denom, u_char *clkdoub)
1267 {
1268 #define OSC     14318180
1269 /* OK, here's what we're doing here:
1270  *
1271  *             OSC * NUMERATOR
1272  *      VCLK = -------------------  Hz
1273  *             DENOMINATOR * (1+P)
1274  *
1275  * so we're given VCLK and we should give out some useful
1276  * values....
1277  *
1278  * NUMERATOR is 7 bits wide
1279  * DENOMINATOR is 5 bits wide with bit P in the same char as bit 0.
1280  *
1281  * We run through all the possible combinations and
1282  * return the values which deviate the least from the chosen frequency.
1283  *
1284  */
1285 #define OSC     14318180
1286 #define count(n,d,p)    ((OSC * n)/(d * (1+p)))
1287 
1288 	unsigned char n, d, p, minn, mind, minp = 0;
1289 	unsigned long err, minerr;
1290 
1291 /*
1292 numer = 0x00 - 0x7f
1293 denom = 0x00 - 0x1f (1) 0x20 - 0x3e (even)
1294 */
1295 
1296 	/* find lowest error in 6144 iterations. */
1297 	minerr = fq;
1298 	minn = 0;
1299 	mind = 0;
1300 	p = 0;
1301 
1302 	if ((cl_64bit == 1) && (fq >= 86000000))
1303 	{
1304 		for (d = 1; d < 0x20; d++) {
1305 			for (n = 1; n < 0x80; n++) {
1306 				err = abs(count(n, d, 0) - fq);
1307 				if (err < minerr) {
1308 					minerr = err;
1309 					minn = n;
1310 					mind = d;
1311 					minp = 1;
1312 				}
1313 			}
1314 		}
1315 		*clkdoub = 1;
1316 	}
1317 	else {
1318 		for (d = 1; d < 0x20; d++) {
1319 			for (n = 1; n < 0x80; n++) {
1320 				err = abs(count(n, d, p) - fq);
1321 				if (err < minerr) {
1322 					minerr = err;
1323 					minn = n;
1324 					mind = d;
1325 					minp = p;
1326 				}
1327 			}
1328 			if (d == 0x1f && p == 0) {
1329 				p = 1;
1330 				d = 0x0f;
1331 			}
1332 		}
1333 		*clkdoub = 0;
1334 	}
1335 
1336 	*num = minn;
1337 	*denom = (mind << 1) | minp;
1338 	if (minerr > 500000)
1339 		printf("Warning: CompFQ minimum error = %ld\n", minerr);
1340 	return;
1341 }
1342 
1343 int
1344 cl_mondefok(struct grfvideo_mode *gv)
1345 {
1346         unsigned long maxpix;
1347 
1348 	if (gv->mode_num < 1 || gv->mode_num > monitor_def_max)
1349                 if (gv->mode_num != 255 || gv->depth != 4)
1350                         return(0);
1351 
1352 	switch (gv->depth) {
1353 	    case 4:
1354                 if (gv->mode_num != 255)
1355                         return(0);
1356 	    case 1:
1357 	    case 8:
1358 		maxpix = cl_maxpixelclock;
1359 		if (cl_64bit == 1)
1360 		{
1361 			if (cltype == PICASSO) /* Picasso IV */
1362 				maxpix = 135000000;
1363 			else                   /* Piccolo SD64 */
1364 				maxpix = 110000000;
1365 		}
1366                 break;
1367 	    case 15:
1368 	    case 16:
1369 		if (cl_64bit == 1)
1370 	                maxpix = 85000000;
1371 		else
1372 	                maxpix = cl_maxpixelclock - (cl_maxpixelclock / 3);
1373                 break;
1374 	    case 24:
1375 		if ((cltype == PICASSO) && (cl_64bit == 1))
1376 	                maxpix = 85000000;
1377 		else
1378 	                maxpix = cl_maxpixelclock / 3;
1379                 break;
1380 	    case 32:
1381 		if ((cltype == PICCOLO) && (cl_64bit == 1))
1382 	                maxpix = 50000000;
1383 		else
1384 	                maxpix = 0;
1385                 break;
1386 	default:
1387 		printf("grfcl: Illegal depth in mode %d\n",
1388 			(int) gv->mode_num);
1389 		return (0);
1390 	}
1391 
1392         if (gv->pixel_clock > maxpix) {
1393 		printf("grfcl: Pixelclock too high in mode %d\n",
1394 			(int) gv->mode_num);
1395                 return (0);
1396 	}
1397 
1398 	if (gv->disp_flags & GRF_FLAGS_SYNC_ON_GREEN) {
1399 		printf("grfcl: sync-on-green is not supported\n");
1400 		return (0);
1401 	}
1402 
1403         return (1);
1404 }
1405 
1406 int
1407 cl_load_mon(struct grf_softc *gp, struct grfcltext_mode *md)
1408 {
1409 	struct grfvideo_mode *gv;
1410 	struct grfinfo *gi;
1411 	volatile void *ba, *fb;
1412 	unsigned char num0, denom0, clkdoub;
1413 	unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS,
1414 	        VSE, VT;
1415 	int	clkmul, clkmode;
1416 	int	vmul;
1417 	int	sr15;
1418 	unsigned char hvsync_pulse;
1419 	char    TEXT;
1420 
1421 	/* identity */
1422 	gv = &md->gv;
1423 	TEXT = (gv->depth == 4);
1424 
1425 	if (!cl_mondefok(gv)) {
1426 		printf("grfcl: Monitor definition not ok\n");
1427 		return (0);
1428 	}
1429 
1430 	ba = gp->g_regkva;
1431 	fb = gp->g_fbkva;
1432 
1433 	/* provide all needed information in grf device-independent locations */
1434 	gp->g_data = (void *) gv;
1435 	gi = &gp->g_display;
1436 	gi->gd_regaddr = (void *) kvtop(__UNVOLATILE(ba));
1437 	gi->gd_regsize = 64 * 1024;
1438 	gi->gd_fbaddr = (void *) kvtop(__UNVOLATILE(fb));
1439 	gi->gd_fbsize = cl_fbsize;
1440 	gi->gd_colors = 1 << gv->depth;
1441 	gi->gd_planes = gv->depth;
1442 	gi->gd_fbwidth = gv->disp_width;
1443 	gi->gd_fbheight = gv->disp_height;
1444 	gi->gd_fbx = 0;
1445 	gi->gd_fby = 0;
1446 	if (TEXT) {
1447 		gi->gd_dwidth = md->fx * md->cols;
1448 		gi->gd_dheight = md->fy * md->rows;
1449 	} else {
1450 		gi->gd_dwidth = gv->disp_width;
1451 		gi->gd_dheight = gv->disp_height;
1452 	}
1453 	gi->gd_dx = 0;
1454 	gi->gd_dy = 0;
1455 
1456 	/* get display mode parameters */
1457 
1458 	HBS = gv->hblank_start;
1459 	HSS = gv->hsync_start;
1460 	HSE = gv->hsync_stop;
1461 	HBE = gv->htotal - 1;
1462 	HT = gv->htotal;
1463 	VBS = gv->vblank_start;
1464 	VSS = gv->vsync_start;
1465 	VSE = gv->vsync_stop;
1466 	VBE = gv->vtotal - 1;
1467 	VT = gv->vtotal;
1468 
1469 	if (TEXT)
1470 		HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1;
1471 	else
1472 		HDE = (gv->disp_width + 3) / 8 - 1;	/* HBS; */
1473 	VDE = gv->disp_height - 1;
1474 
1475 	/* adjustments */
1476 	switch (gv->depth) {
1477 	    case 8:
1478 		clkmul = 1;
1479 		clkmode = 0x0;
1480 		break;
1481 	    case 15:
1482 	    case 16:
1483 		clkmul = 1;
1484 		clkmode = 0x6;
1485 		break;
1486 	    case 24:
1487 		if ((cltype == PICASSO) && (cl_64bit == 1))	/* Picasso IV */
1488 			clkmul = 1;
1489 		else
1490 			clkmul = 3;
1491 		clkmode = 0x4;
1492 		break;
1493 	    case 32:
1494 		clkmul = 1;
1495 		clkmode = 0x8;
1496 		break;
1497 	    default:
1498 		clkmul = 1;
1499 		clkmode = 0x0;
1500 		break;
1501 	}
1502 
1503 	if ((VT > 1023) && (!(gv->disp_flags & GRF_FLAGS_LACE))) {
1504 		WCrt(ba, CRT_ID_MODE_CONTROL, 0xe7);
1505 	} else
1506 		WCrt(ba, CRT_ID_MODE_CONTROL, 0xe3);
1507 
1508 	vmul = 2;
1509 	if ((VT > 1023) || (gv->disp_flags & GRF_FLAGS_LACE))
1510 		vmul = 1;
1511 	if (gv->disp_flags & GRF_FLAGS_DBLSCAN)
1512 		vmul = 4;
1513 
1514 	VDE = VDE * vmul / 2;
1515 	VBS = VBS * vmul / 2;
1516 	VSS = VSS * vmul / 2;
1517 	VSE = VSE * vmul / 2;
1518 	VBE = VBE * vmul / 2;
1519 	VT  = VT * vmul / 2;
1520 
1521 	WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e);
1522 	if (cl_64bit == 1) {
1523 	    if (TEXT || (gv->depth == 1))
1524 		sr15 = 0xd0;
1525 	    else
1526 		sr15 = ((cl_fbsize / 0x100000 == 2) ? 0x38 : 0xb8);
1527 	    WSeq(ba, SEQ_ID_CONF_RBACK, 0x00);
1528 	} else {
1529 		sr15 = (TEXT || (gv->depth == 1)) ? 0xd0 : 0xb0;
1530 		sr15 &= ((cl_fbsize / 0x100000) == 2) ? 0xff : 0x7f;
1531 	}
1532 	WSeq(ba, SEQ_ID_DRAM_CNTL, sr15);
1533 	WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
1534 	WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff);
1535 	WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
1536 
1537 	/* Set clock */
1538 
1539 	cl_CompFQ(gv->pixel_clock * clkmul, &num0, &denom0, &clkdoub);
1540 
1541 	/* Horizontal/Vertical Sync Pulse */
1542 	hvsync_pulse = vgar(ba, GREG_MISC_OUTPUT_R);
1543 	if (gv->disp_flags & GRF_FLAGS_PHSYNC)
1544 		hvsync_pulse &= ~0x40;
1545 	else
1546 		hvsync_pulse |= 0x40;
1547 	if (gv->disp_flags & GRF_FLAGS_PVSYNC)
1548 		hvsync_pulse &= ~0x80;
1549 	else
1550 		hvsync_pulse |= 0x80;
1551 	vgaw(ba, GREG_MISC_OUTPUT_W, hvsync_pulse);
1552 
1553 	if (clkdoub) {
1554 		HDE /= 2;
1555 		HBS /= 2;
1556 		HSS /= 2;
1557 		HSE /= 2;
1558 		HBE /= 2;
1559 		HT  /= 2;
1560 		clkmode = 0x6;
1561 	}
1562 
1563 	WSeq(ba, SEQ_ID_VCLK_3_NUM, num0);
1564 	WSeq(ba, SEQ_ID_VCLK_3_DENOM, denom0);
1565 
1566 	/* load display parameters into board */
1567 
1568 	WCrt(ba, CRT_ID_HOR_TOTAL, HT);
1569 	WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? HBS - 1 : HDE));
1570 	WCrt(ba, CRT_ID_START_HOR_BLANK, HBS);
1571 	WCrt(ba, CRT_ID_END_HOR_BLANK, (HBE & 0x1f) | 0x80);	/* | 0x80? */
1572 	WCrt(ba, CRT_ID_START_HOR_RETR, HSS);
1573 	WCrt(ba, CRT_ID_END_HOR_RETR,
1574 	    (HSE & 0x1f) |
1575 	    ((HBE & 0x20) ? 0x80 : 0x00));
1576 	WCrt(ba, CRT_ID_VER_TOTAL, VT);
1577 	WCrt(ba, CRT_ID_OVERFLOW,
1578 	    0x10 |
1579 	    ((VT & 0x100) ? 0x01 : 0x00) |
1580 	    ((VDE & 0x100) ? 0x02 : 0x00) |
1581 	    ((VSS & 0x100) ? 0x04 : 0x00) |
1582 	    ((VBS & 0x100) ? 0x08 : 0x00) |
1583 	    ((VT & 0x200) ? 0x20 : 0x00) |
1584 	    ((VDE & 0x200) ? 0x40 : 0x00) |
1585 	    ((VSS & 0x200) ? 0x80 : 0x00));
1586 
1587 	WCrt(ba, CRT_ID_CHAR_HEIGHT,
1588 	    0x40 |		/* TEXT ? 0x00 ??? */
1589 	    ((gv->disp_flags & GRF_FLAGS_DBLSCAN) ? 0x80 : 0x00) |
1590 	    ((VBS & 0x200) ? 0x20 : 0x00) |
1591 	    (TEXT ? ((md->fy - 1) & 0x1f) : 0x00));
1592 
1593 	/* text cursor */
1594 
1595 	if (TEXT) {
1596 #if CL_ULCURSOR
1597 		WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2);
1598 		WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1);
1599 #else
1600 		WCrt(ba, CRT_ID_CURSOR_START, 0x00);
1601 		WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f);
1602 #endif
1603 		WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->fy - 1) & 0x1f);
1604 
1605 		WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
1606 		WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
1607 	}
1608 	WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
1609 	WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
1610 
1611 	WCrt(ba, CRT_ID_START_VER_RETR, VSS);
1612 	WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f) | 0x20);
1613 	WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE);
1614 	WCrt(ba, CRT_ID_START_VER_BLANK, VBS);
1615 	WCrt(ba, CRT_ID_END_VER_BLANK, VBE);
1616 
1617 	WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
1618 	WCrt(ba, CRT_ID_LACE_END, HT / 2);	/* MW/16 */
1619 	WCrt(ba, CRT_ID_LACE_CNTL,
1620 	    ((gv->disp_flags & GRF_FLAGS_LACE) ? 0x01 : 0x00) |
1621 	    ((HBE & 0x40) ? 0x10 : 0x00) |
1622 	    ((HBE & 0x80) ? 0x20 : 0x00) |
1623 	    ((VBE & 0x100) ? 0x40 : 0x00) |
1624 	    ((VBE & 0x200) ? 0x80 : 0x00));
1625 
1626 	WGfx(ba, GCT_ID_GRAPHICS_MODE,
1627 	    ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40));
1628 	WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
1629 
1630 	WSeq(ba, SEQ_ID_EXT_SEQ_MODE,
1631 	    ((TEXT || (gv->depth == 1)) ? 0x00 : 0x01) |
1632 	    ((cltype == PICASSO) ? 0x20 : 0x80) | clkmode);
1633 
1634 	/* write 0x00 to VDAC_MASK before accessing HDR this helps
1635 	   sometimes, out of "secret" application note (crest) */
1636 	vgaw(ba, VDAC_MASK, 0);
1637 	/* reset HDR "magic" access counter (crest) */
1638 	vgar(ba, VDAC_ADDRESS);
1639 
1640 	delay(200000);
1641 	vgar(ba, VDAC_MASK);
1642 	delay(200000);
1643 	vgar(ba, VDAC_MASK);
1644 	delay(200000);
1645 	vgar(ba, VDAC_MASK);
1646 	delay(200000);
1647 	vgar(ba, VDAC_MASK);
1648 	delay(200000);
1649 	switch (gv->depth) {
1650 	    case 1:
1651 	    case 4:		/* text */
1652 		vgaw(ba, VDAC_MASK, 0);
1653 		HDE = gv->disp_width / 16;
1654 		break;
1655 	    case 8:
1656 		if (clkdoub)
1657 			vgaw(ba, VDAC_MASK, 0x4a); /* Clockdouble Magic */
1658 		else
1659 			vgaw(ba, VDAC_MASK, 0);
1660 		HDE = gv->disp_width / 8;
1661 		break;
1662 	    case 15:
1663 		vgaw(ba, VDAC_MASK, 0xd0);
1664 		HDE = gv->disp_width / 4;
1665 		break;
1666 	    case 16:
1667 		vgaw(ba, VDAC_MASK, 0xc1);
1668 		HDE = gv->disp_width / 4;
1669 		break;
1670 	    case 24:
1671 		vgaw(ba, VDAC_MASK, 0xc5);
1672 		HDE = (gv->disp_width / 8) * 3;
1673 		break;
1674 	    case 32:
1675 		vgaw(ba, VDAC_MASK, 0xc5);
1676 		HDE = (gv->disp_width / 4);
1677 		break;
1678 	}
1679 
1680 	/* reset HDR "magic" access counter (crest) */
1681 	vgar(ba, VDAC_ADDRESS);
1682 	/* then enable all bit in VDAC_MASK afterwards (crest) */
1683 	vgaw(ba, VDAC_MASK, 0xff);
1684 
1685 	WCrt(ba, CRT_ID_OFFSET, HDE);
1686 	if (cl_64bit == 1) {
1687 		WCrt(ba, CRT_ID_SYNC_ADJ_GENLOCK, 0x00);
1688 		WCrt(ba, CRT_ID_OVERLAY_EXT_CTRL_REG, 0x40);
1689 	}
1690 	WCrt(ba, CRT_ID_EXT_DISP_CNTL,
1691 	    ((TEXT && gv->pixel_clock > 29000000) ? 0x40 : 0x00) |
1692 	    0x22 |
1693 	    ((HDE > 0xff) ? 0x10 : 0x00));
1694 
1695 	WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x0a : 0x01));
1696 	WAttr(ba, 0x20 | ACT_ID_COLOR_PLANE_ENA,
1697 	    (gv->depth == 1) ? 0x01 : 0x0f);
1698 
1699 	/* text initialization */
1700 
1701 	if (TEXT) {
1702 		cl_inittextmode(gp);
1703 	}
1704 	WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x14);
1705 	WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01);
1706 	cl_blanked = 0;
1707 
1708 	/* Pass-through */
1709 
1710 	RegOffpass(ba);
1711 
1712 	return (1);
1713 }
1714 
1715 void
1716 cl_inittextmode(struct grf_softc *gp)
1717 {
1718 	struct grfcltext_mode *tm = (struct grfcltext_mode *) gp->g_data;
1719 	volatile unsigned char *ba = gp->g_regkva;
1720 	unsigned char *fb = __UNVOLATILE(gp->g_fbkva);
1721 	unsigned char *c, *f, y;
1722 	unsigned short z;
1723 
1724 
1725 	/* load text font into beginning of display memory. Each character
1726 	 * cell is 32 bytes long (enough for 4 planes) */
1727 
1728 	SetTextPlane(ba, 0x02);
1729         cl_memset(fb, 0, 256 * 32);
1730 	c = (unsigned char *) (fb) + (32 * tm->fdstart);
1731 	f = tm->fdata;
1732 	for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy))
1733 		for (y = 0; y < tm->fy; y++)
1734 			*c++ = *f++;
1735 
1736 	/* clear out text/attr planes (three screens worth) */
1737 
1738 	SetTextPlane(ba, 0x01);
1739 	cl_memset(fb, 0x07, tm->cols * tm->rows * 3);
1740 	SetTextPlane(ba, 0x00);
1741 	cl_memset(fb, 0x20, tm->cols * tm->rows * 3);
1742 
1743 	/* print out a little init msg */
1744 
1745 	c = (unsigned char *) (fb) + (tm->cols - 16);
1746 	strcpy(c, "CIRRUS");
1747 	c[6] = 0x20;
1748 
1749 	/* set colors (B&W) */
1750 
1751 	vgaw(ba, VDAC_ADDRESS_W, 0);
1752 	for (z = 0; z < 256; z++) {
1753 		unsigned char r, g, b;
1754 
1755 		y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
1756 
1757 		if (cltype == PICASSO) {
1758 			r = clconscolors[y][0];
1759 			g = clconscolors[y][1];
1760 			b = clconscolors[y][2];
1761 		} else {
1762 			b = clconscolors[y][0];
1763 			g = clconscolors[y][1];
1764 			r = clconscolors[y][2];
1765 		}
1766 		vgaw(ba, VDAC_DATA, r >> 2);
1767 		vgaw(ba, VDAC_DATA, g >> 2);
1768 		vgaw(ba, VDAC_DATA, b >> 2);
1769 	}
1770 }
1771 
1772 void
1773 cl_memset(unsigned char *d, unsigned char c, int l)
1774 {
1775 	for (; l > 0; l--)
1776 		*d++ = c;
1777 }
1778 
1779 /*
1780  * Special wakeup/passthrough registers on graphics boards
1781  *
1782  * The methods have diverged a bit for each board, so
1783  * WPass(P) has been converted into a set of specific
1784  * inline functions.
1785  */
1786 static void
1787 RegWakeup(volatile void *ba)
1788 {
1789 
1790 	switch (cltype) {
1791 	    case SPECTRUM:
1792 		vgaw(ba, PASS_ADDRESS_W, 0x1f);
1793 		break;
1794 	    case PICASSO:
1795 		/* Picasso needs no wakeup */
1796 		break;
1797 	    case PICCOLO:
1798 		if (cl_64bit == 1)
1799 			vgaw(ba, PASS_ADDRESS_W, 0x1f);
1800 		else
1801 			vgaw(ba, PASS_ADDRESS_W, vgar(ba, PASS_ADDRESS) | 0x10);
1802 		break;
1803 	}
1804 	delay(200000);
1805 }
1806 
1807 static void
1808 RegOnpass(volatile void *ba)
1809 {
1810 
1811 	switch (cltype) {
1812 	    case SPECTRUM:
1813 		vgaw(ba, PASS_ADDRESS_W, 0x4f);
1814 		break;
1815 	    case PICASSO:
1816 		if (cl_64bit == 0)
1817 			vgaw(ba, PASS_ADDRESS_WP, 0x01);
1818 		break;
1819 	    case PICCOLO:
1820 		if (cl_64bit == 1)
1821 			vgaw(ba, PASS_ADDRESS_W, 0x4f);
1822 		else
1823 			vgaw(ba, PASS_ADDRESS_W, vgar(ba, PASS_ADDRESS) & 0xdf);
1824 		break;
1825 	}
1826 	cl_pass_toggle = 1;
1827 	delay(200000);
1828 }
1829 
1830 static void
1831 RegOffpass(volatile void *ba)
1832 {
1833 
1834 	switch (cltype) {
1835 	    case SPECTRUM:
1836 		vgaw(ba, PASS_ADDRESS_W, 0x6f);
1837 		break;
1838 	    case PICASSO:
1839 		if (cl_64bit == 0)
1840 			vgaw(ba, PASS_ADDRESS_W, 0xff);
1841 		break;
1842 	    case PICCOLO:
1843 		if (cl_64bit == 1)
1844 			vgaw(ba, PASS_ADDRESS_W, 0x6f);
1845 		else
1846 			vgaw(ba, PASS_ADDRESS_W, vgar(ba, PASS_ADDRESS) | 0x20);
1847 		break;
1848 	}
1849 	cl_pass_toggle = 0;
1850 	delay(200000);
1851 }
1852 
1853 #if NWSDISPLAY > 0
1854 static void
1855 cl_wscursor(void *c, int on, int row, int col)
1856 {
1857 	struct rasops_info *ri;
1858 	struct vcons_screen *scr;
1859 	struct grf_softc *gp;
1860 	volatile void *ba;
1861 	int offs;
1862 
1863 	ri = c;
1864 	scr = ri->ri_hw;
1865 	gp = scr->scr_cookie;
1866 	ba = gp->g_regkva;
1867 
1868 	if ((ri->ri_flg & RI_CURSOR) && !on) {
1869 		/* cursor was visible, but we want to remove it */
1870 		/*WCrt(ba, CRT_ID_CURSOR_START, | 0x20);*/
1871 		ri->ri_flg &= ~RI_CURSOR;
1872 	}
1873 
1874 	ri->ri_crow = row;
1875 	ri->ri_ccol = col;
1876 
1877 	if (on) {
1878 		/* move cursor to new location */
1879 		if (!(ri->ri_flg & RI_CURSOR)) {
1880 			/*WCrt(ba, CRT_ID_CURSOR_START, | 0x20);*/
1881 			ri->ri_flg |= RI_CURSOR;
1882 		}
1883 		offs = gp->g_rowoffset[row] + col;
1884 		WCrt(ba, CRT_ID_CURSOR_LOC_LOW, offs & 0xff);
1885 		WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, offs >> 8);
1886 	}
1887 }
1888 
1889 static void
1890 cl_wsputchar(void *c, int row, int col, u_int ch, long attr)
1891 {
1892 	struct rasops_info *ri;
1893 	struct vcons_screen *scr;
1894 	struct grf_softc *gp;
1895 	volatile unsigned char *ba, *cp;
1896 
1897 	ri = c;
1898 	scr = ri->ri_hw;
1899 	gp = scr->scr_cookie;
1900 	ba = gp->g_regkva;
1901 	cp = gp->g_fbkva;
1902 
1903 	cp += gp->g_rowoffset[row] + col;
1904 	SetTextPlane(ba, 0x00);
1905 	*cp = ch;
1906 	SetTextPlane(ba, 0x01);
1907 	*cp = attr;
1908 }
1909 
1910 static void
1911 cl_wscopycols(void *c, int row, int srccol, int dstcol, int ncols)
1912 {
1913 	volatile unsigned char *ba, *dst, *src;
1914 	struct rasops_info *ri;
1915 	struct vcons_screen *scr;
1916 	struct grf_softc *gp;
1917 	int i;
1918 
1919 	KASSERT(ncols > 0);
1920 	ri = c;
1921 	scr = ri->ri_hw;
1922 	gp = scr->scr_cookie;
1923 	ba = gp->g_regkva;
1924 	src = gp->g_fbkva;
1925 
1926 	src += gp->g_rowoffset[row];
1927 	dst = src;
1928 	src += srccol;
1929 	dst += dstcol;
1930 	if (srccol < dstcol) {
1931 		/* need to copy backwards */
1932 		src += ncols;
1933 		dst += ncols;
1934 		SetTextPlane(ba, 0x00);
1935 		for (i = 0; i < ncols; i++)
1936 			*(--dst) = *(--src);
1937 		src += ncols;
1938 		dst += ncols;
1939 		SetTextPlane(ba, 0x01);
1940 		for (i = 0; i < ncols; i++)
1941 			*(--dst) = *(--src);
1942 	} else {
1943 		SetTextPlane(ba, 0x00);
1944 		for (i = 0; i < ncols; i++)
1945 			*dst++ = *src++;
1946 		src -= ncols;
1947 		dst -= ncols;
1948 		SetTextPlane(ba, 0x01);
1949 		for (i = 0; i < ncols; i++)
1950 			*dst++ = *src++;
1951 	}
1952 }
1953 
1954 static void
1955 cl_wserasecols(void *c, int row, int startcol, int ncols, long fillattr)
1956 {
1957 	volatile unsigned char *ba, *cp;
1958 	struct rasops_info *ri;
1959 	struct vcons_screen *scr;
1960 	struct grf_softc *gp;
1961 	int i;
1962 
1963 	ri = c;
1964 	scr = ri->ri_hw;
1965 	gp = scr->scr_cookie;
1966 	ba = gp->g_regkva;
1967 	cp = gp->g_fbkva;
1968 
1969 	cp += gp->g_rowoffset[row] + startcol;
1970 	SetTextPlane(ba, 0x00);
1971 	for (i = 0; i < ncols; i++)
1972 		*cp++ = 0x20;
1973 	cp -= ncols;
1974 	SetTextPlane(ba, 0x01);
1975 	for (i = 0; i < ncols; i++)
1976 		*cp++ = 0x07;
1977 }
1978 
1979 static void
1980 cl_wscopyrows(void *c, int srcrow, int dstrow, int nrows)
1981 {
1982 	volatile unsigned char *ba, *dst, *src;
1983 	struct rasops_info *ri;
1984 	struct vcons_screen *scr;
1985 	struct grf_softc *gp;
1986 	int i, n;
1987 
1988 	KASSERT(nrows > 0);
1989 	ri = c;
1990 	scr = ri->ri_hw;
1991 	gp = scr->scr_cookie;
1992 	ba = gp->g_regkva;
1993 	src = dst = gp->g_fbkva;
1994 	n = ri->ri_cols * nrows;
1995 
1996 	if (srcrow < dstrow) {
1997 		/* need to copy backwards */
1998 		src += gp->g_rowoffset[srcrow + nrows];
1999 		dst += gp->g_rowoffset[dstrow + nrows];
2000 		SetTextPlane(ba, 0x00);
2001 		for (i = 0; i < n; i++)
2002 			*(--dst) = *(--src);
2003 		src += n;
2004 		dst += n;
2005 		SetTextPlane(ba, 0x01);
2006 		for (i = 0; i < n; i++)
2007 			*(--dst) = *(--src);
2008 	} else {
2009 		src += gp->g_rowoffset[srcrow];
2010 		dst += gp->g_rowoffset[dstrow];
2011 		SetTextPlane(ba, 0x00);
2012 		for (i = 0; i < n; i++)
2013 			*dst++ = *src++;
2014 		src -= n;
2015 		dst -= n;
2016 		SetTextPlane(ba, 0x01);
2017 		for (i = 0; i < n; i++)
2018 			*dst++ = *src++;
2019 	}
2020 }
2021 
2022 static void
2023 cl_wseraserows(void *c, int row, int nrows, long fillattr)
2024 {
2025 	volatile unsigned char *ba, *cp;
2026 	struct rasops_info *ri;
2027 	struct vcons_screen *scr;
2028 	struct grf_softc *gp;
2029 	int i, n;
2030 
2031 	ri = c;
2032 	scr = ri->ri_hw;
2033 	gp = scr->scr_cookie;
2034 	ba = gp->g_regkva;
2035 	cp = gp->g_fbkva;
2036 
2037 	cp += gp->g_rowoffset[row];
2038 	n = ri->ri_cols * nrows;
2039 	SetTextPlane(ba, 0x00);
2040 	for (i = 0; i < n; i++)
2041 		*cp++ = 0x20;
2042 	cp -= n;
2043 	SetTextPlane(ba, 0x01);
2044 	for (i = 0; i < n; i++)
2045 		*cp++ = 0x07;
2046 }
2047 
2048 static int
2049 cl_wsallocattr(void *c, int fg, int bg, int flg, long *attr)
2050 {
2051 
2052 	/* XXX color support? */
2053 	*attr = (flg & WSATTR_REVERSE) ? 0x70 : 0x07;
2054 	if (flg & WSATTR_UNDERLINE)	*attr = 0x01;
2055 	if (flg & WSATTR_HILIT)		*attr |= 0x08;
2056 	if (flg & WSATTR_BLINK)		*attr |= 0x80;
2057 	return 0;
2058 }
2059 
2060 /* our font does not support unicode extensions */
2061 static int
2062 cl_wsmapchar(void *c, int ch, unsigned int *cp)
2063 {
2064 
2065 	if (ch > 0 && ch < 256) {
2066 		*cp = ch;
2067 		return 5;
2068 	}
2069 	*cp = ' ';
2070 	return 0;
2071 }
2072 
2073 static int
2074 cl_wsioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
2075 {
2076 	struct vcons_data *vd;
2077 	struct grf_softc *gp;
2078 
2079 	vd = v;
2080 	gp = vd->cookie;
2081 
2082 	switch (cmd) {
2083 	case WSDISPLAYIO_GETCMAP:
2084 		/* Note: wsdisplay_cmap and grf_colormap have same format */
2085 		if (gp->g_display.gd_planes == 8)
2086 			return cl_getcmap(gp, (struct grf_colormap *)data);
2087 		return EINVAL;
2088 
2089 	case WSDISPLAYIO_PUTCMAP:
2090 		/* Note: wsdisplay_cmap and grf_colormap have same format */
2091 		if (gp->g_display.gd_planes == 8)
2092 			return cl_putcmap(gp, (struct grf_colormap *)data);
2093 		return EINVAL;
2094 
2095 	case WSDISPLAYIO_GVIDEO:
2096 		if (cl_isblank(gp))
2097 			*(u_int *)data = WSDISPLAYIO_VIDEO_OFF;
2098 		else
2099 			*(u_int *)data = WSDISPLAYIO_VIDEO_ON;
2100 		return 0;
2101 
2102 	case WSDISPLAYIO_SVIDEO:
2103 		return cl_blank(gp, *(u_int *)data == WSDISPLAYIO_VIDEO_ON);
2104 
2105 	case WSDISPLAYIO_SMODE:
2106 		if ((*(int *)data) != gp->g_wsmode) {
2107 			if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
2108 				/* load console text mode, redraw screen */
2109 				(void)cl_load_mon(gp, &clconsole_mode);
2110 				if (vd->active != NULL)
2111 					vcons_redraw_screen(vd->active);
2112 			} else {
2113 				/* switch to current graphics mode */
2114 				if (!cl_load_mon(gp,
2115 				    (struct grfcltext_mode *)monitor_current))
2116 					return EINVAL;
2117 			}
2118 			gp->g_wsmode = *(int *)data;
2119 		}
2120 		return 0;
2121 
2122 	case WSDISPLAYIO_GET_FBINFO:
2123 		return cl_get_fbinfo(gp, data);
2124 	}
2125 
2126 	/* handle this command hw-independant in grf(4) */
2127 	return grf_wsioctl(v, vs, cmd, data, flag, l);
2128 }
2129 
2130 /*
2131  * Fill the wsdisplayio_fbinfo structure with information from the current
2132  * graphics mode. Even when text mode is active.
2133  */
2134 static int
2135 cl_get_fbinfo(struct grf_softc *gp, struct wsdisplayio_fbinfo *fbi)
2136 {
2137 	struct grfvideo_mode *md;
2138 	uint32_t rbits, gbits, bbits;
2139 
2140 	md = monitor_current;
2141 
2142 	switch (md->depth) {
2143 	case 8:
2144 		fbi->fbi_bitsperpixel = 8;
2145 		rbits = gbits = bbits = 6;  /* keep gcc happy */
2146 		break;
2147 	case 15:
2148 		fbi->fbi_bitsperpixel = 16;
2149 		rbits = gbits = bbits = 5;
2150 		break;
2151 	case 16:
2152 		fbi->fbi_bitsperpixel = 16;
2153 		rbits = bbits = 5;
2154 		gbits = 6;
2155 		break;
2156 	case 24:
2157 		fbi->fbi_bitsperpixel = 24;
2158 		rbits = gbits = bbits = 8;
2159 		break;
2160 	default:
2161 		return EINVAL;
2162 	}
2163 
2164 	fbi->fbi_stride = (fbi->fbi_bitsperpixel / 8) * md->disp_width;
2165 	fbi->fbi_width = md->disp_width;
2166 	fbi->fbi_height = md->disp_height;
2167 
2168 	if (md->depth > 8) {
2169 		fbi->fbi_pixeltype = WSFB_RGB;
2170 		fbi->fbi_subtype.fbi_rgbmasks.red_offset = bbits + gbits;
2171 		fbi->fbi_subtype.fbi_rgbmasks.red_size = rbits;
2172 		fbi->fbi_subtype.fbi_rgbmasks.green_offset = bbits;
2173 		fbi->fbi_subtype.fbi_rgbmasks.green_size = gbits;
2174 		fbi->fbi_subtype.fbi_rgbmasks.blue_offset = 0;
2175 		fbi->fbi_subtype.fbi_rgbmasks.blue_size = bbits;
2176 		fbi->fbi_subtype.fbi_rgbmasks.alpha_offset = 0;
2177 		fbi->fbi_subtype.fbi_rgbmasks.alpha_size = 0;
2178 	} else {
2179 		fbi->fbi_pixeltype = WSFB_CI;
2180 		fbi->fbi_subtype.fbi_cmapinfo.cmap_entries = 1 << md->depth;
2181 	}
2182 
2183 	fbi->fbi_flags = 0;
2184 	fbi->fbi_fbsize = fbi->fbi_stride * fbi->fbi_height;
2185 	fbi->fbi_fboffset = 0;
2186 	return 0;
2187 }
2188 #endif	/* NWSDISPLAY > 0 */
2189 
2190 #endif /* NGRFCL */
2191