Home | History | Annotate | Line # | Download | only in dev
grf_rt.c revision 1.12
      1 /*
      2  *	$Id: grf_rt.c,v 1.12 1994/06/03 00:30:50 chopps Exp $
      3  */
      4 
      5 #include "grf.h"
      6 #if NGRF > 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  = ztwomap(ba);
    714 	gi->gd_regsize  = 64*1024;
    715 
    716 	gi->gd_fbaddr   = ztwomap(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 	if (amiga_realconfig == 0 || rtconunit != cfp->cf_unit) {
    787 		if ((unsigned)retina_default_mon >= retina_mon_max ||
    788 		    monitor_defs[retina_default_mon].DEP == 8)
    789 			retina_default_mon = 0;
    790 
    791 		current_mon = monitor_defs + retina_default_mon;
    792 		if (retina_alive(current_mon) == 0)
    793 			return(0);
    794 		if (amiga_realconfig == 0) {
    795 			rtconunit = cfp->cf_unit;
    796 			cfdata = cfp;
    797 		}
    798 	}
    799 	return(1);
    800 }
    801 
    802 /*
    803  * attach to the grfbus (ztwobus)
    804  */
    805 void
    806 grfrtattach(pdp, dp, auxp)
    807 	struct device *pdp, *dp;
    808 	void *auxp;
    809 {
    810 	static struct grf_softc congrf;
    811 	static int coninited;
    812 	struct ztwobus_args *zap;
    813 	struct grf_softc *gp;
    814 
    815 	zap = auxp;
    816 
    817 	if (dp == NULL)
    818 		gp = &congrf;
    819 	else
    820 		gp = (struct grf_softc *)dp;
    821 
    822 	if (dp != NULL && congrf.g_regkva != 0) {
    823 		/*
    824 		 * we inited earlier just copy the info
    825 		 * take care not to copy the device struct though.
    826 		 */
    827 		bcopy(&congrf.g_display, &gp->g_display,
    828 		    (char *)&gp[1] - (char *)&gp->g_display);
    829 	} else {
    830 		gp->g_regkva = (volatile caddr_t)zap->va;
    831 		gp->g_fbkva = (volatile caddr_t)zap->va + 64 * 1024;
    832 		gp->g_unit = GRF_RETINAII_UNIT;
    833 		gp->g_mode = rt_mode;
    834 		gp->g_conpri = grfrt_cnprobe();
    835 		grfrt_iteinit(gp);
    836 		(void)rt_load_mon(gp, current_mon);
    837 	}
    838 	if (dp != NULL)
    839 		printf("\n");
    840 	/*
    841 	 * attach grf
    842 	 */
    843 	amiga_config_found(cfdata, &gp->g_device, gp, grfrtprint);
    844 }
    845 
    846 int
    847 grfrtprint(auxp, pnp)
    848 	void *auxp;
    849 	char *pnp;
    850 {
    851 	if (pnp)
    852 		printf("grf%d at %s", ((struct grf_softc *)auxp)->g_unit,
    853 			pnp);
    854 	return(UNCONF);
    855 }
    856 
    857 static int
    858 rt_getvmode (gp, vm)
    859      struct grf_softc *gp;
    860      struct grfvideo_mode *vm;
    861 {
    862   struct MonDef *md;
    863 
    864   if (vm->mode_num && vm->mode_num > retina_mon_max)
    865     return EINVAL;
    866 
    867   if (! vm->mode_num)
    868     vm->mode_num = (current_mon - monitor_defs) + 1;
    869 
    870   md = monitor_defs + (vm->mode_num - 1);
    871   strncpy (vm->mode_descr, monitor_descr + (vm->mode_num - 1),
    872 	   sizeof (vm->mode_descr));
    873   vm->pixel_clock  = md->FQ;
    874   vm->disp_width   = md->MW;
    875   vm->disp_height  = md->MH;
    876   vm->depth        = md->DEP;
    877   vm->hblank_start = md->HBS;
    878   vm->hblank_stop  = md->HBE;
    879   vm->hsync_start  = md->HSS;
    880   vm->hsync_stop   = md->HSE;
    881   vm->htotal       = md->HT;
    882   vm->vblank_start = md->VBS;
    883   vm->vblank_stop  = md->VBE;
    884   vm->vsync_start  = md->VSS;
    885   vm->vsync_stop   = md->VSE;
    886   vm->vtotal       = md->VT;
    887 
    888   return 0;
    889 }
    890 
    891 
    892 static int
    893 rt_setvmode (gp, mode, txtonly)
    894      struct grf_softc *gp;
    895      unsigned mode;
    896      int txtonly;
    897 {
    898   struct MonDef *md;
    899   int error;
    900 
    901   if (!mode || mode > retina_mon_max)
    902     return EINVAL;
    903 
    904   if (txtonly && monitor_defs[mode-1].DEP == 8)
    905     return EINVAL;
    906 
    907   current_mon = monitor_defs + (mode - 1);
    908 
    909   error = rt_load_mon (gp, current_mon) ? 0 : EINVAL;
    910 
    911   return error;
    912 }
    913 
    914 
    915 /*
    916  * Change the mode of the display.
    917  * Return a UNIX error number or 0 for success.
    918  */
    919 int
    920 rt_mode(gp, cmd, arg, a2, a3)
    921 	struct grf_softc *gp;
    922 	int cmd;
    923 	void *arg;
    924 	int a2, a3;
    925 {
    926   /* implement these later... */
    927 
    928   switch (cmd)
    929     {
    930     case GM_GRFON:
    931       rt_setvmode (gp, retina_default_gfx + 1, 0);
    932       return 0;
    933 
    934     case GM_GRFOFF:
    935       rt_setvmode (gp, retina_default_mon + 1, 0);
    936       return 0;
    937 
    938     case GM_GRFCONFIG:
    939       return 0;
    940 
    941     case GM_GRFGETVMODE:
    942       return rt_getvmode (gp, (struct grfvideo_mode *) arg);
    943 
    944     case GM_GRFSETVMODE:
    945       return rt_setvmode (gp, *(unsigned *) arg, 1);
    946 
    947     case GM_GRFGETNUMVM:
    948       *(int *)arg = retina_mon_max;
    949       return 0;
    950 
    951 #ifdef BANKEDDEVPAGER
    952     case GM_GRFGETBANK:
    953       *(int *)arg = rt_getbank (gp, a2, a3);
    954       return 0;
    955 
    956     case GM_GRFGETCURBANK:
    957       *(int *)arg = rt_getcurbank (gp);
    958       return 0;
    959 
    960     case GM_GRFSETBANK:
    961       return rt_setbank (gp, arg);
    962 #endif
    963     case GM_GRFIOCTL:
    964       return rt_ioctl (gp, arg, a2);
    965 
    966     default:
    967       break;
    968     }
    969 
    970   return EINVAL;
    971 }
    972 
    973 int
    974 rt_ioctl (gp, cmd, data)
    975 	register struct grf_softc *gp;
    976 	int cmd;
    977 	void *data;
    978 {
    979   switch (cmd)
    980     {
    981     case GRFIOCGSPRITEPOS:
    982       return rt_getspritepos (gp, (struct grf_position *) data);
    983 
    984     case GRFIOCSSPRITEPOS:
    985       return rt_setspritepos (gp, (struct grf_position *) data);
    986 
    987     case GRFIOCSSPRITEINF:
    988       return rt_setspriteinfo (gp, (struct grf_spriteinfo *) data);
    989 
    990     case GRFIOCGSPRITEINF:
    991       return rt_getspriteinfo (gp, (struct grf_spriteinfo *) data);
    992 
    993     case GRFIOCGSPRITEMAX:
    994       return rt_getspritemax (gp, (struct grf_position *) data);
    995 
    996     case GRFIOCGETCMAP:
    997       return rt_getcmap (gp, (struct grf_colormap *) data);
    998 
    999     case GRFIOCPUTCMAP:
   1000       return rt_putcmap (gp, (struct grf_colormap *) data);
   1001 
   1002     case GRFIOCBITBLT:
   1003       return rt_bitblt (gp, (struct grf_bitblt *) data);
   1004     }
   1005 
   1006   return EINVAL;
   1007 }
   1008 
   1009 #ifdef BANKEDDEVPAGER
   1010 
   1011 /* Retina banks can overlap. Don't use this information (yet?), and
   1012    only switch 64k sized banks. */
   1013 
   1014 int
   1015 rt_getbank (gp, offs, prot)
   1016      struct grf_softc *gp;
   1017      off_t offs;
   1018      int prot;
   1019 {
   1020   /* XXX */
   1021   if (offs <  0 || offs >= 4*1024*1024)
   1022     return -1;
   1023   else
   1024     return offs >> 16;
   1025 }
   1026 
   1027 int
   1028 rt_getcurbank (gp)
   1029      struct grf_softc *gp;
   1030 {
   1031   struct grfinfo *gi = &gp->g_display;
   1032   volatile unsigned char *ba;
   1033   int bank;
   1034 
   1035   ba = gp->g_regkva;
   1036   bank = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO) | (RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI) << 8);
   1037 
   1038   /* bank register is multiple of 64 byte, make this multiple of 64k */
   1039   bank >>= 10;
   1040   return bank;
   1041 }
   1042 
   1043 int
   1044 rt_setbank (gp, bank)
   1045      struct grf_softc *gp;
   1046      int bank;
   1047 {
   1048   volatile unsigned char *ba;
   1049 
   1050   ba = gp->g_regkva;
   1051   /* bank register is multiple of 64 byte, make this multiple of 64k */
   1052   bank <<= 10;
   1053   WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, (unsigned char) bank);
   1054   bank >>= 8;
   1055   WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, (unsigned char) bank);
   1056 
   1057   return 0;
   1058 }
   1059 
   1060 #endif
   1061 
   1062 int
   1063 rt_getcmap (gfp, cmap)
   1064      struct grf_softc *gfp;
   1065      struct grf_colormap *cmap;
   1066 {
   1067   volatile unsigned char *ba;
   1068   u_char red[256], green[256], blue[256], *rp, *gp, *bp;
   1069   short x;
   1070   int error;
   1071 
   1072   if (cmap->count == 0 || cmap->index >= 256)
   1073     return 0;
   1074 
   1075   if (cmap->index + cmap->count > 256)
   1076     cmap->count = 256 - cmap->index;
   1077 
   1078   ba = gfp->g_regkva;
   1079   /* first read colors out of the chip, then copyout to userspace */
   1080   vgaw (ba, VDAC_REG_SELECT, cmap->index);
   1081   x = cmap->count - 1;
   1082   rp = red + cmap->index;
   1083   gp = green + cmap->index;
   1084   bp = blue + cmap->index;
   1085   do
   1086     {
   1087       *rp++ = vgar (ba, VDAC_REG_DATA);
   1088       *gp++ = vgar (ba, VDAC_REG_DATA);
   1089       *bp++ = vgar (ba, VDAC_REG_DATA);
   1090     }
   1091   while (x--);
   1092 
   1093   if (!(error = copyout (red + cmap->index, cmap->red, cmap->count))
   1094       && !(error = copyout (green + cmap->index, cmap->green, cmap->count))
   1095       && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count)))
   1096     return 0;
   1097 
   1098   return error;
   1099 }
   1100 
   1101 int
   1102 rt_putcmap (gfp, cmap)
   1103      struct grf_softc *gfp;
   1104      struct grf_colormap *cmap;
   1105 {
   1106   volatile unsigned char *ba;
   1107   u_char red[256], green[256], blue[256], *rp, *gp, *bp;
   1108   short x;
   1109   int error;
   1110 
   1111   if (cmap->count == 0 || cmap->index >= 256)
   1112     return 0;
   1113 
   1114   if (cmap->index + cmap->count > 256)
   1115     cmap->count = 256 - cmap->index;
   1116 
   1117   /* first copy the colors into kernelspace */
   1118   if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
   1119       && !(error = copyin (cmap->green, green + cmap->index, cmap->count))
   1120       && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count)))
   1121     {
   1122       ba = gfp->g_regkva;
   1123       vgaw (ba, VDAC_REG_SELECT, cmap->index);
   1124       x = cmap->count - 1;
   1125       rp = red + cmap->index;
   1126       gp = green + cmap->index;
   1127       bp = blue + cmap->index;
   1128       do
   1129 	{
   1130 	  vgaw (ba, VDAC_REG_DATA, *rp++);
   1131 	  vgaw (ba, VDAC_REG_DATA, *gp++);
   1132 	  vgaw (ba, VDAC_REG_DATA, *bp++);
   1133 	}
   1134       while (x--);
   1135       return 0;
   1136     }
   1137   else
   1138     return error;
   1139 }
   1140 
   1141 int
   1142 rt_getspritepos (gp, pos)
   1143      struct grf_softc *gp;
   1144      struct grf_position *pos;
   1145 {
   1146   volatile unsigned char *ba;
   1147 
   1148   ba = gp->g_regkva;
   1149   pos->x = vgar (ba, SEQ_ID_CURSOR_X_LOC_LO) | (vgar (ba, SEQ_ID_CURSOR_X_LOC_HI) << 8);
   1150   pos->y = vgar (ba, SEQ_ID_CURSOR_Y_LOC_LO) | (vgar (ba, SEQ_ID_CURSOR_Y_LOC_HI) << 8);
   1151   return 0;
   1152 }
   1153 
   1154 int
   1155 rt_setspritepos (gp, pos)
   1156      struct grf_softc *gp;
   1157      struct grf_position *pos;
   1158 {
   1159   volatile unsigned char *ba;
   1160 
   1161   ba = gp->g_regkva;
   1162   vgaw (ba, SEQ_ID_CURSOR_X_LOC_LO, pos->x & 0xff);
   1163   vgaw (ba, SEQ_ID_CURSOR_X_LOC_HI, (pos->x >> 8) & 0x07);
   1164   vgaw (ba, SEQ_ID_CURSOR_Y_LOC_LO, pos->y & 0xff);
   1165   vgaw (ba, SEQ_ID_CURSOR_Y_LOC_HI, (pos->y >> 8) & 0x07);
   1166   return 0;
   1167 }
   1168 
   1169 /* assume an at least 2M retina (XXX), sprite is last in memory.
   1170    According to the bogus docs, the cursor can be at most 128 lines
   1171    in height, and the x-hostspot can be placed at most at pos 31,
   1172    this gives width of a long */
   1173 #define SPRITE_ADDR (2*1024*1024 - 128*4)
   1174 
   1175 int
   1176 rt_getspriteinfo (gp, info)
   1177      struct grf_softc *gp;
   1178      struct grf_spriteinfo *info;
   1179 {
   1180   volatile unsigned char *ba, *fb;
   1181 
   1182   ba = gp->g_regkva;
   1183   fb = gp->g_fbkva;
   1184   if (info->set & GRFSPRSET_ENABLE)
   1185     info->enable = vgar (ba, SEQ_ID_CURSOR_CONTROL) & 0x01;
   1186   if (info->set & GRFSPRSET_POS)
   1187     rt_getspritepos (gp, &info->pos);
   1188   if (info->set & GRFSPRSET_HOT)
   1189     {
   1190       info->hot.x = vgar (ba, SEQ_ID_CURSOR_X_INDEX) & 0x1f;
   1191       info->hot.y = vgar (ba, SEQ_ID_CURSOR_Y_INDEX) & 0x7f;
   1192     }
   1193   if (info->set & GRFSPRSET_CMAP)
   1194     {
   1195       struct grf_colormap cmap;
   1196       int index;
   1197       cmap.index = 0;
   1198       cmap.count = 256;
   1199       rt_getcmap (gp, &cmap);
   1200       index = vgar (ba, SEQ_ID_CURSOR_COLOR0);
   1201       info->cmap.red[0] = cmap.red[index];
   1202       info->cmap.green[0] = cmap.green[index];
   1203       info->cmap.blue[0] = cmap.blue[index];
   1204       index = vgar (ba, SEQ_ID_CURSOR_COLOR1);
   1205       info->cmap.red[1] = cmap.red[index];
   1206       info->cmap.green[1] = cmap.green[index];
   1207       info->cmap.blue[1] = cmap.blue[index];
   1208     }
   1209   if (info->set & GRFSPRSET_SHAPE)
   1210     {
   1211       int saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
   1212       int saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
   1213       int last_bank = SPRITE_ADDR >> 6;
   1214       int last_bank_lo = last_bank & 0xff;
   1215       int last_bank_hi = last_bank >> 8;
   1216       u_char mask;
   1217       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, last_bank_lo);
   1218       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, last_bank_hi);
   1219       copyout (fb, info->image, 128*4);
   1220       mask = RSeq (ba, SEQ_ID_CURSOR_PIXELMASK);
   1221       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, saved_bank_lo);
   1222       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, saved_bank_hi);
   1223       copyout (&mask, info->mask, 1);
   1224       info->size.x = 32; /* ??? */
   1225       info->size.y = (RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 6) << 4;
   1226     }
   1227 
   1228 }
   1229 
   1230 int
   1231 rt_setspriteinfo (gp, info)
   1232      struct grf_softc *gp;
   1233      struct grf_spriteinfo *info;
   1234 {
   1235   volatile unsigned char *ba, *fb;
   1236   u_char control;
   1237 
   1238   ba = gp->g_regkva;
   1239   fb = gp->g_fbkva;
   1240   control = vgar (ba, SEQ_ID_CURSOR_CONTROL);
   1241   if (info->set & GRFSPRSET_ENABLE)
   1242     {
   1243       if (info->enable)
   1244 	control |= 1;
   1245       else
   1246 	control &= ~1;
   1247       vgaw (ba, SEQ_ID_CURSOR_CONTROL, control);
   1248     }
   1249   if (info->set & GRFSPRSET_POS)
   1250     rt_setspritepos (gp, &info->pos);
   1251   if (info->set & GRFSPRSET_HOT)
   1252     {
   1253       vgaw (ba, SEQ_ID_CURSOR_X_INDEX, info->hot.x & 0x1f);
   1254       vgaw (ba, SEQ_ID_CURSOR_Y_INDEX, info->hot.y & 0x7f);
   1255     }
   1256   if (info->set & GRFSPRSET_CMAP)
   1257     {
   1258       /* hey cheat a bit here.. XXX */
   1259       vgaw (ba, SEQ_ID_CURSOR_COLOR0, 0);
   1260       vgaw (ba, SEQ_ID_CURSOR_COLOR1, 1);
   1261     }
   1262   if (info->set & GRFSPRSET_SHAPE)
   1263     {
   1264       int saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
   1265       int saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
   1266       int last_bank = SPRITE_ADDR >> 6;
   1267       int last_bank_lo = last_bank & 0xff;
   1268       int last_bank_hi = last_bank >> 8;
   1269       u_char mask;
   1270       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, last_bank_lo);
   1271       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, last_bank_hi);
   1272       copyin (info->image, fb, 128*4);
   1273       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, saved_bank_lo);
   1274       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, saved_bank_hi);
   1275       copyin (info->mask, &mask, 1);
   1276       WSeq (ba, SEQ_ID_CURSOR_PIXELMASK, mask);
   1277       /* info->size.x = 32; *//* ??? */
   1278 
   1279       info->size.y = (RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 6) << 4;
   1280       control = (control & ~6) | ((info->size.y >> 4) & 6);
   1281       vgaw (ba, SEQ_ID_CURSOR_CONTROL, control);
   1282 
   1283       /* sick intel bull-addressing.. */
   1284       WSeq (ba, SEQ_ID_CURSOR_STORE_LO, SPRITE_ADDR & 0x0f);
   1285       WSeq (ba, SEQ_ID_CURSOR_STORE_HI, 0);
   1286       WSeq (ba, SEQ_ID_CURSOR_ST_OFF_LO, (SPRITE_ADDR >> 4) & 0xff);
   1287       WSeq (ba, SEQ_ID_CURSOR_ST_OFF_HI, ((SPRITE_ADDR >> 4) >> 8) & 0xff);
   1288     }
   1289 
   1290   return 0;
   1291 }
   1292 
   1293 int
   1294 rt_getspritemax (gp, pos)
   1295      struct grf_softc *gp;
   1296      struct grf_position *pos;
   1297 {
   1298   pos->x = 32;
   1299   pos->y = 128;
   1300 
   1301   return 0;
   1302 }
   1303 
   1304 
   1305 /*
   1306  * !!! THIS AREA UNDER CONSTRUCTION !!!
   1307  */
   1308 
   1309 int
   1310 rt_bitblt (gp, bb)
   1311      struct grf_softc *gp;
   1312      struct grf_bitblt *bb;
   1313 {
   1314   return EINVAL;
   1315 
   1316 
   1317 #if 0
   1318   volatile unsigned char *ba, *fb;
   1319   u_char control;
   1320   u_char saved_bank_lo;
   1321   u_char saved_bank_hi;
   1322   u_char src_bank_lo, src_bank_hi;
   1323   u_char dst_bank_lo, dst_bank_hi;
   1324   u_long src_offset, dst_offset;
   1325   u_short src_bank, dst_bank;
   1326   u_char *srcp, *dstp;
   1327   short x, y;
   1328   u_long tot;
   1329 
   1330   ba = gp->g_regkva;
   1331   fb = gp->g_fbkva;
   1332 
   1333   saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
   1334   saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
   1335 
   1336   /* for now, only GRFBBcopy is supported, and only for depth 8. No
   1337      clipping is performed, either... */
   1338 
   1339   if (bb->op != GRFBBcopy && gp->g_display.gd_planes != 8)
   1340     return EINVAL;
   1341 
   1342   src_offset = op->src_x + op->src_y * gp->g_display.gd_fbwidth;
   1343   dst_offset = op->dst_x + op->dst_y * gp->g_display.gd_fbwidth;
   1344   tot = op->w * op->h;
   1345 
   1346   /* set write mode 1, "[...] data in the read latches is written
   1347      to memory during CPU memory write cycles. [...]" */
   1348   WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 1);
   1349   /* write to primary, read from secondary */
   1350   WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, (RSeq(ba, SEQ_ID_EXTENDED_MEM_ENA) & 0x1f) | 0 );
   1351 
   1352   if (src_offset < dst_offset)
   1353     {
   1354       /* start at end */
   1355       src_offset += tot;
   1356       dst_offset += tot;
   1357     }
   1358 
   1359   src_bank_lo = (src_offset >> 6) & 0xff;
   1360   src_bank_hi = (src_offset >> 14) & 0xff;
   1361   dst_bank_lo = (dst_offset >> 6) & 0xff;
   1362   dst_bank_hi = (dst_offset >> 14) & 0xff;
   1363 
   1364   while (tot)
   1365     {
   1366       WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, src_bank_lo);
   1367       WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, src_bank_hi);
   1368       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, dst_bank_lo);
   1369       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, dst_bank_hi);
   1370 
   1371       if (src_offset < dst_offset)
   1372 	{
   1373 
   1374 
   1375 	}
   1376       else
   1377 	{
   1378 
   1379 	}
   1380     }
   1381 
   1382 
   1383 #endif
   1384 }
   1385 
   1386 
   1387 #endif	/* NGRF */
   1388