Home | History | Annotate | Line # | Download | only in dev
grf_rt.c revision 1.54.12.2
      1 /*	$NetBSD: grf_rt.c,v 1.54.12.2 2012/10/30 17:18:48 yamt Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1993 Markus Wild
      5  * Copyright (c) 1993 Lutz Vieweg
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. All advertising materials mentioning features or use of this software
     17  *    must display the following acknowledgement:
     18  *      This product includes software developed by Lutz Vieweg.
     19  * 4. The name of the author may not be used to endorse or promote products
     20  *    derived from this software without specific prior written permission
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32  */
     33 #include "opt_amigacons.h"
     34 
     35 #include <sys/cdefs.h>
     36 __KERNEL_RCSID(0, "$NetBSD: grf_rt.c,v 1.54.12.2 2012/10/30 17:18:48 yamt Exp $");
     37 
     38 #include "grfrt.h"
     39 #include "ite.h"
     40 #if NGRFRT > 0
     41 
     42 /* Graphics routines for the Retina board,
     43    using the NCR 77C22E+ VGA controller. */
     44 
     45 #include <sys/param.h>
     46 #include <sys/systm.h>
     47 #include <sys/errno.h>
     48 #include <sys/ioctl.h>
     49 #include <sys/device.h>
     50 #include <machine/cpu.h>
     51 #include <amiga/amiga/device.h>
     52 #include <amiga/dev/zbusvar.h>
     53 #include <amiga/dev/grfioctl.h>
     54 #include <amiga/dev/grfvar.h>
     55 #include <amiga/dev/grf_rtreg.h>
     56 
     57 int rt_ioctl(struct grf_softc *gp, u_long, void *);
     58 
     59 /*
     60  * marked true early so that retina_cnprobe() can tell if we are alive.
     61  */
     62 int retina_inited;
     63 
     64 
     65 /*
     66  * This driver for the MacroSystem Retina board was only possible,
     67  * because MacroSystem provided information about the pecularities
     68  * of the board. THANKS! Competition in Europe among gfx board
     69  * manufacturers is rather tough, so Lutz Vieweg, who wrote the
     70  * initial driver, has made an agreement with MS not to document
     71  * the driver source (see also his comment below).
     72  * -> ALL comments after
     73  * -> " -------------- START OF CODE -------------- "
     74  * -> have been added by myself (mw) from studying the publically
     75  * -> available "NCR 77C22E+" Data Manual
     76  */
     77 /*
     78  * This code offers low-level routines to access the Retina graphics-board
     79  * manufactured by MS MacroSystem GmbH from within NetBSD for the Amiga.
     80  *
     81  * Thanks to MacroSystem for providing me with the necessary information
     82  * to create theese routines. The sparse documentation of this code
     83  * results from the agreements between MS and me.
     84  */
     85 
     86 extern unsigned char kernel_font_8x8_width, kernel_font_8x8_height;
     87 extern unsigned char kernel_font_8x8_lo, kernel_font_8x8_hi;
     88 extern unsigned char kernel_font_8x8[];
     89 
     90 
     91 #define MDF_DBL 1
     92 #define MDF_LACE 2
     93 #define MDF_CLKDIV2 4
     94 
     95 
     96 /* standard-palette definition */
     97 
     98 unsigned char NCRStdPalette[16*3] = {
     99 /*   R   G   B  */
    100 	  0,  0,  0,
    101 	192,192,192,
    102 	128,  0,  0,
    103 	  0,128,  0,
    104 	  0,  0,128,
    105 	128,128,  0,
    106 	  0,128,128,
    107 	128,  0,128,
    108 	 64, 64, 64, /* the higher 8 colors have more intensity for  */
    109 	255,255,255, /* compatibility with standard attributes       */
    110 	255,  0,  0,
    111 	  0,255,  0,
    112 	  0,  0,255,
    113 	255,255,  0,
    114 	  0,255,255,
    115 	255,  0,255
    116 };
    117 
    118 
    119 /* The following structures are examples for monitor-definitions. To make one
    120    of your own, first use "DefineMonitor" and create the 8-bit monitor-mode of
    121    your dreams. Then save it, and make a structure from the values provided in
    122    the file DefineMonitor stored - the labels in the comment above the
    123    structure definition show where to put what value.
    124 
    125    Then you'll need to adapt your monitor-definition to the font you want to
    126    use. Be FX the width of the font, then the following modifications have to
    127    be applied to your values:
    128 
    129    HBS = (HBS * 4) / FX
    130    HSS = (HSS * 4) / FX
    131    HSE = (HSE * 4) / FX
    132    HBE = (HBE * 4) / FX
    133    HT  = (HT  * 4) / FX
    134 
    135    Make sure your maximum width (MW) and height (MH) are even multiples of
    136    the fonts' width and height.
    137 */
    138 
    139 #if 0
    140 /* horizontal 31.5 kHz */
    141 
    142 /*                                      FQ     FLG    MW   MH   HBS HSS HSE HBE  HT  VBS  VSS  VSE  VBE   VT  */
    143    struct MonDef MON_640_512_60  = { 50000000,  28,  640, 512,   81, 86, 93, 98, 95, 513, 513, 521, 535, 535,
    144    /* Depth,           PAL, TX,  TY,    XY,FontX, FontY,    FontData,  FLo,  Fhi */
    145           4, NCRStdPalette, 80,  64,  5120,    8,     8, kernel_font_8x8,   32,  255};
    146 
    147  struct MonDef MON_640_480_62_G  = { 50000000,   4,  640, 480,  161,171,184,196,195, 481, 484, 492, 502, 502,
    148           8, NCRStdPalette,640,480,  5120,    8,     8, kernel_font_8x8,   32,  255};
    149 /* Enter higher values here ^   ^ for panning! */
    150 
    151 /* horizontal 38kHz */
    152 
    153    struct MonDef MON_768_600_60  = { 75000000,  28,  768, 600,   97, 99,107,120,117, 601, 615, 625, 638, 638,
    154           4, NCRStdPalette, 96,  75,  7200,    8,     8, kernel_font_8x8,   32,  255};
    155 
    156 /* horizontal 64kHz */
    157 
    158    struct MonDef MON_768_600_80  = { 50000000, 24,  768, 600,   97,104,112,122,119, 601, 606, 616, 628, 628,
    159           4, NCRStdPalette, 96,  75,  7200,    8,     8, kernel_font_8x8,   32,  255};
    160 
    161    struct MonDef MON_1024_768_80 = { 90000000, 24, 1024, 768,  129,130,141,172,169, 769, 770, 783, 804, 804,
    162           4, NCRStdPalette,128,  96, 12288,    8,     8, kernel_font_8x8,   32,  255};
    163 
    164 /*                                     FQ     FLG    MW   MH   HBS HSS HSE HBE  HT  VBS  VSS  VSE  VBE   VT  */
    165  struct MonDef MON_1024_768_80_G = { 90000000, 0,  1024, 768,  257,258,280,344,343, 769, 770, 783, 804, 804,
    166           8, NCRStdPalette, 1024, 768, 12288,    8,     8, kernel_font_8x8,   32,  255};
    167 
    168    struct MonDef MON_1024_1024_59= { 90000000, 24, 1024,1024,  129,130,141,173,170,1025,1059,1076,1087,1087,
    169           4, NCRStdPalette,128, 128, 16384,    8,     8, kernel_font_8x8,   32,  255};
    170 
    171 /* WARNING: THE FOLLOWING MONITOR MODES EXCEED THE 90-MHz LIMIT THE PROCESSOR
    172             HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
    173             MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)!     */
    174 
    175    struct MonDef MON_1280_1024_60= {110000000,  24, 1280,1024,  161,162,176,211,208,1025,1026,1043,1073,1073,
    176           4, NCRStdPalette,160, 128, 20480,    8,     8, kernel_font_8x8,   32,  255};
    177 
    178  struct MonDef MON_1280_1024_60_G= {110000000,   0, 1280,1024,  321,322,349,422,421,1025,1026,1043,1073,1073,
    179           8, NCRStdPalette,1280,1024, 20480,    8,     8, kernel_font_8x8,   32,  255};
    180 
    181 /* horizontal 75kHz */
    182 
    183    struct MonDef MON_1280_1024_69= {120000000,  24, 1280,1024,  161,162,175,200,197,1025,1026,1043,1073,1073,
    184           4, NCRStdPalette,160, 128, 20480,    8,     8, kernel_font_8x8,   32,  255};
    185 
    186 #else
    187 
    188 struct MonDef monitor_defs[] = {
    189 /* horizontal 31.5 kHz */
    190 
    191    { 50000000,  28,  640, 512,   81, 86, 93, 98, 95, 513, 513, 521, 535, 535,
    192           4, NCRStdPalette, 80,  64,  5120,    8,     8, kernel_font_8x8,   32,  255},
    193 
    194 /* horizontal 38kHz */
    195 
    196    { 75000000,  28,  768, 600,   97, 99,107,120,117, 601, 615, 625, 638, 638,
    197           4, NCRStdPalette, 96,  75,  7200,    8,     8, kernel_font_8x8,   32,  255},
    198 
    199 /* horizontal 64kHz */
    200 
    201    { 50000000, 24,  768, 600,   97,104,112,122,119, 601, 606, 616, 628, 628,
    202           4, NCRStdPalette, 96,  75,  7200,    8,     8, kernel_font_8x8,   32,  255},
    203 
    204    { 90000000, 24, 1024, 768,  129,130,141,172,169, 769, 770, 783, 804, 804,
    205           4, NCRStdPalette,128,  96, 12288,    8,     8, kernel_font_8x8,   32,  255},
    206 
    207    /* GFX modes */
    208 
    209 /* horizontal 31.5 kHz */
    210 
    211    { 50000000,   4,  640, 480,  161,171,184,196,195, 481, 484, 492, 502, 502,
    212           8, NCRStdPalette,640, 480,  5120,    8,     8, kernel_font_8x8,   32,  255},
    213 
    214 /* horizontal 64kHz */
    215 
    216    { 90000000, 0,  1024, 768,  257,258,280,344,343, 769, 770, 783, 804, 804,
    217           8, NCRStdPalette, 1024, 768, 12288,    8,     8, kernel_font_8x8,   32,  255},
    218 
    219 /* WARNING: THE FOLLOWING MONITOR MODES EXCEED THE 90-MHz LIMIT THE PROCESSOR
    220             HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
    221             MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)!     */
    222 
    223    {110000000,   0, 1280,1024,  321,322,349,422,421,1025,1026,1043,1073,1073,
    224           8, NCRStdPalette,1280,1024, 20480,    8,     8, kernel_font_8x8,   32,  255},
    225 };
    226 
    227 static const char *monitor_descr[] = {
    228   "80x64 (640x512) 31.5kHz",
    229   "96x75 (768x600) 38kHz",
    230   "96x75 (768x600) 64kHz",
    231   "128x96 (1024x768) 64kHz",
    232 
    233   "GFX (640x480) 31.5kHz",
    234   "GFX (1024x768) 64kHz",
    235   "GFX (1280x1024) 64kHz ***EXCEEDS CHIP LIMIT!!!***",
    236 };
    237 
    238 int retina_mon_max = sizeof (monitor_defs)/sizeof (monitor_defs[0]);
    239 
    240 /* patchable */
    241 int retina_default_mon = 0;
    242 int retina_default_gfx = 4;
    243 
    244 #endif
    245 
    246 
    247 static struct MonDef *current_mon;
    248 
    249 /* -------------- START OF CODE -------------- */
    250 
    251 
    252 static const long FQTab[16] =
    253 { 25175000,  28322000,  36000000,  65000000,
    254   44900000,  50000000,  80000000,  75000000,
    255   56644000,  63000000,  72000000, 130000000,
    256   90000000, 100000000, 110000000, 120000000 };
    257 
    258 
    259 /*--------------------------------------------------*/
    260 /*--------------------------------------------------*/
    261 
    262 #if 0
    263 static struct MonDef *default_monitor = &DEFAULT_MONDEF;
    264 #endif
    265 
    266 int retina_alive(struct MonDef *);
    267 static int rt_load_mon(struct grf_softc *, struct MonDef *);
    268 
    269 
    270 /*
    271  * used to query the retina to see if its alive (?)
    272  */
    273 int
    274 retina_alive(struct MonDef *mdp)
    275 {
    276 	short clksel;
    277 
    278 	for (clksel = 15; clksel; clksel--) {
    279 		if (FQTab[clksel] == mdp->FQ)
    280 			break;
    281 	}
    282 	if (clksel < 0)
    283 		return(0);
    284 	if (mdp->DEP != 4)
    285 		return(1);
    286 	if (mdp->FX == 4 || (mdp->FX >= 7 && mdp->FX <= 16))
    287 		return(1);
    288 	return(0);
    289 }
    290 
    291 static int
    292 rt_load_mon(struct grf_softc *gp, struct MonDef *md)
    293 {
    294 	struct grfinfo *gi = &gp->g_display;
    295 	volatile void *ba;
    296 	volatile char *fb;
    297 	short FW, clksel, HDE, VDE;
    298 
    299 	for (clksel = 15; clksel; clksel--) {
    300 		if (FQTab[clksel] == md->FQ) break;
    301 	}
    302 	if (clksel < 0)
    303 		return(0);
    304 
    305 	ba = gp->g_regkva;
    306 	fb = (volatile char*)gp->g_fbkva;
    307 
    308 	FW = 0;
    309 	if (md->DEP == 4) {
    310 		switch (md->FX) {
    311 		    case 4:
    312 			FW = 0;
    313 			break;
    314 		    case 7:
    315 			FW = 1;
    316 			break;
    317 		    case 8:
    318 			FW = 2;
    319 			break;
    320 		    case 9:
    321 			FW = 3;
    322 			break;
    323 		    case 10:
    324 			FW = 4;
    325 			break;
    326 		    case 11:
    327 			FW = 5;
    328 			break;
    329 		    case 12:
    330 			FW = 6;
    331 			break;
    332 		    case 13:
    333 			FW = 7;
    334 			break;
    335 		    case 14:
    336 			FW = 8;
    337 			break;
    338 		    case 15:
    339 			FW = 9;
    340 			break;
    341 		    case 16:
    342 			FW = 11;
    343 			break;
    344 		    default:
    345 			return(0);
    346 			break;
    347 		};
    348 	}
    349 
    350         if (md->DEP == 4) HDE = (md->MW+md->FX-1)/md->FX;
    351         else              HDE = (md->MW+3)/4;
    352 	VDE = md->MH-1;
    353 
    354 	/* hmm... */
    355 	fb[0x8000] = 0;
    356 
    357 		/* enable extension registers */
    358 	WSeq (ba, SEQ_ID_EXTENDED_ENABLE,	0x05);
    359 
    360 #if 0
    361 	/* program the clock oscillator */
    362 	vgaw (ba, GREG_MISC_OUTPUT_W, 0xe3 | ((clksel & 3) * 0x04));
    363 	vgaw (ba, GREG_FEATURE_CONTROL_W, 0x00);
    364 
    365 	/* XXXX according to the NCR specs, this register should be set to 1
    366 	   XXXX before doing the MISC_OUTPUT setting and CLOCKING_MODE
    367 	   XXXX setting. */
    368 	WSeq (ba, SEQ_ID_RESET, 		0x03);
    369 
    370 	WSeq (ba, SEQ_ID_CLOCKING_MODE, 	0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8));
    371 	WSeq (ba, SEQ_ID_MAP_MASK, 		0x0f);
    372 	WSeq (ba, SEQ_ID_CHAR_MAP_SELECT, 	0x00);
    373 		/* odd/even write select + extended memory */
    374 	WSeq (ba, SEQ_ID_MEMORY_MODE, 	0x06);
    375 	/* XXXX I think this order of setting RESET is wrong... */
    376 	WSeq (ba, SEQ_ID_RESET, 		0x01);
    377 	WSeq (ba, SEQ_ID_RESET, 		0x03);
    378 #else
    379 	WSeq (ba, SEQ_ID_RESET, 		0x01);
    380 
    381 		/* set font width + rest of clocks */
    382 	WSeq (ba, SEQ_ID_EXT_CLOCK_MODE,	0x30 | (FW & 0x0f) | ((clksel & 4) / 4 * 0x40) );
    383 		/* another clock bit, plus hw stuff */
    384 	WSeq (ba, SEQ_ID_MISC_FEATURE_SEL,	0xf4 | (clksel & 8) );
    385 
    386 	/* program the clock oscillator */
    387 	vgaw (ba, GREG_MISC_OUTPUT_W, 		0xe3 | ((clksel & 3) * 0x04));
    388 	vgaw (ba, GREG_FEATURE_CONTROL_W, 	0x00);
    389 
    390 	WSeq (ba, SEQ_ID_CLOCKING_MODE, 	0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8));
    391 	WSeq (ba, SEQ_ID_MAP_MASK, 		0x0f);
    392 	WSeq (ba, SEQ_ID_CHAR_MAP_SELECT, 	0x00);
    393 		/* odd/even write select + extended memory */
    394 	WSeq (ba, SEQ_ID_MEMORY_MODE, 		0x06);
    395 	WSeq (ba, SEQ_ID_RESET, 		0x03);
    396 #endif
    397 
    398 		/* monochrome cursor */
    399 	WSeq (ba, SEQ_ID_CURSOR_CONTROL,	0x00);
    400 		/* bank0 */
    401 	WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI,	0x00);
    402 	WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO,	0x00);
    403 	WSeq (ba, SEQ_ID_DISP_OFF_HI , 		0x00);
    404 	WSeq (ba, SEQ_ID_DISP_OFF_LO , 		0x00);
    405 		/* bank0 */
    406 	WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI,	0x00);
    407 	WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO,	0x00);
    408 		/* 1M-chips + ena SEC + ena EMem + rw PrimA0/rw Sec/B0 */
    409 	WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA,	0x3 | 0x4 | 0x10 | 0x40);
    410 #if 0
    411 		/* set font width + rest of clocks */
    412 	WSeq (ba, SEQ_ID_EXT_CLOCK_MODE,	0x30 | (FW & 0x0f) | ((clksel & 4) / 4 * 0x40) );
    413 #endif
    414 	if (md->DEP == 4) {
    415 			/* no ext-chain4 + no host-addr-bit-16 */
    416 		WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR,	0x00);
    417 			/* no packed/nibble + no 256bit gfx format */
    418 		WSeq (ba, SEQ_ID_EXT_PIXEL_CNTL,	0x00);
    419 	}
    420 	else {
    421 		WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR,	0x02);
    422 			/* 256bit gfx format */
    423 		WSeq (ba, SEQ_ID_EXT_PIXEL_CNTL,	0x01);
    424 	}
    425 		/* AT-interface */
    426 	WSeq (ba, SEQ_ID_BUS_WIDTH_FEEDB,	0x06);
    427 		/* see fg/bg color expansion */
    428 	WSeq (ba, SEQ_ID_COLOR_EXP_WFG,		0x01);
    429 	WSeq (ba, SEQ_ID_COLOR_EXP_WBG,		0x00);
    430 	WSeq (ba, SEQ_ID_EXT_RW_CONTROL,	0x00);
    431 #if 0
    432 		/* another clock bit, plus hw stuff */
    433 	WSeq (ba, SEQ_ID_MISC_FEATURE_SEL,	0xf4 | (clksel & 8) );
    434 #endif
    435 		/* don't tristate PCLK and PIX */
    436 	WSeq (ba, SEQ_ID_COLOR_KEY_CNTL,	0x40 );
    437 		/* reset CRC circuit */
    438 	WSeq (ba, SEQ_ID_CRC_CONTROL,		0x00 );
    439 		/* set RAS/CAS swap */
    440 	WSeq (ba, SEQ_ID_PERF_SELECT,		0x20);
    441 
    442 	WCrt (ba, CRT_ID_END_VER_RETR,		(md->VSE & 0xf ) | 0x20);
    443 	WCrt (ba, CRT_ID_HOR_TOTAL,		md->HT   & 0xff);
    444 	WCrt (ba, CRT_ID_HOR_DISP_ENA_END,	(HDE-1)  & 0xff);
    445 	WCrt (ba, CRT_ID_START_HOR_BLANK,	md->HBS  & 0xff);
    446 	WCrt (ba, CRT_ID_END_HOR_BLANK,		(md->HBE & 0x1f) | 0x80);
    447 
    448 	WCrt (ba, CRT_ID_START_HOR_RETR,	md->HSS  & 0xff);
    449 	WCrt (ba, CRT_ID_END_HOR_RETR,		(md->HSE & 0x1f) | ((md->HBE & 0x20)/ 0x20 * 0x80));
    450 	WCrt (ba, CRT_ID_VER_TOTAL,		(md->VT  & 0xff));
    451 	WCrt (ba, CRT_ID_OVERFLOW,		(( (md->VSS  & 0x200) / 0x200 * 0x80)
    452 						 | ((VDE     & 0x200) / 0x200 * 0x40)
    453 						 | ((md->VT  & 0x200) / 0x200 * 0x20)
    454 						 | 				0x10
    455 						 | ((md->VBS & 0x100) / 0x100 * 8   )
    456 						 | ((md->VSS & 0x100) / 0x100 * 4   )
    457 						 | ((VDE     & 0x100) / 0x100 * 2   )
    458 						 | ((md->VT  & 0x100) / 0x100       )));
    459 	WCrt (ba, CRT_ID_PRESET_ROW_SCAN,	0x00);
    460 
    461 	if (md->DEP == 4) {
    462 		WCrt (ba, CRT_ID_MAX_SCAN_LINE,	((  (md->FLG & MDF_DBL)/ MDF_DBL * 0x80)
    463 						 | 				   0x40
    464 						 | ((md->VBS & 0x200)/0x200	 * 0x20)
    465 						 | ((md->FY-1) 			 & 0x1f)));
    466 	}
    467 	else {
    468 		WCrt (ba, CRT_ID_MAX_SCAN_LINE,	((  (md->FLG & MDF_DBL)/ MDF_DBL * 0x80)
    469 						 | 				   0x40
    470 						 | ((md->VBS & 0x200)/0x200	 * 0x20)
    471 						 | (0	 			 & 0x1f)));
    472 	}
    473 
    474 	WCrt (ba, CRT_ID_CURSOR_START, (md->FY & 0x1f) - 2);
    475 	WCrt (ba, CRT_ID_CURSOR_END, (md->FY & 0x1f) - 1);
    476 
    477 	WCrt (ba, CRT_ID_START_ADDR_HIGH, 0x00);
    478 	WCrt (ba, CRT_ID_START_ADDR_LOW, 0x00);
    479 
    480 	WCrt (ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
    481 	WCrt (ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
    482 
    483 	WCrt (ba, CRT_ID_START_VER_RETR, md->VSS & 0xff);
    484 	WCrt (ba, CRT_ID_END_VER_RETR, (md->VSE & 0x0f) | 0x80 | 0x20);
    485 	WCrt (ba, CRT_ID_VER_DISP_ENA_END, VDE & 0xff);
    486 	if (md->DEP == 4)
    487 		WCrt (ba, CRT_ID_OFFSET, (HDE / 2)  & 0xff);
    488 	else
    489 		WCrt (ba, CRT_ID_OFFSET, (md->TX / 8)  & 0xff);
    490 
    491 	WCrt (ba, CRT_ID_UNDERLINE_LOC, (md->FY-1) & 0x1f);
    492 	WCrt (ba, CRT_ID_START_VER_BLANK, md->VBS  & 0xff);
    493 	WCrt (ba, CRT_ID_END_VER_BLANK, md->VBE & 0xff);
    494 		/* byte mode + wrap + select row scan counter + cms */
    495 	WCrt (ba, CRT_ID_MODE_CONTROL, 0xe3);
    496 	WCrt (ba, CRT_ID_LINE_COMPARE, 0xff);
    497 
    498 		/* enable extended end bits + those bits */
    499 	WCrt (ba, CRT_ID_EXT_HOR_TIMING1, ( 					 0x20
    500 					 | ((md->FLG & MDF_LACE)  / MDF_LACE   * 0x10)
    501 					 | ((md->HT  & 0x100) / 0x100          * 0x01)
    502 					 | (((HDE-1) & 0x100) / 0x100 	       * 0x02)
    503 					 | ((md->HBS & 0x100) / 0x100 	       * 0x04)
    504 					 | ((md->HSS & 0x100) / 0x100 	       * 0x08)));
    505 
    506 	if (md->DEP == 4)
    507 		WCrt (ba, CRT_ID_EXT_START_ADDR, (((HDE / 2) & 0x100)/0x100 * 16));
    508 	else
    509 		WCrt (ba, CRT_ID_EXT_START_ADDR, (((md->TX / 8) & 0x100)/0x100 * 16));
    510 
    511 	WCrt (ba, CRT_ID_EXT_HOR_TIMING2,  ( ((md->HT  & 0x200)/ 0x200	* 0x01)
    512 					 | (((HDE-1) & 0x200)/ 0x200	* 0x02)
    513 					 | ((md->HBS & 0x200)/ 0x200	* 0x04)
    514 					 | ((md->HSS & 0x200)/ 0x200	* 0x08)
    515 					 | ((md->HBE & 0xc0) / 0x40	* 0x10)
    516 					 | ((md->HSE & 0x60) / 0x20	* 0x40)));
    517 
    518 	WCrt (ba, CRT_ID_EXT_VER_TIMING, ( ((md->VSE & 0x10) / 0x10	* 0x80)
    519 					 | ((md->VBE & 0x300)/ 0x100	* 0x20)
    520 					 |				0x10
    521 					 | ((md->VSS & 0x400)/ 0x400	* 0x08)
    522 					 | ((md->VBS & 0x400)/ 0x400	* 0x04)
    523 					 | ((VDE     & 0x400)/ 0x400	* 0x02)
    524 					 | ((md->VT  & 0x400)/ 0x400	* 0x01)));
    525 
    526 	WGfx (ba, GCT_ID_SET_RESET, 0x00);
    527 	WGfx (ba, GCT_ID_ENABLE_SET_RESET, 0x00);
    528 	WGfx (ba, GCT_ID_COLOR_COMPARE, 0x00);
    529 	WGfx (ba, GCT_ID_DATA_ROTATE, 0x00);
    530 	WGfx (ba, GCT_ID_READ_MAP_SELECT, 0x00);
    531 	WGfx (ba, GCT_ID_GRAPHICS_MODE, 0x00);
    532 	if (md->DEP == 4)
    533 		WGfx (ba, GCT_ID_MISC, 0x04);
    534 	else
    535 		WGfx (ba, GCT_ID_MISC, 0x05);
    536 	WGfx (ba, GCT_ID_COLOR_XCARE, 0xff);
    537 	WGfx (ba, GCT_ID_BITMASK, 0xff);
    538 
    539 	/* reset the Attribute Controller flipflop */
    540 	vgar (ba, GREG_STATUS1_R);
    541 	WAttr (ba, ACT_ID_PALETTE0, 0x00);
    542 	WAttr (ba, ACT_ID_PALETTE1, 0x01);
    543 	WAttr (ba, ACT_ID_PALETTE2, 0x02);
    544 	WAttr (ba, ACT_ID_PALETTE3, 0x03);
    545 	WAttr (ba, ACT_ID_PALETTE4, 0x04);
    546 	WAttr (ba, ACT_ID_PALETTE5, 0x05);
    547 	WAttr (ba, ACT_ID_PALETTE6, 0x06);
    548 	WAttr (ba, ACT_ID_PALETTE7, 0x07);
    549 	WAttr (ba, ACT_ID_PALETTE8, 0x08);
    550 	WAttr (ba, ACT_ID_PALETTE9, 0x09);
    551 	WAttr (ba, ACT_ID_PALETTE10, 0x0a);
    552 	WAttr (ba, ACT_ID_PALETTE11, 0x0b);
    553 	WAttr (ba, ACT_ID_PALETTE12, 0x0c);
    554 	WAttr (ba, ACT_ID_PALETTE13, 0x0d);
    555 	WAttr (ba, ACT_ID_PALETTE14, 0x0e);
    556 	WAttr (ba, ACT_ID_PALETTE15, 0x0f);
    557 
    558 	vgar (ba, GREG_STATUS1_R);
    559 	if (md->DEP == 4)
    560 		WAttr (ba, ACT_ID_ATTR_MODE_CNTL, 0x08);
    561 	else
    562 		WAttr (ba, ACT_ID_ATTR_MODE_CNTL, 0x09);
    563 
    564 	WAttr (ba, ACT_ID_OVERSCAN_COLOR, 0x00);
    565 	WAttr (ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
    566 	WAttr (ba, ACT_ID_HOR_PEL_PANNING, 0x00);
    567 	WAttr (ba, ACT_ID_COLOR_SELECT,	0x00);
    568 
    569 	vgar (ba, GREG_STATUS1_R);
    570 		/* I have *NO* idea what strobing reg-0x20 might do... */
    571 	vgaw (ba, ACT_ADDRESS_W, 0x20);
    572 
    573 	if (md->DEP == 4)
    574 		WCrt (ba, CRT_ID_MAX_SCAN_LINE,	( ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80)
    575 						|	                          0x40
    576 						| ((md->VBS & 0x200)/0x200	* 0x20)
    577 						| ((md->FY-1) 			& 0x1f)));
    578 	else
    579 		WCrt (ba, CRT_ID_MAX_SCAN_LINE,	( ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80)
    580 						|	                          0x40
    581 						| ((md->VBS & 0x200)/0x200	* 0x20)
    582 						| (0	 			& 0x1f)));
    583 
    584 
    585 	/* not it's time for guessing... */
    586 
    587 	vgaw (ba, VDAC_REG_D, 	   0x02);
    588 
    589 		/* if this does what I think it does, it selects DAC
    590 		   register 0, and writes the palette in subsequent
    591 		   registers, thus it works similar to the WD33C93
    592 		   select/data mechanism */
    593 	vgaw (ba, VDAC_REG_SELECT, 0x00);
    594 
    595 	{
    596 
    597 		short x = 15;
    598 		const unsigned char * col = md->PAL;
    599 		do {
    600 
    601 			vgaw (ba, VDAC_REG_DATA, *col++);
    602 			vgaw (ba, VDAC_REG_DATA, *col++);
    603 			vgaw (ba, VDAC_REG_DATA, *col++);
    604 
    605 
    606 		} while (x--);
    607 
    608 		if (md->DEP != 4) {
    609 			short xx = 256-17;
    610 			unsigned char cols = 16;
    611 			do {
    612 
    613 				vgaw(ba, VDAC_REG_DATA, cols);
    614 				vgaw(ba, VDAC_REG_DATA, cols);
    615 				vgaw(ba, VDAC_REG_DATA, cols);
    616 				cols++;
    617 
    618 			} while (xx--);
    619 		}
    620 	}
    621 
    622 
    623 	/* now load the font into maps 2 (and 3 for fonts wider than 8 pixels) */
    624 	if (md->DEP == 4) {
    625 
    626 		/* first set the whole font memory to a test-pattern, so we
    627 		   can see if something that shouldn't be drawn IS drawn.. */
    628 		{
    629 			volatile char *c = fb;
    630 			long x;
    631 			Map(2);
    632 
    633 			for (x = 0; x < 65536; x++) {
    634 				*c++ = (x & 1)? 0xaa : 0x55;
    635 			}
    636 		}
    637 
    638 		{
    639 			volatile char *c = fb;
    640 			long x;
    641 			Map(3);
    642 
    643 			for (x = 0; x < 65536; x++) {
    644 				*c++ = (x & 1)? 0xaa : 0x55;
    645 			}
    646 		}
    647 
    648 		{
    649 		  /* ok, now position at first defined character, and
    650 		     copy over the images */
    651 		  volatile char *c = fb + md->FLo * 32;
    652 		  const unsigned char * f = md->FData;
    653 		  unsigned short z;
    654 
    655 		  Map(2);
    656 		  for (z = md->FLo; z <= md->FHi; z++) {
    657 
    658 			short y = md->FY-1;
    659 			if (md->FX > 8){
    660 				do {
    661 					*c++ = *f;
    662 					f += 2;
    663 				} while (y--);
    664 			}
    665 			else {
    666 				do {
    667 					*c++ = *f++;
    668 				} while (y--);
    669 			}
    670 
    671 			c += 32-md->FY;
    672 
    673 		  }
    674 
    675 		  if (md->FX > 8) {
    676 			unsigned short zz;
    677 
    678 			Map(3);
    679 			c = fb + md->FLo*32;
    680 			f = md->FData+1;
    681 			for (zz = md->FLo; z <= md->FHi; zz++) {
    682 
    683 				short y = md->FY-1;
    684 				do {
    685 					*c++ = *f;
    686 					f += 2;
    687 				} while (y--);
    688 
    689 				c += 32-md->FY;
    690 
    691 			}
    692 		  }
    693 		}
    694 
    695 	}
    696 
    697 		/* select map 0 */
    698 	WGfx (ba, GCT_ID_READ_MAP_SELECT,	0);
    699 	if (md->DEP == 4)
    700 			/* allow writes into maps 0 and 1 */
    701 		WSeq (ba, SEQ_ID_MAP_MASK,		3);
    702 	else
    703 			/* allow writes into all maps */
    704 		WSeq (ba, SEQ_ID_MAP_MASK,		0x0f);
    705 
    706 		/* select extended chain4 addressing:
    707 		    !A0/!A1	map 0	character to be displayed
    708 		    !A1/ A1	map 1	attribute of that character
    709 		     A0/!A1	map 2	not used (masked out, ignored)
    710 		     A0/ A1 	map 3	not used (masked out, ignored) */
    711 	WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR,	RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) | 0x02);
    712 
    713 	if (md->DEP == 4) {
    714 		/* position in display memory */
    715 		volatile unsigned short * c = (volatile unsigned short *) fb;
    716 
    717 		/* fill with blank, white on black */
    718 		const unsigned short fill_val = 0x2010;
    719 		short x = md->XY;
    720 		do {
    721 			*c = fill_val;
    722 			c += 2; } while (x--);
    723 
    724 		/* I won't comment this :-)) */
    725 		c = (volatile unsigned short *) fb;
    726 		c += (md->TX-6)*2;
    727 		{
    728 		  unsigned short init_msg[6] = {0x520a, 0x450b, 0x540c, 0x490d, 0x4e0e, 0x410f};
    729 		  unsigned short * f = init_msg;
    730 		  x = 5;
    731 		  do {
    732 			*c = *f++;
    733 			c += 2;
    734 	 	  } while (x--);
    735 	 	}
    736 	}
    737 	else if (md->DEP == 8) {
    738 		/* could clear the gfx screen here, but that's what the X server does anyway */
    739 	        ;
    740 	}
    741 
    742 	gp->g_data	= (void *)md;
    743 	gi->gd_regaddr  = (void *)ztwopa(ba);
    744 	gi->gd_regsize  = 64*1024;
    745 
    746 	gi->gd_fbaddr   = (void *)ztwopa(fb);
    747 	gi->gd_fbsize   = 64*1024;	/* larger, but that's whats mappable */
    748 
    749 	gi->gd_colors   = 1 << md->DEP;
    750 	gi->gd_planes   = md->DEP;
    751 
    752 	gi->gd_fbwidth  = md->MW;
    753 	gi->gd_fbheight = md->MH;
    754 	gi->gd_fbx	= 0;
    755 	gi->gd_fby	= 0;
    756 	gi->gd_dwidth   = md->TX * md->FX;
    757 	gi->gd_dheight  = md->TY * md->FY;
    758 	gi->gd_dx	= 0;
    759 	gi->gd_dy	= 0;
    760 
    761 	/* initialized, works, return 1 */
    762 	return(1);
    763 }
    764 
    765 void grfrtattach(device_t, device_t, void *);
    766 int grfrtprint(void *, const char *);
    767 int grfrtmatch(device_t, cfdata_t, void *);
    768 
    769 int rt_mode(struct grf_softc *, u_long, void *, u_long, int);
    770 static int rt_getvmode(struct grf_softc *, struct grfvideo_mode *);
    771 static int rt_setvmode(struct grf_softc *, unsigned, int);
    772 int rt_getspritepos(struct grf_softc *, struct grf_position *);
    773 int rt_setspritepos(struct grf_softc *, struct grf_position *);
    774 int rt_getspriteinfo(struct grf_softc *, struct grf_spriteinfo *);
    775 int rt_setspriteinfo(struct grf_softc *, struct grf_spriteinfo *);
    776 int rt_getspritemax(struct grf_softc *, struct grf_position *);
    777 int rt_getcmap(struct grf_softc *, struct grf_colormap *);
    778 int rt_putcmap(struct grf_softc *, struct grf_colormap *);
    779 int rt_bitblt(struct grf_softc *, struct grf_bitblt *);
    780 int rt_blank(struct grf_softc *, int *);
    781 
    782 CFATTACH_DECL_NEW(grfrt, sizeof(struct grf_softc),
    783     grfrtmatch, grfrtattach, NULL, NULL);
    784 
    785 /*
    786  * only used in console init
    787  */
    788 static struct cfdata *cfdata;
    789 
    790 /*
    791  * we make sure to only init things once.  this is somewhat
    792  * tricky regarding the console.
    793  */
    794 int
    795 grfrtmatch(device_t parent, cfdata_t cf, void *aux)
    796 {
    797 #ifdef RETINACONSOLE
    798 	static int rtconunit = -1;
    799 #endif
    800 	struct zbus_args *zap;
    801 
    802 	zap = aux;
    803 
    804 	/*
    805 	 * allow only one retina console
    806 	 */
    807 	if (amiga_realconfig == 0)
    808 #ifdef RETINACONSOLE
    809 		if (rtconunit != -1)
    810 #endif
    811 			return(0);
    812 	/*
    813 	 * check that this is a retina board.
    814 	 */
    815 	if (zap->manid != 18260 || zap->prodid != 6)
    816 		return(0);
    817 
    818 #ifdef RETINACONSOLE
    819 	if (amiga_realconfig == 0 || rtconunit != cf->cf_unit) {
    820 #endif
    821 		if ((unsigned)retina_default_mon >= retina_mon_max ||
    822 		    monitor_defs[retina_default_mon].DEP == 8)
    823 			retina_default_mon = 0;
    824 
    825 		current_mon = monitor_defs + retina_default_mon;
    826 		if (retina_alive(current_mon) == 0)
    827 			return(0);
    828 #ifdef RETINACONSOLE
    829 		if (amiga_realconfig == 0) {
    830 			rtconunit = cf->cf_unit;
    831 			cfdata = cf;
    832 		}
    833 	}
    834 #endif
    835 	return(1);
    836 }
    837 
    838 /*
    839  * attach to the grfbus (zbus)
    840  */
    841 void
    842 grfrtattach(device_t parent, device_t self, void *aux)
    843 {
    844 	static struct grf_softc congrf;
    845 	struct device temp;
    846 	struct zbus_args *zap;
    847 	struct grf_softc *gp;
    848 
    849 	zap = aux;
    850 
    851 	if (self == NULL) {
    852 		gp = &congrf;
    853 		gp->g_device = &temp;
    854 		temp.dv_private = gp;
    855 	} else {
    856 		gp = device_private(self);
    857 		gp->g_device = self;
    858 	}
    859 
    860 	if (self != NULL && congrf.g_regkva != 0) {
    861 		/*
    862 		 * we inited earlier just copy the info
    863 		 * take care not to copy the device struct though.
    864 		 */
    865 		memcpy(&gp->g_display, &congrf.g_display,
    866 		    (char *)&gp[1] - (char *)&gp->g_display);
    867 	} else {
    868 		gp->g_regkva = (volatile void *)zap->va;
    869 		gp->g_fbkva = (volatile char *)zap->va + 64 * 1024;
    870 		gp->g_unit = GRF_RETINAII_UNIT;
    871 		gp->g_flags = GF_ALIVE;
    872 		gp->g_mode = rt_mode;
    873 #if NITE > 0
    874 		gp->g_conpri = grfrt_cnprobe();
    875 		grfrt_iteinit(gp);
    876 #endif
    877 		(void)rt_load_mon(gp, current_mon);
    878 	}
    879 	if (self != NULL)
    880 		printf("\n");
    881 	/*
    882 	 * attach grf
    883 	 */
    884 	amiga_config_found(cfdata, self, gp, grfrtprint);
    885 }
    886 
    887 int
    888 grfrtprint(void *aux, const char *pnp)
    889 {
    890 	if (pnp)
    891 		aprint_normal("grf%d at %s", ((struct grf_softc *)aux)->g_unit,
    892 			pnp);
    893 	return(UNCONF);
    894 }
    895 
    896 static int
    897 rt_getvmode(struct grf_softc *gp, struct grfvideo_mode *vm)
    898 {
    899 	struct MonDef *md;
    900 	int vmul;
    901 
    902 	if (vm->mode_num && vm->mode_num > retina_mon_max)
    903 		return (EINVAL);
    904 
    905 	if (! vm->mode_num)
    906 		vm->mode_num = (current_mon - monitor_defs) + 1;
    907 
    908 	md = monitor_defs + (vm->mode_num - 1);
    909 	strncpy (vm->mode_descr, monitor_descr[vm->mode_num - 1],
    910 	    sizeof (vm->mode_descr));
    911 	vm->pixel_clock  = md->FQ;
    912 	vm->disp_width   = md->MW;
    913 	vm->disp_height  = md->MH;
    914 	vm->depth        = md->DEP;
    915 
    916 	/*
    917 	 * From observation of the monitor definition table above, I guess that
    918 	 * the horizontal timings are in units of longwords. Hence, I get the
    919 	 * pixels by multiplication with 32 and division by the depth.
    920 	 * The text modes, apparently marked by depth == 4, are even more weird.
    921 	 * According to a comment above, they are computed from a depth==8 mode
    922 	 * (thats for us: * 32 / 8) by applying another factor of 4 / font width.
    923 	 * Reverse applying the latter formula most of the constants cancel
    924 	 * themselves and we are left with a nice (* font width).
    925 	 * That is, internal timings are in units of longwords for graphics
    926 	 * modes, or in units of characters widths for text modes.
    927 	 * We better don't WRITE modes until this has been real live checked.
    928 	 * 			- Ignatios Souvatzis
    929 	 */
    930 
    931 	if (md->DEP != 4) {
    932 		vm->hblank_start = md->HBS * 32 / md->DEP;
    933 		vm->hsync_start  = md->HSS * 32 / md->DEP;
    934 		vm->hsync_stop   = md->HSE * 32 / md->DEP;
    935 		vm->htotal       = md->HT * 32 / md->DEP;
    936 	} else {
    937 		vm->hblank_start = md->HBS * md->FX;
    938 		vm->hsync_start  = md->HSS * md->FX;
    939 		vm->hsync_stop   = md->HSE * md->FX;
    940 		vm->htotal       = md->HT * md->FX;
    941 	}
    942 
    943 
    944 	/* XXX move vm->disp_flags and vmul to rt_load_mon
    945 	* if rt_setvmode can add new modes with grfconfig */
    946 	vm->disp_flags = 0;
    947 	vmul = 2;
    948 	if (md->FLG & MDF_DBL) {
    949 		vm->disp_flags |= GRF_FLAGS_DBLSCAN;
    950 		vmul = 4;
    951 	}
    952 	if (md->FLG & MDF_LACE) {
    953 		vm->disp_flags |= GRF_FLAGS_LACE;
    954 		vmul = 1;
    955 	}
    956 	vm->vblank_start = md->VBS * vmul / 2;
    957 	vm->vsync_start  = md->VSS * vmul / 2;
    958 	vm->vsync_stop   = md->VSE * vmul / 2;
    959 	vm->vtotal       = md->VT * vmul / 2;
    960 
    961 	return (0);
    962 }
    963 
    964 
    965 static int
    966 rt_setvmode(struct grf_softc *gp, unsigned mode, int txtonly)
    967 {
    968 	int error;
    969 
    970 	if (!mode || mode > retina_mon_max)
    971 		return (EINVAL);
    972 
    973 	if (txtonly && monitor_defs[mode-1].DEP == 8)
    974 		return (EINVAL);
    975 
    976 	current_mon = monitor_defs + (mode - 1);
    977 
    978 	error = rt_load_mon (gp, current_mon) ? 0 : EINVAL;
    979 
    980 	return (error);
    981 }
    982 
    983 
    984 /*
    985  * Change the mode of the display.
    986  * Return a UNIX error number or 0 for success.
    987  */
    988 int
    989 rt_mode(struct grf_softc *gp, u_long cmd, void *arg, u_long a2, int a3)
    990 {
    991 /* implement these later... */
    992 
    993 	switch (cmd) {
    994 	    case GM_GRFON:
    995 		rt_setvmode (gp, retina_default_gfx + 1, 0);
    996 		return (0);
    997 
    998 	    case GM_GRFOFF:
    999 		rt_setvmode (gp, retina_default_mon + 1, 0);
   1000 		return (0);
   1001 
   1002 	    case GM_GRFCONFIG:
   1003 		return (0);
   1004 
   1005 	    case GM_GRFGETVMODE:
   1006 		return (rt_getvmode (gp, (struct grfvideo_mode *) arg));
   1007 
   1008 	    case GM_GRFSETVMODE:
   1009 		return (rt_setvmode (gp, *(unsigned *) arg, 1));
   1010 
   1011 	    case GM_GRFGETNUMVM:
   1012 		*(int *)arg = retina_mon_max;
   1013 		return (0);
   1014 
   1015 	    case GM_GRFIOCTL:
   1016 		return (rt_ioctl (gp, a2, arg));
   1017 
   1018 	    default:
   1019 		break;
   1020 	}
   1021 
   1022 	return (EPASSTHROUGH);
   1023 }
   1024 
   1025 int
   1026 rt_ioctl(register struct grf_softc *gp, u_long cmd, void *data)
   1027 {
   1028 	switch (cmd) {
   1029 	    case GRFIOCGSPRITEPOS:
   1030 		return (rt_getspritepos (gp, (struct grf_position *) data));
   1031 
   1032 	    case GRFIOCSSPRITEPOS:
   1033 		return (rt_setspritepos (gp, (struct grf_position *) data));
   1034 
   1035 	    case GRFIOCSSPRITEINF:
   1036 		return (rt_setspriteinfo (gp, (struct grf_spriteinfo *) data));
   1037 
   1038 	    case GRFIOCGSPRITEINF:
   1039 		return (rt_getspriteinfo (gp, (struct grf_spriteinfo *) data));
   1040 
   1041 	    case GRFIOCGSPRITEMAX:
   1042 		return (rt_getspritemax (gp, (struct grf_position *) data));
   1043 
   1044 	    case GRFIOCGETCMAP:
   1045 		return (rt_getcmap (gp, (struct grf_colormap *) data));
   1046 
   1047 	    case GRFIOCPUTCMAP:
   1048 		return (rt_putcmap (gp, (struct grf_colormap *) data));
   1049 
   1050 	    case GRFIOCBITBLT:
   1051 		return (rt_bitblt (gp, (struct grf_bitblt *) data));
   1052 
   1053 	    case GRFIOCBLANK:
   1054 		return (rt_blank(gp, (int *)data));
   1055 	}
   1056 
   1057 	return (EPASSTHROUGH);
   1058 }
   1059 
   1060 int
   1061 rt_getcmap(struct grf_softc *gfp, struct grf_colormap *cmap)
   1062 {
   1063 	volatile unsigned char *ba;
   1064 	u_char red[256], green[256], blue[256], *rp, *gp, *bp;
   1065 	short x;
   1066 	int error;
   1067 
   1068 	if (cmap->count == 0 || cmap->index >= 256)
   1069 		return (0);
   1070 
   1071 	if (cmap->count > 256 - cmap->index)
   1072 		cmap->count = 256 - cmap->index;
   1073 
   1074 	ba = gfp->g_regkva;
   1075 	/* first read colors out of the chip, then copyout to userspace */
   1076 	vgaw (ba, VDAC_REG_SELECT, cmap->index);
   1077 	x = cmap->count - 1;
   1078 	rp = red + cmap->index;
   1079 	gp = green + cmap->index;
   1080 	bp = blue + cmap->index;
   1081 	do {
   1082 		*rp++ = vgar (ba, VDAC_REG_DATA);
   1083 		*gp++ = vgar (ba, VDAC_REG_DATA);
   1084 		*bp++ = vgar (ba, VDAC_REG_DATA);
   1085 	}
   1086 	while (x--);
   1087 
   1088 	if (!(error = copyout (red + cmap->index, cmap->red, cmap->count))
   1089 	    && !(error = copyout (green + cmap->index, cmap->green, cmap->count))
   1090 	    && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count)))
   1091 		return (0);
   1092 
   1093 	return (error);
   1094 }
   1095 
   1096 int
   1097 rt_putcmap(struct grf_softc *gfp, struct grf_colormap *cmap)
   1098 {
   1099 	volatile unsigned char *ba;
   1100 	u_char red[256], green[256], blue[256], *rp, *gp, *bp;
   1101 	short x;
   1102 	int error;
   1103 
   1104 	if (cmap->count == 0 || cmap->index >= 256)
   1105 		return 0;
   1106 
   1107 	if (cmap->count > 256 - cmap->index)
   1108 		cmap->count = 256 - cmap->index;
   1109 
   1110 	/* first copy the colors into kernelspace */
   1111 	if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
   1112 	    && !(error = copyin (cmap->green, green + cmap->index, cmap->count))
   1113 	    && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count)))
   1114 	{
   1115 		ba = gfp->g_regkva;
   1116 		vgaw (ba, VDAC_REG_SELECT, cmap->index);
   1117 		x = cmap->count - 1;
   1118 		rp = red + cmap->index;
   1119 		gp = green + cmap->index;
   1120 		bp = blue + cmap->index;
   1121 		do {
   1122 			vgaw (ba, VDAC_REG_DATA, *rp++);
   1123 			vgaw (ba, VDAC_REG_DATA, *gp++);
   1124 			vgaw (ba, VDAC_REG_DATA, *bp++);
   1125 		}
   1126 		while (x--);
   1127 		return (0);
   1128 	} else
   1129 		return (error);
   1130 }
   1131 
   1132 
   1133 int
   1134 rt_getspritepos(struct grf_softc *gp, struct grf_position *pos)
   1135 {
   1136 	volatile unsigned char *ba;
   1137 
   1138 	ba = gp->g_regkva;
   1139 	pos->x = vgar (ba, SEQ_ID_CURSOR_X_LOC_LO) |
   1140 			(vgar (ba, SEQ_ID_CURSOR_X_LOC_HI) << 8);
   1141 	pos->y = vgar (ba, SEQ_ID_CURSOR_Y_LOC_LO) |
   1142 			(vgar (ba, SEQ_ID_CURSOR_Y_LOC_HI) << 8);
   1143 	return (0);
   1144 }
   1145 
   1146 int
   1147 rt_setspritepos(struct grf_softc *gp, struct grf_position *pos)
   1148 {
   1149 	volatile unsigned char *ba;
   1150 
   1151 	ba = gp->g_regkva;
   1152 	vgaw (ba, SEQ_ID_CURSOR_X_LOC_LO, pos->x & 0xff);
   1153 	vgaw (ba, SEQ_ID_CURSOR_X_LOC_HI, (pos->x >> 8) & 0x07);
   1154 	vgaw (ba, SEQ_ID_CURSOR_Y_LOC_LO, pos->y & 0xff);
   1155 	vgaw (ba, SEQ_ID_CURSOR_Y_LOC_HI, (pos->y >> 8) & 0x07);
   1156 	return (0);
   1157 }
   1158 
   1159 /* assume an at least 2M retina (XXX), sprite is last in memory.
   1160  * According to the bogus docs, the cursor can be at most 128 lines
   1161  * in height, and the x-hostspot can be placed at most at pos 31,
   1162  * this gives width of a long
   1163  */
   1164 #define SPRITE_ADDR (2*1024*1024 - 128*4)
   1165 
   1166 int
   1167 rt_getspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *info)
   1168 {
   1169 	volatile void *ba, *fb;
   1170 
   1171 	ba = gp->g_regkva;
   1172 	fb = gp->g_fbkva;
   1173 	if (info->set & GRFSPRSET_ENABLE)
   1174 		info->enable = vgar (ba, SEQ_ID_CURSOR_CONTROL) & 0x01;
   1175 	if (info->set & GRFSPRSET_POS)
   1176 		rt_getspritepos (gp, &info->pos);
   1177 	if (info->set & GRFSPRSET_HOT) {
   1178 		info->hot.x = vgar (ba, SEQ_ID_CURSOR_X_INDEX) & 0x1f;
   1179 		info->hot.y = vgar (ba, SEQ_ID_CURSOR_Y_INDEX) & 0x7f;
   1180 	}
   1181 	if (info->set & GRFSPRSET_CMAP) {
   1182 		struct grf_colormap cmap;
   1183 		int index;
   1184 		cmap.index = 0;
   1185 		cmap.count = 256;
   1186 		rt_getcmap (gp, &cmap);
   1187 		index = vgar (ba, SEQ_ID_CURSOR_COLOR0);
   1188 		info->cmap.red[0] = cmap.red[index];
   1189 		info->cmap.green[0] = cmap.green[index];
   1190 		info->cmap.blue[0] = cmap.blue[index];
   1191 		index = vgar (ba, SEQ_ID_CURSOR_COLOR1);
   1192 		info->cmap.red[1] = cmap.red[index];
   1193 		info->cmap.green[1] = cmap.green[index];
   1194 		info->cmap.blue[1] = cmap.blue[index];
   1195 	}
   1196 	if (info->set & GRFSPRSET_SHAPE) {
   1197 		int saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
   1198 		int saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
   1199 		int last_bank = SPRITE_ADDR >> 6;
   1200 		int last_bank_lo = last_bank & 0xff;
   1201 		int last_bank_hi = last_bank >> 8;
   1202 		u_char mask;
   1203 		WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, last_bank_lo);
   1204 		WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, last_bank_hi);
   1205 		copyout (__UNVOLATILE(fb), info->image, 128*4);
   1206 		mask = RSeq (ba, SEQ_ID_CURSOR_PIXELMASK);
   1207 		WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, saved_bank_lo);
   1208 		WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, saved_bank_hi);
   1209 		copyout (&mask, info->mask, 1);
   1210 		info->size.x = 32; /* ??? */
   1211 		info->size.y = (RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 6) << 4;
   1212 	}
   1213 
   1214 	return (0);
   1215 }
   1216 
   1217 
   1218 int
   1219 rt_setspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *info)
   1220 {
   1221 	volatile void *ba, *fb;
   1222 	u_char control;
   1223 
   1224 	ba = gp->g_regkva;
   1225 	fb = gp->g_fbkva;
   1226 	control = vgar (ba, SEQ_ID_CURSOR_CONTROL);
   1227 	if (info->set & GRFSPRSET_ENABLE) {
   1228 		if (info->enable)
   1229 			control |= 1;
   1230 		else
   1231 			control &= ~1;
   1232 	vgaw (ba, SEQ_ID_CURSOR_CONTROL, control);
   1233 	}
   1234 	if (info->set & GRFSPRSET_POS)
   1235 		rt_setspritepos (gp, &info->pos);
   1236 	if (info->set & GRFSPRSET_HOT) {
   1237 		vgaw (ba, SEQ_ID_CURSOR_X_INDEX, info->hot.x & 0x1f);
   1238 		vgaw (ba, SEQ_ID_CURSOR_Y_INDEX, info->hot.y & 0x7f);
   1239 	}
   1240 	if (info->set & GRFSPRSET_CMAP) {
   1241 		/* hey cheat a bit here.. XXX */
   1242 		vgaw (ba, SEQ_ID_CURSOR_COLOR0, 0);
   1243 		vgaw (ba, SEQ_ID_CURSOR_COLOR1, 1);
   1244 	}
   1245 	if (info->set & GRFSPRSET_SHAPE) {
   1246 		int saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
   1247 		int saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
   1248 		int last_bank = SPRITE_ADDR >> 6;
   1249 		int last_bank_lo = last_bank & 0xff;
   1250 		int last_bank_hi = last_bank >> 8;
   1251 		u_char mask;
   1252 		WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, last_bank_lo);
   1253 		WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, last_bank_hi);
   1254 		copyin (info->image, __UNVOLATILE(fb), 128*4);
   1255 		WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, saved_bank_lo);
   1256 		WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, saved_bank_hi);
   1257 		copyin (info->mask, &mask, 1);
   1258 		WSeq (ba, SEQ_ID_CURSOR_PIXELMASK, mask);
   1259 		/* info->size.x = 32; *//* ??? */
   1260 
   1261 		info->size.y = (RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 6) << 4;
   1262 		control = (control & ~6) | ((info->size.y >> 4) & 6);
   1263 		vgaw (ba, SEQ_ID_CURSOR_CONTROL, control);
   1264 
   1265 		/* sick intel bull-addressing.. */
   1266 		WSeq (ba, SEQ_ID_CURSOR_STORE_LO, SPRITE_ADDR & 0x0f);
   1267 		WSeq (ba, SEQ_ID_CURSOR_STORE_HI, 0);
   1268 		WSeq (ba, SEQ_ID_CURSOR_ST_OFF_LO, (SPRITE_ADDR >> 4) & 0xff);
   1269 		WSeq (ba, SEQ_ID_CURSOR_ST_OFF_HI, ((SPRITE_ADDR >> 4) >> 8) & 0xff);
   1270 	}
   1271 
   1272 	return (0);
   1273 }
   1274 
   1275 
   1276 int
   1277 rt_getspritemax(struct grf_softc *gp, struct grf_position *pos)
   1278 {
   1279 	pos->x = 32;
   1280 	pos->y = 128;
   1281 
   1282 	return (0);
   1283 }
   1284 
   1285 
   1286 /*
   1287  * !!! THIS AREA UNDER CONSTRUCTION !!!
   1288  */
   1289 
   1290 int
   1291 rt_bitblt(struct grf_softc *gp, struct grf_bitblt *bb)
   1292 {
   1293 	return (EINVAL);
   1294 
   1295 #if 0
   1296   volatile void *ba, fb;
   1297   u_char control;
   1298   u_char saved_bank_lo;
   1299   u_char saved_bank_hi;
   1300   u_char src_bank_lo, src_bank_hi;
   1301   u_char dst_bank_lo, dst_bank_hi;
   1302   u_long src_offset, dst_offset;
   1303   u_short src_bank, dst_bank;
   1304   u_char *srcp, *dstp;
   1305   short x, y;
   1306   u_long tot;
   1307 
   1308   ba = gp->g_regkva;
   1309   fb = gp->g_fbkva;
   1310 
   1311   saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
   1312   saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
   1313 
   1314   /* for now, only GRFBBcopy is supported, and only for depth 8. No
   1315      clipping is performed, either... */
   1316 
   1317   if (bb->op != GRFBBcopy && gp->g_display.gd_planes != 8)
   1318     return EINVAL;
   1319 
   1320   src_offset = op->src_x + op->src_y * gp->g_display.gd_fbwidth;
   1321   dst_offset = op->dst_x + op->dst_y * gp->g_display.gd_fbwidth;
   1322   tot = op->w * op->h;
   1323 
   1324   /* set write mode 1, "[...] data in the read latches is written
   1325      to memory during CPU memory write cycles. [...]" */
   1326   WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 1);
   1327   /* write to primary, read from secondary */
   1328   WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, (RSeq(ba, SEQ_ID_EXTENDED_MEM_ENA) & 0x1f) | 0 );
   1329 
   1330   if (src_offset < dst_offset)
   1331     {
   1332       /* start at end */
   1333       src_offset += tot;
   1334       dst_offset += tot;
   1335     }
   1336 
   1337   src_bank_lo = (src_offset >> 6) & 0xff;
   1338   src_bank_hi = (src_offset >> 14) & 0xff;
   1339   dst_bank_lo = (dst_offset >> 6) & 0xff;
   1340   dst_bank_hi = (dst_offset >> 14) & 0xff;
   1341 
   1342   while (tot)
   1343     {
   1344       WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, src_bank_lo);
   1345       WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, src_bank_hi);
   1346       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, dst_bank_lo);
   1347       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, dst_bank_hi);
   1348 
   1349       if (src_offset < dst_offset)
   1350 	{
   1351 
   1352 
   1353 	}
   1354       else
   1355 	{
   1356 
   1357 	}
   1358     }
   1359 
   1360 
   1361 #endif
   1362 }
   1363 
   1364 
   1365 int
   1366 rt_blank(struct grf_softc *gp, int *on)
   1367 {
   1368 	struct MonDef *md = (struct MonDef *)gp->g_data;
   1369 	int r;
   1370 
   1371 	r = 0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8);
   1372 
   1373 	WSeq(gp->g_regkva, SEQ_ID_CLOCKING_MODE, *on > 0 ? r : 0x21);
   1374 
   1375 	return(0);
   1376 }
   1377 
   1378 #endif	/* NGRF */
   1379