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