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