Home | History | Annotate | Line # | Download | only in dev
grf_cl.c revision 1.4
      1 
      2 /*
      3  * Copyright (c) 1995 Ezra Story
      4  * Copyright (c) 1995 Kari Mettinen
      5  * Copyright (c) 1994 Markus Wild
      6  * Copyright (c) 1994 Lutz Vieweg
      7  * All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. All advertising materials mentioning features or use of this software
     18  *    must display the following acknowledgement:
     19  *      This product includes software developed by Lutz Vieweg.
     20  * 4. The name of the author may not be used to endorse or promote products
     21  *    derived from this software without specific prior written permission
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     33  */
     34 
     35 #ifdef GRF_CL5426
     36 /*
     37  * Graphics routines for Cirrus CL GD 5426 boards,
     38  *
     39  * This code offers low-level routines to access Cirrus Cl GD 5426
     40  * graphics-boards from within NetBSD for the Amiga.
     41  * No warranties for any kind of function at all - this
     42  * code may crash your hardware and scratch your harddisk.  Use at your
     43  * own risk.  Freely distributable.
     44  *
     45  * Modified for Cirrus CL GD 5426 from
     46  * Lutz Vieweg's retina driver by Kari Mettinen 08/94
     47  * Contributions by Ill, ScottE, MiL
     48  * Extensively hacked and rewritten by Ezra Story (Ezy) 01/95
     49  *
     50  * Thanks to Village Tronic Marketing Gmbh for providing me with
     51  * a Picasso-II board.
     52  * Thanks for Integrated Electronics Oy Ab for providing me with
     53  * Cirrus CL GD 542x family documentation.
     54  *
     55  * TODO:
     56  *    Mouse support
     57  *    Blitter support
     58  *
     59  */
     60 
     61 #include <sys/param.h>
     62 #include <sys/systm.h>
     63 #include <sys/errno.h>
     64 #include <sys/ioctl.h>
     65 #include <sys/device.h>
     66 #include <sys/malloc.h>
     67 #include <machine/cpu.h>
     68 #include <dev/cons.h>
     69 #include <amiga/amiga/device.h>
     70 #include <amiga/dev/grfioctl.h>
     71 #include <amiga/dev/grfvar.h>
     72 #include <amiga/dev/grf_clreg.h>
     73 #include <amiga/dev/zbusvar.h>
     74 
     75 static int cl_mondefok __P((struct grfvideo_mode *mdp));
     76 static void cl_boardinit();
     77 static void CompFQ __P((u_int fq, u_char *num, u_char *denom));
     78 static int cl_getvmode __P((struct grf_softc *gp, struct grfvideo_mode *vm));
     79 static int cl_setvmode __P((struct grf_softc *gp, unsigned int mode));
     80 static int cl_toggle __P((struct grf_softc *gp,unsigned short));
     81 static int cl_getcmap __P((struct grf_softc *gfp, struct grf_colormap *cmap));
     82 static int cl_putcmap __P((struct grf_softc *gfp, struct grf_colormap *cmap));
     83 static void cl_off __P((struct grf_softc *gp));
     84 static void cl_inittextmode __P((struct grf_softc *gp));
     85 static int cl_ioctl __P((register struct grf_softc *gp, int cmd, void *data));
     86 
     87 void grfclattach __P((struct device *, struct device *, void *));
     88 int  grfclprint  __P((void *, char *));
     89 int  grfclmatch  __P((struct device *, struct cfdata *, void *));
     90 void memset __P((unsigned char *d, unsigned char c, int l));
     91 
     92 /* Graphics display definitions.
     93  * These are filled by 'grfconfig' using GRFIOCSETMON.
     94  */
     95 #define monitor_def_max 8
     96 static struct grfvideo_mode monitor_def[8] = {
     97 	{0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}
     98 };
     99 static struct grfvideo_mode *monitor_current = &monitor_def[0];
    100 
    101 /* Patchable maximum pixel clock */
    102 unsigned long cl_maxpixelclock = 115000000;
    103 
    104 /* Console display definition.
    105  *   Default hardcoded text mode.  This grf_cl is set up to
    106  *   use one text mode only, and this is it.  You may use
    107  *   grfconfig to change the mode after boot.
    108  */
    109 /* Console font */
    110 #ifdef KFONT_8X11
    111 #define CIRRUSFONT kernel_font_8x11
    112 #define CIRRUSFONTY 11
    113 #else
    114 #define CIRRUSFONT kernel_font_8x8
    115 #define CIRRUSFONTY 8
    116 #endif
    117 extern unsigned char CIRRUSFONT[];
    118 
    119 struct grfcltext_mode clconsole_mode = {
    120 	{255, "", 25200000, 640, 480, 4, 80, 94, 99, 100, 100, 481, 490,
    121 	498, 522, 522},
    122 	8, CIRRUSFONTY, 80, 480/CIRRUSFONTY, CIRRUSFONT, 32, 255
    123 };
    124 
    125 /* Console colors */
    126 unsigned char clconscolors[3][3] = {  /* background, foreground, hilite */
    127 	{0,0x40,0x50}, {152,152,152},  {255,255,255}
    128 };
    129 
    130 int             cltype = 0;   /* Picasso, Spectrum or Piccolo */
    131 unsigned char   pass_toggle;  /* passthru status tracker */
    132 
    133 /* because all 5426-boards have 2 configdev entries, one for
    134  * framebuffer mem and the other for regs, we have to hold onto
    135  * the pointers globally until we match on both.  This and 'cltype'
    136  * are the primary obsticles to multiple board support, but if you
    137  * have multiple boards you have bigger problems than grf_cl.
    138  */
    139 static void *cl_fbaddr = 0;     /* framebuffer */
    140 static void *cl_regaddr = 0;    /* registers */
    141 static int cl_fbsize;           /* framebuffer size */
    142 
    143 /* standard driver stuff */
    144 struct cfdriver grfclcd = {
    145 	NULL, "grfcl", (cfmatch_t)grfclmatch, grfclattach,
    146 	DV_DULL, sizeof(struct grf_softc), NULL, 0
    147 };
    148 static struct cfdata *cfdata;
    149 
    150 int
    151 grfclmatch(pdp, cfp, auxp)
    152 	struct device *pdp;
    153 	struct cfdata *cfp;
    154 	void *auxp;
    155 {
    156 	struct zbus_args *zap;
    157 	static int regprod, fbprod;
    158 
    159 	zap = auxp;
    160 
    161 #ifndef CL5426CONSOLE
    162 	if (amiga_realconfig == 0)
    163 		 return(0);
    164 #endif
    165 
    166 	/* Grab the first board we encounter as the preferred one.
    167 	 * This will allow one board to work in a multiple 5426 board
    168 	 * system, but not multiple boards at the same time.
    169 	 */
    170 	if (cltype == 0) {
    171 		switch (zap->manid) {
    172 		case PICASSO:
    173 			if (zap->prodid != 12 && zap->prodid != 11)
    174 				return (0);
    175 			regprod = 12;
    176 			fbprod = 11;
    177 			break;
    178 		case SPECTRUM:
    179 			if (zap->prodid != 2 && zap->prodid != 1)
    180 				return (0);
    181 			regprod = 2;
    182 			fbprod = 1;
    183 			break;
    184 		case PICCOLO:
    185 			if (zap->prodid != 6 && zap->prodid != 5)
    186 				return (0);
    187 			regprod = 6;
    188 			fbprod = 5;
    189 			break;
    190 		default:
    191 			return(0);
    192 		}
    193 		cltype = zap->manid;
    194 	} else {
    195 		if (cltype != zap->manid) {
    196 			return(0);
    197 		}
    198 	}
    199 
    200 	/* Configure either registers or framebuffer in any order
    201 	 */
    202 	if (zap->prodid == regprod)
    203 		cl_regaddr = zap->va;
    204 	else if (zap->prodid == fbprod) {
    205 		cl_fbaddr = zap->va;
    206 		cl_fbsize = zap->size;
    207 	} else {
    208 		printf("grfcl: Bad product id\n");
    209 		return(0);
    210 	}
    211 
    212 #ifdef CL5426CONSOLE
    213 	if (amiga_realconfig == 0) {
    214 		cfdata = cfp;
    215 	}
    216 
    217 #endif
    218 
    219 	return(1);
    220 }
    221 
    222 void
    223 grfclattach(pdp, dp, auxp)
    224 	struct device *pdp, *dp;
    225 	void *auxp;
    226 {
    227 	static struct grf_softc congrf;
    228 	struct zbus_args *zap;
    229 	struct grf_softc *gp;
    230 	int x;
    231 	static char attachflag = 0;
    232 
    233 	zap = auxp;
    234 
    235 	printf("\n");
    236 
    237 	/* make sure both halves have matched */
    238 	if (!cl_regaddr || !cl_fbaddr)
    239 		return;
    240 
    241 	/* do all that messy console/grf stuff */
    242 	if (dp == NULL)
    243 		gp = &congrf;
    244 	else
    245 		gp = (struct grf_softc *)dp;
    246 
    247 	if (dp != NULL && congrf.g_regkva != 0) {
    248 		/*
    249 		 * inited earlier, just copy (not device struct)
    250 		 */
    251 		bcopy(&congrf.g_display, &gp->g_display,
    252 		    (char *)&gp[1] - (char *)&gp->g_display);
    253 	} else {
    254 		gp->g_regkva = (volatile caddr_t)cl_regaddr;
    255 		gp->g_fbkva = (volatile caddr_t)cl_fbaddr;
    256 
    257 		gp->g_unit = GRF_CL5426_UNIT;
    258 		gp->g_mode = cl_mode;
    259 		gp->g_conpri = grfcl_cnprobe();
    260 		gp->g_flags = GF_ALIVE;
    261 
    262 		/* wakeup the board */
    263 		cl_boardinit(gp);
    264 
    265 #ifdef CL5426CONSOLE
    266 		grfcl_iteinit(gp);
    267 		(void)cl_load_mon(gp, &clconsole_mode);
    268 #endif
    269 
    270 	}
    271 
    272 	/*
    273 	 * attach grf (once)
    274 	 */
    275 	if (amiga_config_found(cfdata, &gp->g_device, gp, grfclprint)) {
    276 		attachflag = 1;
    277 		printf("grfcl: %dMB ", cl_fbsize/0x100000);
    278 		switch (cltype) {
    279 		case PICASSO:
    280 			printf("Picasso II");
    281 			break;
    282 		case SPECTRUM:
    283 			printf("Spectrum");
    284 			break;
    285 		case PICCOLO:
    286 			printf("Piccolo");
    287 			break;
    288 		}
    289 		printf(" being used\n");
    290 	} else {
    291 		if (!attachflag)
    292 			printf("grfcl unattached!!\n");
    293 	}
    294 }
    295 
    296 int
    297 grfclprint(auxp, pnp)
    298 	void *auxp;
    299 	char *pnp;
    300 {
    301 	if (pnp)
    302 		printf("ite at %s: ", pnp);
    303 	return(UNCONF);
    304 }
    305 
    306 void
    307 cl_boardinit(gp)
    308 struct grf_softc        *gp;
    309 {
    310 	unsigned char *ba = gp->g_regkva;
    311 	int x;
    312 	void *bah;
    313 
    314 	/* wakeup board and flip passthru OFF */
    315 
    316 	RegWakeup(ba);
    317 	RegOnpass(ba);
    318 
    319 	vgaw(ba, 0x46e8, 0x16);
    320 	vgaw(ba, 0x102, 1);
    321 	vgaw(ba, 0x46e8, 0x0e);
    322 	vgaw(ba, 0x3c3, 1);
    323 
    324 	/* setup initial unchanging parameters */
    325 
    326 	WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21);   /* 8 dot - display off */
    327 	vgaw(ba, GREG_MISC_OUTPUT_W, 0xe1);     /* mem disable */
    328 
    329 	WGfx(ba, GCT_ID_OFFSET_1, 0xec);        /* magic cookie */
    330 	WSeq(ba, SEQ_ID_UNLOCK_EXT, 0x12);      /* yum! cookies! */
    331 
    332 	WSeq(ba, SEQ_ID_DRAM_CNTL, 0xb0);
    333 	WSeq(ba, SEQ_ID_RESET, 0x03);
    334 	WSeq(ba, SEQ_ID_MAP_MASK, 0xff);
    335 	WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
    336 	WSeq(ba, SEQ_ID_MEMORY_MODE, 0x0e); /* a or 6? */
    337 	WSeq(ba, SEQ_ID_EXT_SEQ_MODE, (cltype == PICASSO) ? 0x20 : 0x80);
    338 	WSeq(ba, SEQ_ID_EEPROM_CNTL, 0x00);
    339 	WSeq(ba, SEQ_ID_PERF_TUNE, 0x0a);
    340 	WSeq(ba, SEQ_ID_SIG_CNTL, 0x02);
    341 
    342 	WSeq(ba, SEQ_ID_MCLK_SELECT, 0x22);
    343 
    344 	WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00);
    345 	WCrt(ba, CRT_ID_CURSOR_START, 0x00);
    346 	WCrt(ba, CRT_ID_CURSOR_END, 0x08);
    347 	WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
    348 	WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
    349 	WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
    350 	WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
    351 
    352 	WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x07);
    353 	WCrt(ba, CRT_ID_MODE_CONTROL, 0xa3); /* c3 */
    354 	WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); /* ff */
    355 	WCrt(ba, CRT_ID_EXT_DISP_CNTL, 0x22);
    356 	WSeq(ba, SEQ_ID_CURSOR_STORE, 0x00);
    357 
    358 	WGfx(ba, GCT_ID_SET_RESET, 0x00);
    359 	WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
    360 	WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
    361 	WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
    362 	WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x00);
    363 	WGfx(ba, GCT_ID_MISC, 0x01);
    364 	WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f);
    365 	WGfx(ba, GCT_ID_BITMASK, 0xff);
    366 	WGfx(ba, GCT_ID_MODE_EXT, 0x28);
    367 
    368 	for (x=0; x< 0x10; x++)
    369 	    WAttr(ba, x, x);
    370 	WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x01);
    371 	WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00);
    372 	WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
    373 	WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
    374 	WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
    375 
    376 	delay(200000);
    377 	WAttr(ba, 0x34, 0x00);
    378 	delay(200000);
    379 
    380 	vgaw(ba, VDAC_MASK, 0xff);
    381 	delay(200000);
    382 	vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3); /* c3 */
    383 
    384 	WGfx(ba, GCT_ID_BLT_STAT_START, 0x40);
    385 	WGfx(ba, GCT_ID_BLT_STAT_START, 0x00);
    386 
    387 	/* colors initially set to greyscale */
    388 
    389 	vgaw(ba, VDAC_ADDRESS_W, 0);
    390 	for (x = 255; x >= 0 ; x--) {
    391 		vgaw(ba, VDAC_DATA, x);
    392 		vgaw(ba, VDAC_DATA, x);
    393 		vgaw(ba, VDAC_DATA, x);
    394 	}
    395 }
    396 
    397 
    398 int
    399 cl_getvmode(gp, vm)
    400 	struct grf_softc *gp;
    401 	struct grfvideo_mode *vm;
    402 {
    403 	struct grfvideo_mode *gv;
    404 
    405 #ifdef CL5426CONSOLE
    406 	/* Handle grabbing console mode */
    407 	if (vm->mode_num == 255) {
    408 		bcopy(&clconsole_mode, vm, sizeof(struct grfvideo_mode));
    409 		/* XXX so grfconfig can tell us the correct text
    410 		 * dimensions.
    411 		 */
    412 		vm->depth = clconsole_mode.fy;
    413 		return(0);
    414 	}
    415 #endif
    416 	if (vm->mode_num && vm->mode_num > monitor_def_max)
    417 		return(EINVAL);
    418 
    419 	if (!vm->mode_num)
    420 		vm->mode_num = (monitor_current - monitor_def) + 1;
    421 
    422 	gv = monitor_def + (vm->mode_num - 1);
    423 	if (gv->mode_num == 0)
    424 		return(EINVAL);
    425 
    426 	bcopy(gv, vm, sizeof(struct grfvideo_mode));
    427 	return(0);
    428 }
    429 
    430 
    431 int
    432 cl_setvmode(gp, mode)
    433 	struct grf_softc *gp;
    434 	unsigned mode;
    435 {
    436 	struct grfvideo_mode *gv;
    437 
    438 	if (!mode || (mode > monitor_def_max) ||
    439 	    monitor_def[mode-1].mode_num == 0)
    440 		return(EINVAL);
    441 
    442 	monitor_current = monitor_def + (mode - 1);
    443 
    444 
    445 	return(0);
    446 }
    447 
    448 void
    449 cl_off(gp)
    450 struct grf_softc *gp;
    451 {
    452 	char *ba = gp->g_regkva;
    453 
    454 	/* we'll put the pass-through on for cc ite and set Full Bandwidth
    455 	 * bit on just in case it didn't work...but then it doesn't matter
    456 	 * does it? =)
    457 	 */
    458 	RegOnpass(ba);
    459 	WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21);
    460 }
    461 
    462 /*
    463  * Change the mode of the display.
    464  * Return a UNIX error number or 0 for success.
    465  */
    466 cl_mode(gp, cmd, arg, a2, a3)
    467 	register struct grf_softc *gp;
    468 	int cmd;
    469 	void *arg;
    470 	int a2, a3;
    471 {
    472 	int error;
    473 
    474 	switch (cmd) {
    475 	case GM_GRFON:
    476 		error = cl_load_mon (gp,
    477 		    (struct grfcltext_mode *) monitor_current) ? 0 : EINVAL;
    478 		return(error);
    479 
    480 	case GM_GRFOFF:
    481 #ifndef CL5426CONSOLE
    482 		cl_off(gp);
    483 #else
    484 		cl_load_mon(gp, &clconsole_mode);
    485 #endif
    486 		return(0);
    487 
    488 	case GM_GRFCONFIG:
    489 		return(0);
    490 
    491 	case GM_GRFGETVMODE:
    492 		return(cl_getvmode (gp, (struct grfvideo_mode *) arg));
    493 
    494 	case GM_GRFSETVMODE:
    495 		error = cl_setvmode (gp, *(unsigned *) arg);
    496 		if (!error && (gp->g_flags & GF_GRFON))
    497 			cl_load_mon(gp,
    498 			    (struct grfcltext_mode *) monitor_current);
    499 		return(error);
    500 
    501 	case GM_GRFGETNUMVM:
    502 		*(int *)arg = monitor_def_max;
    503 		return(0);
    504 
    505 	case GM_GRFIOCTL:
    506 		return(cl_ioctl (gp, (int) arg, (caddr_t) a2));
    507 
    508 	default:
    509 		break;
    510 	}
    511 
    512 	return(EINVAL);
    513 }
    514 
    515 int
    516 cl_ioctl (gp, cmd, data)
    517 	register struct grf_softc *gp;
    518 	int cmd;
    519 	void *data;
    520 {
    521 	switch (cmd) {
    522 	case GRFIOCGSPRITEPOS:
    523 	case GRFIOCSSPRITEPOS:
    524 	case GRFIOCSSPRITEINF:
    525 	case GRFIOCGSPRITEINF:
    526 	case GRFIOCGSPRITEMAX:
    527 		break;
    528 
    529 	case GRFIOCGETCMAP:
    530 		return(cl_getcmap (gp, (struct grf_colormap *) data));
    531 
    532 	case GRFIOCPUTCMAP:
    533 		return(cl_putcmap (gp, (struct grf_colormap *) data));
    534 
    535 	case GRFIOCBITBLT:
    536 		break;
    537 
    538 	case GRFTOGGLE:
    539 		return(cl_toggle (gp,0));
    540 
    541 	case GRFIOCSETMON:
    542 		return(cl_setmonitor (gp, (struct grfvideo_mode *)data));
    543 
    544 	}
    545 	return(EINVAL);
    546 }
    547 
    548 int
    549 cl_setmonitor(gp, gv)
    550 	struct grf_softc *gp;
    551 	struct grfvideo_mode *gv;
    552 {
    553 	struct grfvideo_mode *md;
    554         unsigned long maxpix;
    555 
    556 #ifdef CL5426CONSOLE
    557 	/* handle interactive setting of console mode */
    558 	if (gv->mode_num == 255 && gv->depth == 4) {
    559 		bcopy(gv, &clconsole_mode.gv, sizeof(struct grfvideo_mode));
    560 		clconsole_mode.rows = gv->disp_height / clconsole_mode.fy;
    561 		clconsole_mode.cols = gv->disp_width / clconsole_mode.fx;
    562 		if (!(gp->g_flags & GF_GRFON))
    563 		    cl_load_mon(gp, &clconsole_mode);
    564 		ite_reinit(gp->g_itedev);
    565 		return(0);
    566 	}
    567 #endif
    568 
    569     	/* text mode not valid for other than console */
    570     	if (gv->depth == 4)
    571     	    	return(EINVAL);
    572 
    573 	if (!gv->mode_num || gv->mode_num > monitor_def_max)
    574 		return(EINVAL);
    575 
    576 	if ((gv->depth == 24 && (gv->pixel_clock*3) > cl_maxpixelclock) ||
    577 	    (gv->pixel_clock > cl_maxpixelclock))
    578 		return(EINVAL);
    579 
    580 	md = monitor_def + (gv->mode_num-1);
    581 
    582 	bcopy(gv, md, sizeof(struct grfvideo_mode));
    583 	return(0);
    584 }
    585 
    586 int
    587 cl_getcmap (gfp, cmap)
    588 	struct grf_softc *gfp;
    589 	struct grf_colormap *cmap;
    590 {
    591 	volatile unsigned char *ba;
    592 	u_char red[256], green[256], blue[256], *rp, *gp, *bp;
    593 	short x;
    594 	int error;
    595 
    596 	if (cmap->count == 0 || cmap->index >= 256)
    597 		return 0;
    598 
    599 	if (cmap->index + cmap->count > 256)
    600 		cmap->count = 256 - cmap->index;
    601 
    602 	ba = gfp->g_regkva;
    603 	/* first read colors out of the chip, then copyout to userspace */
    604 	vgaw (ba, VDAC_ADDRESS_W, cmap->index);
    605 	x = cmap->count - 1;
    606 
    607 /* Some sort 'o Magic. Spectrum has some changes on the board to speed
    608  * up 15 and 16Bit modes. They can access these modes with easy-to-programm
    609  * rgbrgbrgb instead of rrrgggbbb. Side effect: when in 8Bit mode, rgb
    610  * is swapped to bgr. I wonder if we need to check for 8Bit though, ill
    611  */
    612 
    613 	switch (cltype) {
    614 	case SPECTRUM:
    615 	case PICCOLO:
    616 		rp = blue + cmap->index;
    617 		gp = green + cmap->index;
    618 		bp = red + cmap->index;
    619 		break;
    620 	case PICASSO:
    621 		rp = red + cmap->index;
    622 		gp = green + cmap->index;
    623 		bp = blue + cmap->index;
    624 		break;
    625 	}
    626 
    627 	do {
    628 		*rp++ = vgar (ba, VDAC_DATA) << 2;
    629 		*gp++ = vgar (ba, VDAC_DATA) << 2;
    630 		*bp++ = vgar (ba, VDAC_DATA) << 2;
    631 	} while (x-- > 0);
    632 
    633 	if (!(error = copyout (red + cmap->index, cmap->red, cmap->count))
    634 	    && !(error = copyout (green + cmap->index, cmap->green, cmap->count))
    635 	    && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count)))
    636 		return(0);
    637 
    638 	return(error);
    639 }
    640 
    641 int
    642 cl_putcmap (gfp, cmap)
    643 	struct grf_softc *gfp;
    644 	struct grf_colormap *cmap;
    645 {
    646 	volatile unsigned char *ba;
    647 	u_char red[256], green[256], blue[256], *rp, *gp, *bp;
    648 	short x;
    649 	int error;
    650 
    651 	if (cmap->count == 0 || cmap->index >= 256)
    652 		return(0);
    653 
    654 	if (cmap->index + cmap->count > 256)
    655 		cmap->count = 256 - cmap->index;
    656 
    657 	/* first copy the colors into kernelspace */
    658 	if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
    659 	    && !(error = copyin (cmap->green, green + cmap->index, cmap->count))
    660 	    && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count))) {
    661 		ba = gfp->g_regkva;
    662 		vgaw (ba, VDAC_ADDRESS_W, cmap->index);
    663 		x = cmap->count - 1;
    664 
    665 		switch (cltype) {
    666 		case SPECTRUM:
    667 		case PICCOLO:
    668 			rp = blue + cmap->index;
    669 			gp = green + cmap->index;
    670 			bp = red + cmap->index;
    671 			break;
    672 		case PICASSO:
    673 			rp = red + cmap->index;
    674 			gp = green + cmap->index;
    675 			bp = blue + cmap->index;
    676 			break;
    677 		}
    678 
    679 		do {
    680 			vgaw (ba, VDAC_DATA, *rp++ >> 2);
    681 			vgaw (ba, VDAC_DATA, *gp++ >> 2);
    682 			vgaw (ba, VDAC_DATA, *bp++ >> 2);
    683 		} while (x-- > 0);
    684 		return(0);
    685 	}
    686 	else
    687 		return(error);
    688 }
    689 
    690 
    691 int
    692 cl_toggle(gp,wopp)
    693 	struct grf_softc *gp;
    694 	unsigned short wopp; /* don't need that one yet, ill */
    695 {
    696 	volatile unsigned char *ba;
    697 
    698 	ba = gp->g_regkva;
    699 
    700 	if (pass_toggle) {
    701 		RegOffpass(ba);
    702 	} else {
    703 		/* This was in the original.. is it needed? */
    704 		if (cltype == PICASSO || cltype == PICCOLO)
    705 			RegWakeup(ba);
    706 		RegOnpass(ba);
    707 	}
    708 	return(0);
    709 }
    710 
    711 static void
    712 CompFQ(fq,num,denom)
    713 u_int fq;
    714 u_char *num;
    715 u_char *denom;
    716 {
    717 #define OSC     14318180
    718 /* OK, here's what we're doing here:
    719  *
    720  *             OSC * NUMERATOR
    721  *      VCLK = -------------------  Hz
    722  *             DENOMINATOR * (1+P)
    723  *
    724  * so we're given VCLK and we should give out some useful
    725  * values....
    726  *
    727  * NUMERATOR is 6 bits wide
    728  * DENOMINATOR is 5 bits wide with bit P in the same char as bit 0.
    729  *
    730  * We run through all the possible combinations and
    731  * return the values which deviate the least from the chosen frequency.
    732  *
    733  */
    734 #define OSC     14318180
    735 #define count(n,d,p)    ((OSC * n)/(d * (1+p)))
    736 
    737 	unsigned char n, d, p, minn, mind, minp;
    738 	unsigned long err, minerr;
    739 
    740 /*
    741 numer = 0x00 - 0x7f (7 bit!)
    742 denom = 0x00 - 0x1f (1) 0x20 - 0x3e (even)
    743 */
    744 
    745 	/* find lowest error in 6144 iterations.
    746 	 */
    747 	minerr = fq;
    748 	minn = 0;
    749 	mind = 0;
    750 	p = 0;
    751 
    752 	for (d=1; d < 0x20; d++) {
    753 		for (n=1; n < 0x80; n++) {
    754 			err = abs(count(n, d, p) - fq);
    755 			if (err < minerr) {
    756 				minerr = err;
    757 				minn = n;
    758 				mind = d;
    759 				minp = p;
    760 			}
    761 		}
    762 		if (d == 0x1f && p == 0) {
    763 			p = 1;
    764 			d = 0x0f;
    765 		}
    766 	}
    767 
    768 	*num = minn;
    769 	*denom = (mind << 1) | minp;
    770 	if (minerr > 500000)
    771 	    printf("Warning: CompFQ minimum error = %d\n", minerr);
    772 	return;
    773 }
    774 
    775 int
    776 cl_mondefok(mdp)
    777 	struct grfvideo_mode *mdp;
    778 {
    779 	if (mdp->mode_num == 0 || (mdp->depth == 24 ?
    780             mdp->pixel_clock * 3 : mdp->pixel_clock) > cl_maxpixelclock)
    781 		return(0);
    782 
    783 	switch(mdp->depth) {
    784 	case 1:
    785 	case 4:
    786 	case 8:
    787 	case 15:
    788 	case 16:
    789 	case 24:
    790 		return(1);
    791 	default:
    792 		return(0);
    793 	}
    794 }
    795 
    796 int
    797 cl_load_mon(gp, md)
    798 	struct grf_softc *gp;
    799 	struct grfcltext_mode *md;
    800 {
    801 	struct grfvideo_mode *gv;
    802 	struct grfinfo *gi;
    803 	volatile unsigned char *ba;
    804 	volatile unsigned char *fb;
    805 	unsigned char num0,denom0;
    806 	unsigned short HT,HDE,HBS,HBE,HSS,HSE,VDE,VBS,VBE,VSS,VSE,VT;
    807 	char LACE, DBLSCAN, TEXT;
    808 	unsigned short clkdiv, clksel;
    809 	int uplim, lowlim;
    810 
    811 	/* identity */
    812 	gv = &md->gv;
    813 	TEXT = (gv->depth == 4);
    814 
    815 	if (!cl_mondefok(gv)) {
    816 		printf("mondef not ok\n");
    817 		return(0);
    818 	}
    819 
    820 	ba = gp->g_regkva;
    821 	fb = gp->g_fbkva;
    822 
    823 	/* provide all needed information in grf device-independant
    824 	 * locations
    825 	 */
    826 	gp->g_data              = (caddr_t) gv;
    827 	gi = &gp->g_display;
    828 	gi->gd_regaddr          = (caddr_t) ztwopa (ba);
    829 	gi->gd_regsize          = 64*1024;
    830 	gi->gd_fbaddr           = (caddr_t) kvtop (fb);
    831 	gi->gd_fbsize           = cl_fbsize;
    832 	gi->gd_colors           = 1 << gv->depth;
    833 	gi->gd_planes           = gv->depth;
    834 	gi->gd_fbwidth          = gv->disp_width;
    835 	gi->gd_fbheight         = gv->disp_height;
    836 	gi->gd_fbx              = 0;
    837 	gi->gd_fby              = 0;
    838 	if (TEXT) {
    839 		gi->gd_dwidth   = md->fx * md->cols;
    840 		gi->gd_dheight  = md->fy * md->rows;
    841 	} else {
    842 		gi->gd_dwidth   = gv->disp_width;
    843 		gi->gd_dheight  = gv->disp_height;
    844 	}
    845 	gi->gd_dx               = 0;
    846 	gi->gd_dy               = 0;
    847 
    848 	/* get display mode parameters */
    849 
    850 	HBS = gv->hblank_start;
    851 	HBE = gv->hblank_stop;
    852 	HSS = gv->hsync_start;
    853 	HSE = gv->hsync_stop;
    854 	HT  = gv->htotal;
    855 	VBS = gv->vblank_start;
    856 	VSS = gv->vsync_start;
    857 	VSE = gv->vsync_stop;
    858 	VBE = gv->vblank_stop;
    859 	VT  = gv->vtotal;
    860 
    861 	if (TEXT)
    862 		HDE = ((gv->disp_width+md->fx-1)/md->fx) - 1;
    863 	else
    864 		HDE = (gv->disp_width+3)/8 - 1; /*HBS;*/
    865 	VDE = gv->disp_height-1;
    866 
    867 	/* figure out whether lace or dblscan is needed */
    868 
    869 	uplim = gv->disp_height + (gv->disp_height / 4);
    870 	lowlim = gv->disp_height - (gv->disp_height / 4);
    871 	LACE = (((VT*2) > lowlim) && ((VT*2) < uplim)) ? 1 : 0;
    872 	DBLSCAN = (((VT/2) > lowlim) && ((VT/2) < uplim)) ? 1 : 0;
    873 
    874 	/* adjustments */
    875 
    876 	if (LACE)
    877 		VDE /= 2;
    878 
    879 	WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e);
    880 	WSeq(ba, SEQ_ID_DRAM_CNTL, (TEXT || (gv->depth == 1)) ? 0x90 : 0xb0);
    881 	WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
    882 	WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff);
    883 	WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
    884 
    885 	/* Set clock */
    886 
    887 	CompFQ((gv->depth == 24) ? gv->pixel_clock*3 : gv->pixel_clock,
    888 	    &num0, &denom0);
    889 	WSeq(ba, SEQ_ID_VCLK_0_NUM, num0);
    890 	WSeq(ba, SEQ_ID_VCLK_0_DENOM, denom0);
    891 
    892 	/* load display parameters into board */
    893 
    894 	WCrt(ba, CRT_ID_HOR_TOTAL, HT);
    895 	WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? HBS-1 : HDE));
    896 	WCrt(ba, CRT_ID_START_HOR_BLANK, HBS);
    897 	WCrt(ba, CRT_ID_END_HOR_BLANK, (HBE & 0x1f) | 0x80); /* | 0x80? */
    898 	WCrt(ba, CRT_ID_START_HOR_RETR, HSS);
    899 	WCrt(ba, CRT_ID_END_HOR_RETR,
    900 	    (HSE & 0x1f) |
    901 	    ((HBE & 0x20) ? 0x80 : 0x00) );
    902 	WCrt(ba, CRT_ID_VER_TOTAL, VT);
    903 	WCrt(ba, CRT_ID_OVERFLOW,
    904 	    0x10 |
    905 	    ((VT  & 0x100) ? 0x01 : 0x00) |
    906 	    ((VDE & 0x100) ? 0x02 : 0x00) |
    907 	    ((VSS & 0x100) ? 0x04 : 0x00) |
    908 	    ((VBS & 0x100) ? 0x08 : 0x00) |
    909 	    ((VT  & 0x200) ? 0x20 : 0x00) |
    910 	    ((VDE & 0x200) ? 0x40 : 0x00) |
    911 	    ((VSS & 0x200) ? 0x80 : 0x00) );
    912 
    913 
    914 	WCrt(ba, CRT_ID_CHAR_HEIGHT,
    915 	    0x40 |  /* TEXT ? 0x00 ??? */
    916 	    (DBLSCAN ? 0x80 : 0x00) |
    917 	    ((VBS & 0x200) ? 0x20 : 0x00) |
    918 	    (TEXT ? ((md->fy-1) & 0x1f) : 0x00));
    919 	WCrt(ba, CRT_ID_MODE_CONTROL,
    920 	    ((TEXT || (gv->depth == 1)) ? 0xc3 : 0xa3));
    921 
    922 	/* text cursor */
    923 
    924 	if (TEXT) {
    925 #if 0
    926 		WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2);
    927 		WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1);
    928 #else
    929 		WCrt(ba, CRT_ID_CURSOR_START, 0x00);
    930 		WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f);
    931 #endif
    932 		WCrt(ba, CRT_ID_UNDERLINE_LOC, md->fy-1 & 0x1f);
    933 
    934 		WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
    935 		WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
    936 	}
    937 
    938 	WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
    939 	WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
    940 
    941 	WCrt(ba, CRT_ID_START_VER_RETR, VSS);
    942 	WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f) | 0x30);
    943 	WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE);
    944 	WCrt(ba, CRT_ID_START_VER_BLANK, VBS);
    945 	WCrt(ba, CRT_ID_END_VER_BLANK, VBE);
    946 
    947 	WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
    948 	WCrt(ba, CRT_ID_LACE_END, HT/2); /* MW/16 */
    949 	WCrt(ba, CRT_ID_LACE_CNTL,
    950 	    (LACE ? 0x01 : 0x00) |
    951 	    ((HBE & 0x40) ? 0x10 : 0x00) |
    952 	    ((HBE & 0x80) ? 0x20 : 0x00) |
    953 	    ((VBE & 0x100) ? 0x40 : 0x00) |
    954 	    ((VBE & 0x200) ? 0x80 : 0x00) );
    955 
    956 	/* depth dependent stuff */
    957 
    958 	switch (gv->depth) {
    959 	case 1:
    960 	case 4:
    961 	case 8:
    962 	    clkdiv = 0;
    963 	    break;
    964 	case 15:
    965 	case 16:
    966 	    clkdiv = 3;
    967 	    break;
    968 	case 24:
    969 	    clkdiv = 2;
    970 	    break;
    971 	}
    972 
    973 	WGfx(ba, GCT_ID_GRAPHICS_MODE,
    974 	    ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40));
    975 	WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
    976 
    977 	WSeq(ba, SEQ_ID_EXT_SEQ_MODE,
    978 	    ((TEXT || (gv->depth == 1)) ? 0x00 : 0x01) |
    979 	    ((cltype == PICASSO) ? 0x20: 0x80) |
    980 	    (clkdiv << 1) );
    981 
    982         delay(200000);
    983 	vgaw(ba, VDAC_MASK, 0xff);
    984 	delay(200000);
    985 	vgar(ba, VDAC_MASK);
    986 	delay(200000);
    987 	vgar(ba, VDAC_MASK);
    988 	delay(200000);
    989 	vgar(ba, VDAC_MASK);
    990 	delay(200000);
    991 	vgar(ba, VDAC_MASK);
    992 	delay(200000);
    993 	switch (gv->depth) {
    994 	case 1:
    995 	case 4: /* text */
    996 		vgaw(ba, VDAC_MASK, 0);
    997 		HDE = gv->disp_width / 16;
    998 		break;
    999 	case 8:
   1000 		vgaw(ba, VDAC_MASK, 0);
   1001 		HDE = gv->disp_width / 8;
   1002 		break;
   1003 	case 15:
   1004 		vgaw(ba, VDAC_MASK, 0xd0);
   1005 		HDE = gv->disp_width / 4;
   1006 		break;
   1007 	case 16:
   1008 		vgaw(ba, VDAC_MASK, 0xc1);
   1009 		HDE = gv->disp_width / 4;
   1010 		break;
   1011 	case 24:
   1012 		vgaw(ba, VDAC_MASK, 0xc5);
   1013 		HDE = (gv->disp_width / 8) * 3;
   1014 		break;
   1015 	}
   1016 	delay(200000);
   1017 
   1018 	WCrt(ba, CRT_ID_OFFSET,  HDE);
   1019 	WCrt(ba, CRT_ID_EXT_DISP_CNTL,
   1020 	    ((TEXT && gv->pixel_clock > 29000000) ? 0x40 : 0x00) |
   1021 	    0x22  |
   1022 	    ((HDE > 0xff) ? 0x10 : 0x00)); /* text? */
   1023 
   1024 	delay(200000);
   1025 	WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x0a : 0x01));
   1026 	delay(200000);
   1027 	WAttr(ba, 0x20 | ACT_ID_COLOR_PLANE_ENA,
   1028 	    (gv->depth == 1) ? 0x01 : 0x0f);
   1029 	delay(200000);
   1030 
   1031 	/* text initialization */
   1032 
   1033 	if (TEXT) {
   1034 		cl_inittextmode(gp);
   1035 	}
   1036 
   1037 	WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x14);
   1038 	WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01);
   1039 
   1040 	/* Pass-through */
   1041 
   1042 	RegOffpass(ba);
   1043 
   1044 	return(1);
   1045 }
   1046 
   1047 void
   1048 cl_inittextmode(gp)
   1049 	struct grf_softc *gp;
   1050 {
   1051 	struct grfcltext_mode *tm = (struct grfcltext_mode *)gp->g_data;
   1052 	volatile unsigned char *ba = gp->g_regkva;
   1053 	unsigned char *fb = gp->g_fbkva;
   1054 	unsigned char *c, *f, y;
   1055 	unsigned short z;
   1056 
   1057 
   1058 	/* load text font into beginning of display memory.
   1059 	 * Each character cell is 32 bytes long (enough for
   1060 	 * 4 planes)
   1061 	 */
   1062 
   1063 	SetTextPlane(ba, 0x02);
   1064 	c = (unsigned char *)(fb);
   1065 	f = tm->fdata;
   1066 	for (z = 0; z < tm->fdstart; z++, c+=(32-tm->fy))
   1067 		for (y=0; y < tm->fy; y++)
   1068 			*c++ = 0;
   1069 	for (; z <= tm->fdend; z++, c+=(32-tm->fy))
   1070 		for (y=0; y < tm->fy; y++)
   1071 			*c++ = *f++;
   1072 	for (; z < 256; z++, c+=(32-tm->fy))
   1073 		for (y=0; y < tm->fy; y++)
   1074 			*c++ = 0;
   1075 
   1076 	/* clear out text/attr planes (three screens worth) */
   1077 
   1078 	SetTextPlane(ba, 0x01);
   1079 	memset(fb, 0x07, tm->cols*tm->rows*3);
   1080 	SetTextPlane(ba, 0x00);
   1081 	memset(fb, 0x20, tm->cols*tm->rows*3);
   1082 
   1083 	/* print out a little init msg */
   1084 
   1085 	c = (unsigned char *)(fb) + (tm->cols-16);
   1086 	strcpy(c, "CIRRUS");
   1087 	c[6] = 0x20;
   1088 
   1089 	/* set colors (B&W) */
   1090 
   1091 
   1092 	vgaw(ba, VDAC_ADDRESS_W, 0);
   1093 	for (z=0; z<256; z++) {
   1094 		unsigned char r, g, b;
   1095 
   1096 		y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
   1097 
   1098 		if (cltype == PICASSO) {
   1099 			r = clconscolors[y][0];
   1100 			g = clconscolors[y][1];
   1101 			b = clconscolors[y][2];
   1102 		} else {
   1103 			b = clconscolors[y][0];
   1104 			g = clconscolors[y][1];
   1105 			r = clconscolors[y][2];
   1106 		}
   1107 		vgaw(ba, VDAC_DATA, r >> 2);
   1108 		vgaw(ba, VDAC_DATA, g >> 2);
   1109 		vgaw(ba, VDAC_DATA, b >> 2);
   1110 	}
   1111 }
   1112 
   1113 void
   1114 memset(d, c, l)
   1115 	unsigned char *d;
   1116 	unsigned char c;
   1117 	int l;
   1118 {
   1119 	for(; l>0; l--)
   1120 		*d++ = c;
   1121 }
   1122 
   1123 #endif  /* GRF_CL5426 */
   1124 
   1125