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