xref: /netbsd-src/sys/arch/amiga/dev/grf_cl.c (revision 2a73ef60b7f052dbb7ae5d4c3924cc286f1cc2bf)
1 /*      $NetBSD: grf_cl.c,v 1.13 1996/08/27 21:54:46 cgd Exp $        */
2 
3 /*
4  * Copyright (c) 1995 Ezra Story
5  * Copyright (c) 1995 Kari Mettinen
6  * Copyright (c) 1994 Markus Wild
7  * Copyright (c) 1994 Lutz Vieweg
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *      This product includes software developed by Lutz Vieweg.
21  * 4. The name of the author may not be used to endorse or promote products
22  *    derived from this software without specific prior written permission
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 #include "grfcl.h"
36 #if NGRFCL > 0
37 
38 /*
39  * Graphics routines for Cirrus CL GD 5426 boards,
40  *
41  * This code offers low-level routines to access Cirrus Cl GD 5426
42  * graphics-boards from within NetBSD for the Amiga.
43  * No warranties for any kind of function at all - this
44  * code may crash your hardware and scratch your harddisk.  Use at your
45  * own risk.  Freely distributable.
46  *
47  * Modified for Cirrus CL GD 5426 from
48  * Lutz Vieweg's retina driver by Kari Mettinen 08/94
49  * Contributions by Ill, ScottE, MiL
50  * Extensively hacked and rewritten by Ezra Story (Ezy) 01/95
51  * Picasso/040 patches (wee!) by crest 01/96
52  *
53  * Thanks to Village Tronic Marketing Gmbh for providing me with
54  * a Picasso-II board.
55  * Thanks for Integrated Electronics Oy Ab for providing me with
56  * Cirrus CL GD 542x family documentation.
57  *
58  * TODO:
59  *    Mouse support (almost there! :-))
60  *    Blitter support
61  *
62  */
63 
64 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/errno.h>
67 #include <sys/ioctl.h>
68 #include <sys/device.h>
69 #include <sys/malloc.h>
70 
71 #include <machine/cpu.h>
72 #include <dev/cons.h>
73 #include <amiga/dev/itevar.h>
74 #include <amiga/amiga/device.h>
75 #include <amiga/dev/grfioctl.h>
76 #include <amiga/dev/grfvar.h>
77 #include <amiga/dev/grf_clreg.h>
78 #include <amiga/dev/zbusvar.h>
79 
80 static int cl_mondefok __P((struct grfvideo_mode *));
81 static void cl_boardinit __P((struct grf_softc *));
82 static void cl_CompFQ __P((u_int, u_char *, u_char *));
83 static int cl_getvmode __P((struct grf_softc *, struct grfvideo_mode *));
84 static int cl_setvmode __P((struct grf_softc *, unsigned int));
85 static int cl_toggle __P((struct grf_softc *, unsigned short));
86 static int cl_getcmap __P((struct grf_softc *, struct grf_colormap *));
87 static int cl_putcmap __P((struct grf_softc *, struct grf_colormap *));
88 #ifndef CL5426CONSOLE
89 static void cl_off __P((struct grf_softc *));
90 #endif
91 static void cl_inittextmode __P((struct grf_softc *));
92 static int cl_ioctl __P((register struct grf_softc *, u_long, void *));
93 static int cl_getmousepos __P((struct grf_softc *, struct grf_position *));
94 static int cl_setmousepos __P((struct grf_softc *, struct grf_position *));
95 static int cl_setspriteinfo __P((struct grf_softc *, struct grf_spriteinfo *));
96 static int cl_getspriteinfo __P((struct grf_softc *, struct grf_spriteinfo *));
97 static int cl_getspritemax __P((struct grf_softc *, struct grf_position *));
98 static int cl_blank __P((struct grf_softc *, int *));
99 int cl_setmonitor __P((struct grf_softc *, struct grfvideo_mode *));
100 void cl_writesprpos __P((volatile char *, short, short));
101 void writeshifted __P((volatile char *, char, char));
102 
103 void grfclattach __P((struct device *, struct device *, void *));
104 int grfclprint __P((void *, const char *));
105 int grfclmatch __P((struct device *, void *, void *));
106 void cl_memset __P((unsigned char *, unsigned char, int));
107 
108 /* Graphics display definitions.
109  * These are filled by 'grfconfig' using GRFIOCSETMON.
110  */
111 #define monitor_def_max 8
112 static struct grfvideo_mode monitor_def[8] = {
113 	{0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}
114 };
115 static struct grfvideo_mode *monitor_current = &monitor_def[0];
116 
117 /* Patchable maximum pixel clock */
118 unsigned long cl_maxpixelclock = 86000000;
119 
120 /* Console display definition.
121  *   Default hardcoded text mode.  This grf_cl is set up to
122  *   use one text mode only, and this is it.  You may use
123  *   grfconfig to change the mode after boot.
124  */
125 /* Console font */
126 #ifdef KFONT_8X11
127 #define CIRRUSFONT kernel_font_8x11
128 #define CIRRUSFONTY 11
129 #else
130 #define CIRRUSFONT kernel_font_8x8
131 #define CIRRUSFONTY 8
132 #endif
133 extern unsigned char CIRRUSFONT[];
134 
135 struct grfcltext_mode clconsole_mode = {
136 	{255, "", 25200000, 640, 480, 4, 80, 100, 94, 99, 100, 481, 522, 490,
137 	498, 522},
138 	8, CIRRUSFONTY, 80, 480 / CIRRUSFONTY, CIRRUSFONT, 32, 255
139 };
140 /* Console colors */
141 unsigned char clconscolors[3][3] = {	/* background, foreground, hilite */
142 	{0, 0x40, 0x50}, {152, 152, 152}, {255, 255, 255}
143 };
144 
145 int	cltype = 0;		/* Picasso, Spectrum or Piccolo */
146 int	cl_sd64 = 0;
147 unsigned char pass_toggle;	/* passthru status tracker */
148 
149 /* because all 5426-boards have 2 configdev entries, one for
150  * framebuffer mem and the other for regs, we have to hold onto
151  * the pointers globally until we match on both.  This and 'cltype'
152  * are the primary obsticles to multiple board support, but if you
153  * have multiple boards you have bigger problems than grf_cl.
154  */
155 static void *cl_fbaddr = 0;	/* framebuffer */
156 static void *cl_regaddr = 0;	/* registers */
157 static int cl_fbsize;		/* framebuffer size */
158 
159 /* current sprite info, if you add summport for multiple boards
160  * make this an array or something
161  */
162 struct grf_spriteinfo cl_cursprite;
163 
164 /* sprite bitmaps in kernel stack, you'll need to arrayize these too if
165  * you add multiple board support
166  */
167 static unsigned char cl_imageptr[8 * 64], cl_maskptr[8 * 64];
168 static unsigned char cl_sprred[2], cl_sprgreen[2], cl_sprblue[2];
169 
170 /* standard driver stuff */
171 struct cfattach grfcl_ca = {
172 	sizeof(struct grf_softc), grfclmatch, grfclattach
173 };
174 
175 struct cfdriver grfcl_cd = {
176 	NULL, "grfcl", DV_DULL, NULL, 0
177 };
178 static struct cfdata *cfdata;
179 
180 int
181 grfclmatch(pdp, match, auxp)
182 	struct device *pdp;
183 	void   *match, *auxp;
184 {
185 #ifdef CL5426CONSOLE
186 	struct cfdata *cfp = match;
187 #endif
188 	struct zbus_args *zap;
189 	static int regprod, fbprod;
190 	int error;
191 
192 	zap = auxp;
193 
194 #ifndef CL5426CONSOLE
195 	if (amiga_realconfig == 0)
196 		return (0);
197 #endif
198 
199 	/* Grab the first board we encounter as the preferred one.  This will
200 	 * allow one board to work in a multiple 5426 board system, but not
201 	 * multiple boards at the same time.  */
202 	if (cltype == 0) {
203 		switch (zap->manid) {
204 		    case PICASSO:
205 			if (zap->prodid != 12 && zap->prodid != 11)
206 				return (0);
207 			regprod = 12;
208 			fbprod = 11;
209 			break;
210 		    case SPECTRUM:
211 			if (zap->prodid != 2 && zap->prodid != 1)
212 				return (0);
213 			regprod = 2;
214 			fbprod = 1;
215 			break;
216 		    case PICCOLO:
217 			switch (zap->prodid) {
218 			    case 5:
219 			    case 6:
220 				regprod = 6;
221 				fbprod = 5;
222 				error = 0;
223 				break;
224 			    case 10:
225 			    case 11:
226 				regprod = 11;
227 				fbprod = 10;
228 				cl_sd64 = 1;
229 				error = 0;
230 				break;
231 		    	    default:
232 				error = 1;
233 				break;
234 			}
235 			if (error == 1)
236 			    return (0);
237 			else
238 			    break;
239 		    default:
240 			return (0);
241 		}
242 		cltype = zap->manid;
243 	} else {
244 		if (cltype != zap->manid) {
245 			return (0);
246 		}
247 	}
248 
249 	/* Configure either registers or framebuffer in any order */
250 	if (zap->prodid == regprod)
251 		cl_regaddr = zap->va;
252 	else
253 		if (zap->prodid == fbprod) {
254 			cl_fbaddr = zap->va;
255 			cl_fbsize = zap->size;
256 		} else
257 			return (0);
258 
259 #ifdef CL5426CONSOLE
260 	if (amiga_realconfig == 0) {
261 		cfdata = cfp;
262 	}
263 #endif
264 
265 	return (1);
266 }
267 
268 void
269 grfclattach(pdp, dp, auxp)
270 	struct device *pdp, *dp;
271 	void   *auxp;
272 {
273 	static struct grf_softc congrf;
274 	struct zbus_args *zap;
275 	struct grf_softc *gp;
276 	static char attachflag = 0;
277 
278 	zap = auxp;
279 
280 	printf("\n");
281 
282 	/* make sure both halves have matched */
283 	if (!cl_regaddr || !cl_fbaddr)
284 		return;
285 
286 	/* do all that messy console/grf stuff */
287 	if (dp == NULL)
288 		gp = &congrf;
289 	else
290 		gp = (struct grf_softc *) dp;
291 
292 	if (dp != NULL && congrf.g_regkva != 0) {
293 		/*
294 		 * inited earlier, just copy (not device struct)
295 		 */
296 		bcopy(&congrf.g_display, &gp->g_display,
297 		    (char *) &gp[1] - (char *) &gp->g_display);
298 	} else {
299 		gp->g_regkva = (volatile caddr_t) cl_regaddr;
300 		gp->g_fbkva = (volatile caddr_t) cl_fbaddr;
301 
302 		gp->g_unit = GRF_CL5426_UNIT;
303 		gp->g_mode = cl_mode;
304 		gp->g_conpri = grfcl_cnprobe();
305 		gp->g_flags = GF_ALIVE;
306 
307 		/* wakeup the board */
308 		cl_boardinit(gp);
309 
310 #ifdef CL5426CONSOLE
311 		grfcl_iteinit(gp);
312 		(void) cl_load_mon(gp, &clconsole_mode);
313 #endif
314 
315 	}
316 
317 	/*
318 	 * attach grf (once)
319 	 */
320 	if (amiga_config_found(cfdata, &gp->g_device, gp, grfclprint)) {
321 		attachflag = 1;
322 		printf("grfcl: %dMB ", cl_fbsize / 0x100000);
323 		switch (cltype) {
324 		    case PICASSO:
325 			printf("Picasso II");
326                         cl_maxpixelclock = 86000000;
327 			break;
328 		    case SPECTRUM:
329 			printf("Spectrum");
330                         cl_maxpixelclock = 90000000;
331 			break;
332 		    case PICCOLO:
333 			if (cl_sd64 == 1) {
334 				printf("Piccolo SD64");
335 				/* 110MHz will be supported if we
336 				 * have a palette doubling mode.
337 				 */
338 				cl_maxpixelclock = 90000000;
339 			} else {
340 				printf("Piccolo");
341 				cl_maxpixelclock = 90000000;
342 			}
343 			break;
344 		}
345 		printf(" being used\n");
346 #ifdef CL_OVERCLOCK
347                 cl_maxpixelclock = 115000000;
348 #endif
349 	} else {
350 		if (!attachflag)
351 			printf("grfcl unattached!!\n");
352 	}
353 }
354 
355 int
356 grfclprint(auxp, pnp)
357 	void   *auxp;
358 	const char *pnp;
359 {
360 	if (pnp)
361 		printf("ite at %s: ", pnp);
362 	return (UNCONF);
363 }
364 
365 void
366 cl_boardinit(gp)
367 	struct grf_softc *gp;
368 {
369 	unsigned char *ba = gp->g_regkva;
370 	int     x;
371 
372 	/* wakeup board and flip passthru OFF */
373 
374 	RegWakeup(ba);
375 	RegOnpass(ba);
376 
377 	vgaw(ba, 0x46e8, 0x16);
378 	vgaw(ba, 0x102, 1);
379 	vgaw(ba, 0x46e8, 0x0e);
380 	vgaw(ba, 0x3c3, 1);
381 
382 	/* setup initial unchanging parameters */
383 
384 	WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21);	/* 8 dot - display off */
385 	vgaw(ba, GREG_MISC_OUTPUT_W, 0xed);	/* mem disable */
386 
387 	WGfx(ba, GCT_ID_OFFSET_1, 0xec);	/* magic cookie */
388 	WSeq(ba, SEQ_ID_UNLOCK_EXT, 0x12);	/* yum! cookies! */
389 
390 	if (cl_sd64 == 1) {
391 		WSeq(ba, SEQ_ID_CONF_RBACK, 0x00);
392 		WSeq(ba, SEQ_ID_DRAM_CNTL, (cl_fbsize / 0x100000 == 2) ? 0x38 : 0xb8);
393 	} else {
394 		WSeq(ba, SEQ_ID_DRAM_CNTL, 0xb0);
395 	}
396 	WSeq(ba, SEQ_ID_RESET, 0x03);
397 	WSeq(ba, SEQ_ID_MAP_MASK, 0xff);
398 	WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
399 	WSeq(ba, SEQ_ID_MEMORY_MODE, 0x0e);	/* a or 6? */
400 	WSeq(ba, SEQ_ID_EXT_SEQ_MODE, (cltype == PICASSO) ? 0x20 : 0x80);
401 	WSeq(ba, SEQ_ID_EEPROM_CNTL, 0x00);
402 	WSeq(ba, SEQ_ID_PERF_TUNE, 0x0a);	/* mouse 0a fa */
403 	WSeq(ba, SEQ_ID_SIG_CNTL, 0x02);
404 	WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x04);
405 
406 	WSeq(ba, SEQ_ID_MCLK_SELECT, 0x22);
407 
408 	WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00);
409 	WCrt(ba, CRT_ID_CURSOR_START, 0x00);
410 	WCrt(ba, CRT_ID_CURSOR_END, 0x08);
411 	WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
412 	WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
413 	WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
414 	WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
415 
416 	WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x07);
417 	WCrt(ba, CRT_ID_MODE_CONTROL, 0xa3);	/* c3 */
418 	WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);	/* ff */
419 	WCrt(ba, CRT_ID_EXT_DISP_CNTL, 0x22);
420 	if (cl_sd64 == 1) {
421 		WCrt(ba, CRT_ID_SYNC_ADJ_GENLOCK, 0x00);
422 		WCrt(ba, CRT_ID_OVERLAY_EXT_CTRL_REG, 0x40);
423 	}
424 	WSeq(ba, SEQ_ID_CURSOR_STORE, 0x3c);	/* mouse 0x00 */
425 
426 	WGfx(ba, GCT_ID_SET_RESET, 0x00);
427 	WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
428 	WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
429 	WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
430 	WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x00);
431 	WGfx(ba, GCT_ID_MISC, 0x01);
432 	WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f);
433 	WGfx(ba, GCT_ID_BITMASK, 0xff);
434 	WGfx(ba, GCT_ID_MODE_EXT, 0x28);
435 
436 	for (x = 0; x < 0x10; x++)
437 		WAttr(ba, x, x);
438 	WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x01);
439 	WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00);
440 	WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
441 	WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
442 	WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
443 
444 	delay(200000);
445 	WAttr(ba, 0x34, 0x00);
446 	delay(200000);
447 
448 	vgaw(ba, VDAC_MASK, 0xff);
449 	delay(200000);
450 	vgaw(ba, GREG_MISC_OUTPUT_W, 0xef);
451 
452 	WGfx(ba, GCT_ID_BLT_STAT_START, 0x40);
453 	WGfx(ba, GCT_ID_BLT_STAT_START, 0x00);
454 
455 	/* colors initially set to greyscale */
456 
457 	vgaw(ba, VDAC_ADDRESS_W, 0);
458 	for (x = 255; x >= 0; x--) {
459 		vgaw(ba, VDAC_DATA, x);
460 		vgaw(ba, VDAC_DATA, x);
461 		vgaw(ba, VDAC_DATA, x);
462 	}
463 	/* set sprite bitmap pointers */
464 	cl_cursprite.image = cl_imageptr;
465 	cl_cursprite.mask = cl_maskptr;
466 	cl_cursprite.cmap.red = cl_sprred;
467 	cl_cursprite.cmap.green = cl_sprgreen;
468 	cl_cursprite.cmap.blue = cl_sprblue;
469 }
470 
471 
472 int
473 cl_getvmode(gp, vm)
474 	struct grf_softc *gp;
475 	struct grfvideo_mode *vm;
476 {
477 	struct grfvideo_mode *gv;
478 
479 #ifdef CL5426CONSOLE
480 	/* Handle grabbing console mode */
481 	if (vm->mode_num == 255) {
482 		bcopy(&clconsole_mode, vm, sizeof(struct grfvideo_mode));
483 		/* XXX so grfconfig can tell us the correct text dimensions. */
484 		vm->depth = clconsole_mode.fy;
485 	} else
486 #endif
487         {
488                 if (vm->mode_num == 0)
489                         vm->mode_num = (monitor_current - monitor_def) + 1;
490                 if (vm->mode_num < 1 || vm->mode_num > monitor_def_max)
491                         return (EINVAL);
492                 gv = monitor_def + (vm->mode_num - 1);
493                 if (gv->mode_num == 0)
494                         return (EINVAL);
495 
496                 bcopy(gv, vm, sizeof(struct grfvideo_mode));
497         }
498 
499         /* adjust internal values to pixel values */
500 
501         vm->hblank_start *= 8;
502         vm->hblank_stop *= 8;
503         vm->hsync_start *= 8;
504         vm->hsync_stop *= 8;
505         vm->htotal *= 8;
506 
507 	return (0);
508 }
509 
510 
511 int
512 cl_setvmode(gp, mode)
513 	struct grf_softc *gp;
514 	unsigned mode;
515 {
516 	if (!mode || (mode > monitor_def_max) ||
517 	    monitor_def[mode - 1].mode_num == 0)
518 		return (EINVAL);
519 
520 	monitor_current = monitor_def + (mode - 1);
521 
522 	return (0);
523 }
524 
525 #ifndef CL5426CONSOLE
526 void
527 cl_off(gp)
528 	struct grf_softc *gp;
529 {
530 	char   *ba = gp->g_regkva;
531 
532 	/* we'll put the pass-through on for cc ite and set Full Bandwidth bit
533 	 * on just in case it didn't work...but then it doesn't matter does
534 	 * it? =) */
535 	RegOnpass(ba);
536 	WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21);
537 }
538 #endif
539 
540 int
541 cl_blank(gp, on)
542         struct grf_softc *gp;
543         int *on;
544 {
545         WSeq(gp->g_regkva, SEQ_ID_CLOCKING_MODE, *on > 0 ? 0x01 : 0x21);
546         return(0);
547 }
548 
549 /*
550  * Change the mode of the display.
551  * Return a UNIX error number or 0 for success.
552  */
553 int
554 cl_mode(gp, cmd, arg, a2, a3)
555 	register struct grf_softc *gp;
556 	u_long cmd;
557 	void *arg;
558 	u_long a2;
559 	int a3;
560 {
561 	int     error;
562 
563 	switch (cmd) {
564 	    case GM_GRFON:
565 		error = cl_load_mon(gp,
566 		    (struct grfcltext_mode *) monitor_current) ? 0 : EINVAL;
567 		return (error);
568 
569 	    case GM_GRFOFF:
570 #ifndef CL5426CONSOLE
571 		cl_off(gp);
572 #else
573 		cl_load_mon(gp, &clconsole_mode);
574 #endif
575 		return (0);
576 
577 	    case GM_GRFCONFIG:
578 		return (0);
579 
580 	    case GM_GRFGETVMODE:
581 		return (cl_getvmode(gp, (struct grfvideo_mode *) arg));
582 
583 	    case GM_GRFSETVMODE:
584 		error = cl_setvmode(gp, *(unsigned *) arg);
585 		if (!error && (gp->g_flags & GF_GRFON))
586 			cl_load_mon(gp,
587 			    (struct grfcltext_mode *) monitor_current);
588 		return (error);
589 
590 	    case GM_GRFGETNUMVM:
591 		*(int *) arg = monitor_def_max;
592 		return (0);
593 
594 	    case GM_GRFIOCTL:
595 		return (cl_ioctl(gp, a2, arg));
596 
597 	    default:
598 		break;
599 	}
600 
601 	return (EINVAL);
602 }
603 
604 int
605 cl_ioctl(gp, cmd, data)
606 	register struct grf_softc *gp;
607 	u_long cmd;
608 	void   *data;
609 {
610 	switch (cmd) {
611 	    case GRFIOCGSPRITEPOS:
612 		return (cl_getmousepos(gp, (struct grf_position *) data));
613 
614 	    case GRFIOCSSPRITEPOS:
615 		return (cl_setmousepos(gp, (struct grf_position *) data));
616 
617 	    case GRFIOCSSPRITEINF:
618 		return (cl_setspriteinfo(gp, (struct grf_spriteinfo *) data));
619 
620 	    case GRFIOCGSPRITEINF:
621 		return (cl_getspriteinfo(gp, (struct grf_spriteinfo *) data));
622 
623 	    case GRFIOCGSPRITEMAX:
624 		return (cl_getspritemax(gp, (struct grf_position *) data));
625 
626 	    case GRFIOCGETCMAP:
627 		return (cl_getcmap(gp, (struct grf_colormap *) data));
628 
629 	    case GRFIOCPUTCMAP:
630 		return (cl_putcmap(gp, (struct grf_colormap *) data));
631 
632 	    case GRFIOCBITBLT:
633 		break;
634 
635 	    case GRFTOGGLE:
636 		return (cl_toggle(gp, 0));
637 
638 	    case GRFIOCSETMON:
639 		return (cl_setmonitor(gp, (struct grfvideo_mode *) data));
640 
641             case GRFIOCBLANK:
642                 return (cl_blank(gp, (int *)data));
643 
644 	}
645 	return (EINVAL);
646 }
647 
648 int
649 cl_getmousepos(gp, data)
650 	struct grf_softc *gp;
651 	struct grf_position *data;
652 {
653 	data->x = cl_cursprite.pos.x;
654 	data->y = cl_cursprite.pos.y;
655 	return (0);
656 }
657 
658 void
659 cl_writesprpos(ba, x, y)
660 	volatile char *ba;
661 	short   x;
662 	short   y;
663 {
664 	/* we want to use a 16-bit write to 3c4 so no macros used */
665 	volatile unsigned char *cwp;
666         volatile unsigned short *wp;
667 
668 	cwp = ba + 0x3c4;
669         wp = (unsigned short *)cwp;
670 
671 	/* don't ask me why, but apparently you can't do a 16-bit write with
672 	 * x-position like with y-position below (dagge) */
673         cwp[0] = 0x10 | ((x << 5) & 0xff);
674         cwp[1] = (x >> 3) & 0xff;
675 
676         *wp = 0x1100 | ((y & 7) << 13) | ((y >> 3) & 0xff);
677 
678 }
679 
680 void
681 writeshifted(to, shiftx, shifty)
682 	volatile char *to;
683 	char    shiftx;
684 	char    shifty;
685 {
686 	register char y;
687 	unsigned long long *tptr, *iptr, *mptr, line;
688 
689 	tptr = (unsigned long long *) to;
690         iptr = (unsigned long long *) cl_cursprite.image;
691         mptr = (unsigned long long *) cl_cursprite.mask;
692 
693         shiftx = shiftx < 0 ? 0 : shiftx;
694         shifty = shifty < 0 ? 0 : shifty;
695 
696         /* start reading shifty lines down, and
697          * shift each line in by shiftx
698          */
699         for (y = shifty; y < 64; y++) {
700 
701                 /* image */
702                 line = iptr[y];
703 		*tptr++ = line << shiftx;
704 
705                 /* mask */
706                 line = mptr[y];
707 		*tptr++ = line << shiftx;
708 	}
709 
710         /* clear the remainder */
711         for (y = shifty; y > 0; y--) {
712                 *tptr++ = 0;
713                 *tptr++ = 0;
714         }
715 }
716 
717 int
718 cl_setmousepos(gp, data)
719 	struct grf_softc *gp;
720 	struct grf_position *data;
721 {
722 	volatile char *ba = gp->g_regkva;
723         short rx, ry, prx, pry;
724 #ifdef CL_SHIFTSPRITE
725 	volatile char *fb = gp->g_fbkva;
726         volatile char *sprite = fb + (cl_fbsize - 1024);
727 #endif
728 
729         /* no movement */
730 	if (cl_cursprite.pos.x == data->x && cl_cursprite.pos.y == data->y)
731 		return (0);
732 
733         /* current and previous real coordinates */
734 	rx = data->x - cl_cursprite.hot.x;
735 	ry = data->y - cl_cursprite.hot.y;
736 	prx = cl_cursprite.pos.x - cl_cursprite.hot.x;
737 	pry = cl_cursprite.pos.y - cl_cursprite.hot.y;
738 
739         /* if we are/were on an edge, create (un)shifted bitmap --
740          * ripped out optimization (not extremely worthwhile,
741          * and kind of buggy anyhow).
742          */
743 #ifdef CL_SHIFTSPRITE
744         if (rx < 0 || ry < 0 || prx < 0 || pry < 0) {
745                 writeshifted(sprite, rx < 0 ? -rx : 0, ry < 0 ? -ry : 0);
746         }
747 #endif
748 
749         /* do movement, save position */
750         cl_writesprpos(ba, rx < 0 ? 0 : rx, ry < 0 ? 0 : ry);
751 	cl_cursprite.pos.x = data->x;
752 	cl_cursprite.pos.y = data->y;
753 
754 	return (0);
755 }
756 
757 int
758 cl_getspriteinfo(gp, data)
759 	struct grf_softc *gp;
760 	struct grf_spriteinfo *data;
761 {
762 	copyout(&cl_cursprite, data, sizeof(struct grf_spriteinfo));
763 	copyout(cl_cursprite.image, data->image, 64 * 8);
764 	copyout(cl_cursprite.mask, data->mask, 64 * 8);
765 	return (0);
766 }
767 
768 static
769 int
770 cl_setspriteinfo(gp, data)
771 	struct grf_softc *gp;
772 	struct grf_spriteinfo *data;
773 {
774 	volatile unsigned char *ba = gp->g_regkva, *fb = gp->g_fbkva;
775         volatile char *sprite = fb + (cl_fbsize - 1024);
776 
777 	if (data->set & GRFSPRSET_SHAPE) {
778 
779                 short dsx, dsy, i;
780                 unsigned long *di, *dm, *si, *sm;
781                 unsigned long ssi[128], ssm[128];
782                 struct grf_position gpos;
783 
784 
785                 /* check for a too large sprite (no clipping!) */
786                 dsy = data->size.y;
787                 dsx = data->size.x;
788                 if (dsy > 64 || dsx > 64)
789                         return(EINVAL);
790 
791                 /* prepare destination */
792                 di = (unsigned long *)cl_cursprite.image;
793                 dm = (unsigned long *)cl_cursprite.mask;
794                 cl_memset((unsigned char *)di, 0, 8*64);
795                 cl_memset((unsigned char *)dm, 0, 8*64);
796 
797                 /* two alternatives:  64 across, then it's
798                  * the same format we use, just copy.  Otherwise,
799                  * copy into tmp buf and recopy skipping the
800                  * unused 32 bits.
801                  */
802                 if ((dsx - 1) / 32) {
803                         copyin(data->image, di, 8 * dsy);
804                         copyin(data->mask, dm, 8 * dsy);
805                 } else {
806                         si = ssi; sm = ssm;
807                         copyin(data->image, si, 4 * dsy);
808                         copyin(data->mask, sm, 4 * dsy);
809                         for (i = 0; i < dsy; i++) {
810                                 *di = *si++;
811                                 *dm = *sm++;
812                                 di += 2;
813                                 dm += 2;
814                         }
815                 }
816 
817                 /* set size */
818 		cl_cursprite.size.x = data->size.x;
819 		cl_cursprite.size.y = data->size.y;
820 
821                 /* forcably load into board */
822                 gpos.x = cl_cursprite.pos.x;
823                 gpos.y = cl_cursprite.pos.y;
824                 cl_cursprite.pos.x = -1;
825                 cl_cursprite.pos.y = -1;
826                 writeshifted(sprite, 0, 0);
827                 cl_setmousepos(gp, &gpos);
828 
829 	}
830 	if (data->set & GRFSPRSET_HOT) {
831 
832 		cl_cursprite.hot = data->hot;
833 
834 	}
835 	if (data->set & GRFSPRSET_CMAP) {
836 
837 		u_char  red[2], green[2], blue[2];
838 
839 		copyin(data->cmap.red, red, 2);
840 		copyin(data->cmap.green, green, 2);
841 		copyin(data->cmap.blue, blue, 2);
842 		bcopy(red, cl_cursprite.cmap.red, 2);
843 		bcopy(green, cl_cursprite.cmap.green, 2);
844 		bcopy(blue, cl_cursprite.cmap.blue, 2);
845 
846                 /* enable and load colors 256 & 257 */
847 		WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x06);
848 
849                 /* 256 */
850 		vgaw(ba, VDAC_ADDRESS_W, 0x00);
851 		if (cltype == PICASSO) {
852 			vgaw(ba, VDAC_DATA, (u_char) (red[0] >> 2));
853 			vgaw(ba, VDAC_DATA, (u_char) (green[0] >> 2));
854 			vgaw(ba, VDAC_DATA, (u_char) (blue[0] >> 2));
855 		} else {
856 			vgaw(ba, VDAC_DATA, (u_char) (blue[0] >> 2));
857 			vgaw(ba, VDAC_DATA, (u_char) (green[0] >> 2));
858 			vgaw(ba, VDAC_DATA, (u_char) (red[0] >> 2));
859 		}
860 
861                 /* 257 */
862 		vgaw(ba, VDAC_ADDRESS_W, 0x0f);
863 		if (cltype == PICASSO) {
864 			vgaw(ba, VDAC_DATA, (u_char) (red[1] >> 2));
865 			vgaw(ba, VDAC_DATA, (u_char) (green[1] >> 2));
866 			vgaw(ba, VDAC_DATA, (u_char) (blue[1] >> 2));
867 		} else {
868 			vgaw(ba, VDAC_DATA, (u_char) (blue[1] >> 2));
869 			vgaw(ba, VDAC_DATA, (u_char) (green[1] >> 2));
870 			vgaw(ba, VDAC_DATA, (u_char) (red[1] >> 2));
871 		}
872 
873                 /* turn on/off sprite */
874 		if (cl_cursprite.enable) {
875 			WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x05);
876 		} else {
877 			WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x04);
878 		}
879 
880 	}
881 	if (data->set & GRFSPRSET_ENABLE) {
882 
883 		if (data->enable == 1) {
884 			WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x05);
885 			cl_cursprite.enable = 1;
886 		} else {
887 			WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x04);
888 			cl_cursprite.enable = 0;
889 		}
890 
891 	}
892 	if (data->set & GRFSPRSET_POS) {
893 
894                 /* force placement */
895                 cl_cursprite.pos.x = -1;
896                 cl_cursprite.pos.y = -1;
897 
898                 /* do it */
899                 cl_setmousepos(gp, &data->pos);
900 
901 	}
902 	return (0);
903 }
904 
905 static
906 int
907 cl_getspritemax(gp, data)
908 	struct grf_softc *gp;
909 	struct grf_position *data;
910 {
911 	if (gp->g_display.gd_planes == 24)
912 		return (EINVAL);
913 	data->x = 64;
914 	data->y = 64;
915 	return (0);
916 }
917 
918 int
919 cl_setmonitor(gp, gv)
920 	struct grf_softc *gp;
921 	struct grfvideo_mode *gv;
922 {
923 	struct grfvideo_mode *md;
924 
925         if (!cl_mondefok(gv))
926                 return(EINVAL);
927 
928 #ifdef CL5426CONSOLE
929 	/* handle interactive setting of console mode */
930 	if (gv->mode_num == 255) {
931 		bcopy(gv, &clconsole_mode.gv, sizeof(struct grfvideo_mode));
932                 clconsole_mode.gv.hblank_start /= 8;
933                 clconsole_mode.gv.hblank_stop /= 8;
934                 clconsole_mode.gv.hsync_start /= 8;
935                 clconsole_mode.gv.hsync_stop /= 8;
936                 clconsole_mode.gv.htotal /= 8;
937 		clconsole_mode.rows = gv->disp_height / clconsole_mode.fy;
938 		clconsole_mode.cols = gv->disp_width / clconsole_mode.fx;
939 		if (!(gp->g_flags & GF_GRFON))
940 			cl_load_mon(gp, &clconsole_mode);
941 		ite_reinit(gp->g_itedev);
942 		return (0);
943 	}
944 #endif
945 
946 	md = monitor_def + (gv->mode_num - 1);
947 	bcopy(gv, md, sizeof(struct grfvideo_mode));
948 
949         /* adjust pixel oriented values to internal rep. */
950 
951         md->hblank_start /= 8;
952         md->hblank_stop /= 8;
953         md->hsync_start /= 8;
954         md->hsync_stop /= 8;
955         md->htotal /= 8;
956 
957 	return (0);
958 }
959 
960 int
961 cl_getcmap(gfp, cmap)
962 	struct grf_softc *gfp;
963 	struct grf_colormap *cmap;
964 {
965 	volatile unsigned char *ba;
966 	u_char  red[256], green[256], blue[256], *rp, *gp, *bp;
967 	short   x;
968 	int     error;
969 
970 	if (cmap->count == 0 || cmap->index >= 256)
971 		return 0;
972 
973 	if (cmap->index + cmap->count > 256)
974 		cmap->count = 256 - cmap->index;
975 
976 	ba = gfp->g_regkva;
977 	/* first read colors out of the chip, then copyout to userspace */
978 	vgaw(ba, VDAC_ADDRESS_R, cmap->index);
979 	x = cmap->count - 1;
980 
981 /* Some sort 'o Magic. Spectrum has some changes on the board to speed
982  * up 15 and 16Bit modes. They can access these modes with easy-to-programm
983  * rgbrgbrgb instead of rrrgggbbb. Side effect: when in 8Bit mode, rgb
984  * is swapped to bgr. I wonder if we need to check for 8Bit though, ill
985  */
986 
987 	switch (cltype) {
988 	    case SPECTRUM:
989 	    case PICCOLO:
990 		rp = blue + cmap->index;
991 		gp = green + cmap->index;
992 		bp = red + cmap->index;
993 		break;
994 	    case PICASSO:
995 		rp = red + cmap->index;
996 		gp = green + cmap->index;
997 		bp = blue + cmap->index;
998 		break;
999 	    default:
1000 		rp = gp = bp = 0;
1001 		break;
1002 	}
1003 
1004 	do {
1005 		*rp++ = vgar(ba, VDAC_DATA) << 2;
1006 		*gp++ = vgar(ba, VDAC_DATA) << 2;
1007 		*bp++ = vgar(ba, VDAC_DATA) << 2;
1008 	} while (x-- > 0);
1009 
1010 	if (!(error = copyout(red + cmap->index, cmap->red, cmap->count))
1011 	    && !(error = copyout(green + cmap->index, cmap->green, cmap->count))
1012 	    && !(error = copyout(blue + cmap->index, cmap->blue, cmap->count)))
1013 		return (0);
1014 
1015 	return (error);
1016 }
1017 
1018 int
1019 cl_putcmap(gfp, cmap)
1020 	struct grf_softc *gfp;
1021 	struct grf_colormap *cmap;
1022 {
1023 	volatile unsigned char *ba;
1024 	u_char  red[256], green[256], blue[256], *rp, *gp, *bp;
1025 	short   x;
1026 	int     error;
1027 
1028 	if (cmap->count == 0 || cmap->index >= 256)
1029 		return (0);
1030 
1031 	if (cmap->index + cmap->count > 256)
1032 		cmap->count = 256 - cmap->index;
1033 
1034 	/* first copy the colors into kernelspace */
1035 	if (!(error = copyin(cmap->red, red + cmap->index, cmap->count))
1036 	    && !(error = copyin(cmap->green, green + cmap->index, cmap->count))
1037 	    && !(error = copyin(cmap->blue, blue + cmap->index, cmap->count))) {
1038 		ba = gfp->g_regkva;
1039 		vgaw(ba, VDAC_ADDRESS_W, cmap->index);
1040 		x = cmap->count - 1;
1041 
1042 		switch (cltype) {
1043 		    case SPECTRUM:
1044 		    case PICCOLO:
1045 			rp = blue + cmap->index;
1046 			gp = green + cmap->index;
1047 			bp = red + cmap->index;
1048 			break;
1049 		    case PICASSO:
1050 			rp = red + cmap->index;
1051 			gp = green + cmap->index;
1052 			bp = blue + cmap->index;
1053 			break;
1054 		    default:
1055 			rp = gp = bp = 0;
1056 			break;
1057 		}
1058 
1059 		do {
1060 			vgaw(ba, VDAC_DATA, *rp++ >> 2);
1061 			vgaw(ba, VDAC_DATA, *gp++ >> 2);
1062 			vgaw(ba, VDAC_DATA, *bp++ >> 2);
1063 		} while (x-- > 0);
1064 		return (0);
1065 	} else
1066 		return (error);
1067 }
1068 
1069 
1070 int
1071 cl_toggle(gp, wopp)
1072 	struct grf_softc *gp;
1073 	unsigned short wopp;	/* don't need that one yet, ill */
1074 {
1075 	volatile unsigned char *ba;
1076 
1077 	ba = gp->g_regkva;
1078 
1079 	if (pass_toggle) {
1080 		RegOffpass(ba);
1081 	} else {
1082 		/* This was in the original.. is it needed? */
1083 		if (cltype == PICASSO || cltype == PICCOLO)
1084 			RegWakeup(ba);
1085 		RegOnpass(ba);
1086 	}
1087 	return (0);
1088 }
1089 
1090 static void
1091 cl_CompFQ(fq, num, denom)
1092 	u_int   fq;
1093 	u_char *num;
1094 	u_char *denom;
1095 {
1096 #define OSC     14318180
1097 /* OK, here's what we're doing here:
1098  *
1099  *             OSC * NUMERATOR
1100  *      VCLK = -------------------  Hz
1101  *             DENOMINATOR * (1+P)
1102  *
1103  * so we're given VCLK and we should give out some useful
1104  * values....
1105  *
1106  * NUMERATOR is 7 bits wide
1107  * DENOMINATOR is 5 bits wide with bit P in the same char as bit 0.
1108  *
1109  * We run through all the possible combinations and
1110  * return the values which deviate the least from the chosen frequency.
1111  *
1112  */
1113 #define OSC     14318180
1114 #define count(n,d,p)    ((OSC * n)/(d * (1+p)))
1115 
1116 	unsigned char n, d, p, minn, mind, minp = 0;
1117 	unsigned long err, minerr;
1118 
1119 /*
1120 numer = 0x00 - 0x7f
1121 denom = 0x00 - 0x1f (1) 0x20 - 0x3e (even)
1122 */
1123 
1124 	/* find lowest error in 6144 iterations. */
1125 	minerr = fq;
1126 	minn = 0;
1127 	mind = 0;
1128 	p = 0;
1129 
1130 	for (d = 1; d < 0x20; d++) {
1131 		for (n = 1; n < 0x80; n++) {
1132 			err = abs(count(n, d, p) - fq);
1133 			if (err < minerr) {
1134 				minerr = err;
1135 				minn = n;
1136 				mind = d;
1137 				minp = p;
1138 			}
1139 		}
1140 		if (d == 0x1f && p == 0) {
1141 			p = 1;
1142 			d = 0x0f;
1143 		}
1144 	}
1145 
1146 	*num = minn;
1147 	*denom = (mind << 1) | minp;
1148 	if (minerr > 500000)
1149 		printf("Warning: CompFQ minimum error = %ld\n", minerr);
1150 	return;
1151 }
1152 
1153 int
1154 cl_mondefok(gv)
1155 	struct grfvideo_mode *gv;
1156 {
1157         unsigned long maxpix;
1158 
1159 	if (gv->mode_num < 1 || gv->mode_num > monitor_def_max)
1160                 if (gv->mode_num != 255 || gv->depth != 4)
1161                         return(0);
1162 
1163 	switch (gv->depth) {
1164 	    case 4:
1165                 if (gv->mode_num != 255)
1166                         return(0);
1167 	    case 1:
1168 	    case 8:
1169                 maxpix = cl_maxpixelclock;
1170                 break;
1171 	    case 15:
1172 	    case 16:
1173                 maxpix = cl_maxpixelclock - (cl_maxpixelclock / 3);
1174                 break;
1175 	    case 24:
1176                 maxpix = cl_maxpixelclock / 3;
1177                 break;
1178 	default:
1179 		return (0);
1180 	}
1181         if (gv->pixel_clock > maxpix)
1182                 return (0);
1183         return (1);
1184 }
1185 
1186 int
1187 cl_load_mon(gp, md)
1188 	struct grf_softc *gp;
1189 	struct grfcltext_mode *md;
1190 {
1191 	struct grfvideo_mode *gv;
1192 	struct grfinfo *gi;
1193 	volatile unsigned char *ba;
1194 	volatile caddr_t fb;
1195 	unsigned char num0, denom0;
1196 	unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS,
1197 	        VSE, VT;
1198 	char    LACE, DBLSCAN, TEXT;
1199 	unsigned short clkdiv;
1200 	int     uplim, lowlim;
1201 	int	sr15;
1202 
1203 	/* identity */
1204 	gv = &md->gv;
1205 	TEXT = (gv->depth == 4);
1206 
1207 	if (!cl_mondefok(gv)) {
1208 		printf("mondef not ok\n");
1209 		return (0);
1210 	}
1211 	ba = gp->g_regkva;
1212 	fb = gp->g_fbkva;
1213 
1214 	/* provide all needed information in grf device-independant locations */
1215 	gp->g_data = (caddr_t) gv;
1216 	gi = &gp->g_display;
1217 	gi->gd_regaddr = (caddr_t) ztwopa(ba);
1218 	gi->gd_regsize = 64 * 1024;
1219 	gi->gd_fbaddr = (caddr_t) kvtop(fb);
1220 	gi->gd_fbsize = cl_fbsize;
1221 	gi->gd_colors = 1 << gv->depth;
1222 	gi->gd_planes = gv->depth;
1223 	gi->gd_fbwidth = gv->disp_width;
1224 	gi->gd_fbheight = gv->disp_height;
1225 	gi->gd_fbx = 0;
1226 	gi->gd_fby = 0;
1227 	if (TEXT) {
1228 		gi->gd_dwidth = md->fx * md->cols;
1229 		gi->gd_dheight = md->fy * md->rows;
1230 	} else {
1231 		gi->gd_dwidth = gv->disp_width;
1232 		gi->gd_dheight = gv->disp_height;
1233 	}
1234 	gi->gd_dx = 0;
1235 	gi->gd_dy = 0;
1236 
1237 	/* get display mode parameters */
1238 
1239 	HBS = gv->hblank_start;
1240 	HBE = gv->hblank_stop;
1241 	HSS = gv->hsync_start;
1242 	HSE = gv->hsync_stop;
1243 	HT = gv->htotal;
1244 	VBS = gv->vblank_start;
1245 	VSS = gv->vsync_start;
1246 	VSE = gv->vsync_stop;
1247 	VBE = gv->vblank_stop;
1248 	VT = gv->vtotal;
1249 
1250 	if (TEXT)
1251 		HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1;
1252 	else
1253 		HDE = (gv->disp_width + 3) / 8 - 1;	/* HBS; */
1254 	VDE = gv->disp_height - 1;
1255 
1256 	/* figure out whether lace or dblscan is needed */
1257 
1258 	uplim = gv->disp_height + (gv->disp_height / 4);
1259 	lowlim = gv->disp_height - (gv->disp_height / 4);
1260 	LACE = (((VT * 2) > lowlim) && ((VT * 2) < uplim)) ? 1 : 0;
1261 	DBLSCAN = (((VT / 2) > lowlim) && ((VT / 2) < uplim)) ? 1 : 0;
1262 
1263 	/* adjustments */
1264 
1265 	if (LACE)
1266 		VDE /= 2;
1267 
1268 	WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e);
1269 	if (cl_sd64 == 1) {
1270 	    if (TEXT || (gv->depth == 1))
1271 		sr15 = 0x90;
1272 	    else
1273 		sr15 = ((cl_fbsize / 0x100000 == 2) ? 0x38 : 0xb8);
1274 	    WSeq(ba, SEQ_ID_CONF_RBACK, 0x00);
1275 	} else {
1276 		sr15 = (TEXT || (gv->depth == 1)) ? 0x90 : 0xb0;
1277 	}
1278 	WSeq(ba, SEQ_ID_DRAM_CNTL, sr15);
1279 	WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
1280 	WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff);
1281 	WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
1282 
1283 	/* Set clock */
1284 
1285 	cl_CompFQ((gv->depth == 24) ? gv->pixel_clock * 3 : gv->pixel_clock,
1286 	    &num0, &denom0);
1287 	WSeq(ba, SEQ_ID_VCLK_3_NUM, num0);
1288 	WSeq(ba, SEQ_ID_VCLK_3_DENOM, denom0);
1289 
1290 	/* load display parameters into board */
1291 
1292 	WCrt(ba, CRT_ID_HOR_TOTAL, HT);
1293 	WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? HBS - 1 : HDE));
1294 	WCrt(ba, CRT_ID_START_HOR_BLANK, HBS);
1295 	WCrt(ba, CRT_ID_END_HOR_BLANK, (HBE & 0x1f) | 0x80);	/* | 0x80? */
1296 	WCrt(ba, CRT_ID_START_HOR_RETR, HSS);
1297 	WCrt(ba, CRT_ID_END_HOR_RETR,
1298 	    (HSE & 0x1f) |
1299 	    ((HBE & 0x20) ? 0x80 : 0x00));
1300 	WCrt(ba, CRT_ID_VER_TOTAL, VT);
1301 	WCrt(ba, CRT_ID_OVERFLOW,
1302 	    0x10 |
1303 	    ((VT & 0x100) ? 0x01 : 0x00) |
1304 	    ((VDE & 0x100) ? 0x02 : 0x00) |
1305 	    ((VSS & 0x100) ? 0x04 : 0x00) |
1306 	    ((VBS & 0x100) ? 0x08 : 0x00) |
1307 	    ((VT & 0x200) ? 0x20 : 0x00) |
1308 	    ((VDE & 0x200) ? 0x40 : 0x00) |
1309 	    ((VSS & 0x200) ? 0x80 : 0x00));
1310 
1311 
1312 	WCrt(ba, CRT_ID_CHAR_HEIGHT,
1313 	    0x40 |		/* TEXT ? 0x00 ??? */
1314 	    (DBLSCAN ? 0x80 : 0x00) |
1315 	    ((VBS & 0x200) ? 0x20 : 0x00) |
1316 	    (TEXT ? ((md->fy - 1) & 0x1f) : 0x00));
1317 	WCrt(ba, CRT_ID_MODE_CONTROL,
1318 	    ((TEXT || (gv->depth == 1)) ? 0xc3 : 0xa3));
1319 
1320 	/* text cursor */
1321 
1322 	if (TEXT) {
1323 #if CL_ULCURSOR
1324 		WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2);
1325 		WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1);
1326 #else
1327 		WCrt(ba, CRT_ID_CURSOR_START, 0x00);
1328 		WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f);
1329 #endif
1330 		WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->fy - 1) & 0x1f);
1331 
1332 		WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
1333 		WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
1334 	}
1335 	WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
1336 	WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
1337 
1338 	WCrt(ba, CRT_ID_START_VER_RETR, VSS);
1339 	WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f) | 0x30);
1340 	WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE);
1341 	WCrt(ba, CRT_ID_START_VER_BLANK, VBS);
1342 	WCrt(ba, CRT_ID_END_VER_BLANK, VBE);
1343 
1344 	WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
1345 	WCrt(ba, CRT_ID_LACE_END, HT / 2);	/* MW/16 */
1346 	WCrt(ba, CRT_ID_LACE_CNTL,
1347 	    (LACE ? 0x01 : 0x00) |
1348 	    ((HBE & 0x40) ? 0x10 : 0x00) |
1349 	    ((HBE & 0x80) ? 0x20 : 0x00) |
1350 	    ((VBE & 0x100) ? 0x40 : 0x00) |
1351 	    ((VBE & 0x200) ? 0x80 : 0x00));
1352 
1353 	/* depth dependent stuff */
1354 
1355 	switch (gv->depth) {
1356 	    case 1:
1357 	    case 4:
1358 	    case 8:
1359 		clkdiv = 0;
1360 		break;
1361 	    case 15:
1362 	    case 16:
1363 		clkdiv = 3;
1364 		break;
1365 	    case 24:
1366 		clkdiv = 2;
1367 		break;
1368 	    default:
1369 		clkdiv = 0;
1370 		panic("grfcl: Unsuported depth: %i", gv->depth);
1371 		break;
1372 	}
1373 
1374 	WGfx(ba, GCT_ID_GRAPHICS_MODE,
1375 	    ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40));
1376 	WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
1377 
1378 	WSeq(ba, SEQ_ID_EXT_SEQ_MODE,
1379 	    ((TEXT || (gv->depth == 1)) ? 0x00 : 0x01) |
1380 	    ((cltype == PICASSO) ? 0x20 : 0x80) |
1381 	    (clkdiv << 1));
1382 
1383 	delay(200000);
1384 
1385 	/* write 0x00 to VDAC_MASK before accessing HDR this helps
1386 	   sometimes, out of "secret" application note (crest) */
1387 	vgaw(ba, VDAC_MASK, 0);
1388 	delay(200000);
1389 	/* reset HDR "magic" access counter (crest) */
1390 	vgar(ba, VDAC_ADDRESS);
1391 
1392 	delay(200000);
1393 	vgar(ba, VDAC_MASK);
1394 	delay(200000);
1395 	vgar(ba, VDAC_MASK);
1396 	delay(200000);
1397 	vgar(ba, VDAC_MASK);
1398 	delay(200000);
1399 	vgar(ba, VDAC_MASK);
1400 	delay(200000);
1401 	switch (gv->depth) {
1402 	    case 1:
1403 	    case 4:		/* text */
1404 		vgaw(ba, VDAC_MASK, 0);
1405 		HDE = gv->disp_width / 16;
1406 		break;
1407 	    case 8:
1408 		vgaw(ba, VDAC_MASK, 0);
1409 		HDE = gv->disp_width / 8;
1410 		break;
1411 	    case 15:
1412 		vgaw(ba, VDAC_MASK, 0xd0);
1413 		HDE = gv->disp_width / 4;
1414 		break;
1415 	    case 16:
1416 		vgaw(ba, VDAC_MASK, 0xc1);
1417 		HDE = gv->disp_width / 4;
1418 		break;
1419 	    case 24:
1420 		vgaw(ba, VDAC_MASK, 0xc5);
1421 		HDE = (gv->disp_width / 8) * 3;
1422 		break;
1423 	}
1424 	delay(20000);
1425 
1426 	/* reset HDR "magic" access counter (crest) */
1427 	vgar(ba, VDAC_ADDRESS);
1428 	delay(200000);
1429 	/* then enable all bit in VDAC_MASK afterwards (crest) */
1430 	vgaw(ba, VDAC_MASK, 0xff);
1431 	delay(20000);
1432 
1433 	WCrt(ba, CRT_ID_OFFSET, HDE);
1434 	if (cl_sd64 == 1) {
1435 		WCrt(ba, CRT_ID_SYNC_ADJ_GENLOCK, 0x00);
1436 		WCrt(ba, CRT_ID_OVERLAY_EXT_CTRL_REG, 0x40);
1437 	}
1438 	WCrt(ba, CRT_ID_EXT_DISP_CNTL,
1439 	    ((TEXT && gv->pixel_clock > 29000000) ? 0x40 : 0x00) |
1440 	    0x22 |
1441 	    ((HDE > 0xff) ? 0x10 : 0x00));	/* text? */
1442 
1443 	delay(200000);
1444 	WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x0a : 0x01));
1445 	delay(200000);
1446 	WAttr(ba, 0x20 | ACT_ID_COLOR_PLANE_ENA,
1447 	    (gv->depth == 1) ? 0x01 : 0x0f);
1448 	delay(200000);
1449 
1450 	/* text initialization */
1451 
1452 	if (TEXT) {
1453 		cl_inittextmode(gp);
1454 	}
1455 	WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x14);
1456 	WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01);
1457 
1458 	/* Pass-through */
1459 
1460 	RegOffpass(ba);
1461 
1462 	return (1);
1463 }
1464 
1465 void
1466 cl_inittextmode(gp)
1467 	struct grf_softc *gp;
1468 {
1469 	struct grfcltext_mode *tm = (struct grfcltext_mode *) gp->g_data;
1470 	volatile unsigned char *ba = gp->g_regkva;
1471 	unsigned char *fb = gp->g_fbkva;
1472 	unsigned char *c, *f, y;
1473 	unsigned short z;
1474 
1475 
1476 	/* load text font into beginning of display memory. Each character
1477 	 * cell is 32 bytes long (enough for 4 planes) */
1478 
1479 	SetTextPlane(ba, 0x02);
1480         cl_memset(fb, 0, 256 * 32);
1481 	c = (unsigned char *) (fb) + (32 * tm->fdstart);
1482 	f = tm->fdata;
1483 	for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy))
1484 		for (y = 0; y < tm->fy; y++)
1485 			*c++ = *f++;
1486 
1487 	/* clear out text/attr planes (three screens worth) */
1488 
1489 	SetTextPlane(ba, 0x01);
1490 	cl_memset(fb, 0x07, tm->cols * tm->rows * 3);
1491 	SetTextPlane(ba, 0x00);
1492 	cl_memset(fb, 0x20, tm->cols * tm->rows * 3);
1493 
1494 	/* print out a little init msg */
1495 
1496 	c = (unsigned char *) (fb) + (tm->cols - 16);
1497 	strcpy(c, "CIRRUS");
1498 	c[6] = 0x20;
1499 
1500 	/* set colors (B&W) */
1501 
1502 
1503 	vgaw(ba, VDAC_ADDRESS_W, 0);
1504 	for (z = 0; z < 256; z++) {
1505 		unsigned char r, g, b;
1506 
1507 		y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
1508 
1509 		if (cltype == PICASSO) {
1510 			r = clconscolors[y][0];
1511 			g = clconscolors[y][1];
1512 			b = clconscolors[y][2];
1513 		} else {
1514 			b = clconscolors[y][0];
1515 			g = clconscolors[y][1];
1516 			r = clconscolors[y][2];
1517 		}
1518 		vgaw(ba, VDAC_DATA, r >> 2);
1519 		vgaw(ba, VDAC_DATA, g >> 2);
1520 		vgaw(ba, VDAC_DATA, b >> 2);
1521 	}
1522 }
1523 
1524 void
1525 cl_memset(d, c, l)
1526 	unsigned char *d;
1527 	unsigned char c;
1528 	int     l;
1529 {
1530 	for (; l > 0; l--)
1531 		*d++ = c;
1532 }
1533 #endif /* NGRFCL */
1534