Home | History | Annotate | Line # | Download | only in dev
grf_rt.c revision 1.10
      1 /*
      2  *	$Id: grf_rt.c,v 1.10 1994/04/26 03:48:08 chopps Exp $
      3  */
      4 
      5 #include "grf.h"
      6 #if NGRF > 0
      7 
      8 /* Graphics routines for the Retina board,
      9    using the NCR 77C22E+ VGA controller. */
     10 
     11 #include <sys/param.h>
     12 #include <sys/errno.h>
     13 #include <sys/ioctl.h>
     14 #include <amiga/dev/grfioctl.h>
     15 #include <amiga/dev/grfvar.h>
     16 #include <amiga/dev/grf_rtreg.h>
     17 #include <machine/cpu.h>
     18 #include <amiga/dev/device.h>
     19 
     20 extern caddr_t ZORRO2ADDR;
     21 
     22 /* marked true early so that retina_cnprobe() can tell if we are alive. */
     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 = 2;
    211 int retina_default_gfx = 5;
    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 static int rt_load_mon (struct grf_softc *gp, struct MonDef *md)
    237 {
    238 	struct grfinfo *gi = &gp->g_display;
    239 	volatile unsigned char *ba;
    240 	volatile unsigned char *fb;
    241 	short FW, clksel, HDE, VDE;
    242 
    243 	for (clksel = 15; clksel; clksel--) {
    244 		if (FQTab[clksel] == md->FQ) break;
    245 	}
    246 	if (clksel < 0) return 0;
    247 
    248 	ba = gp->g_regkva;;
    249 	fb = gp->g_fbkva;
    250 
    251 	FW = 0;
    252 	if (md->DEP == 4) {
    253 		switch (md->FX) {
    254 		case 4:
    255 			FW = 0;
    256 			break;
    257 		case 7:
    258 			FW = 1;
    259 			break;
    260 		case 8:
    261 			FW = 2;
    262 			break;
    263 		case 9:
    264 			FW = 3;
    265 			break;
    266 		case 10:
    267 			FW = 4;
    268 			break;
    269 		case 11:
    270 			FW = 5;
    271 			break;
    272 		case 12:
    273 			FW = 6;
    274 			break;
    275 		case 13:
    276 			FW = 7;
    277 			break;
    278 		case 14:
    279 			FW = 8;
    280 			break;
    281 		case 15:
    282 			FW = 9;
    283 			break;
    284 		case 16:
    285 			FW = 11;
    286 			break;
    287 		default:
    288 			return 0;
    289 			break;
    290 		};
    291 	}
    292 
    293         if (md->DEP == 4) HDE = (md->MW+md->FX-1)/md->FX;
    294         else              HDE = (md->MW+3)/4;
    295 	VDE = md->MH-1;
    296 
    297 	/* hmm... */
    298 	fb[0x8000] = 0;
    299 
    300 		/* enable extension registers */
    301 	WSeq (ba, SEQ_ID_EXTENDED_ENABLE,	0x05);
    302 
    303 #if 0
    304 	/* program the clock oscillator */
    305 	vgaw (ba, GREG_MISC_OUTPUT_W, 0xe3 | ((clksel & 3) * 0x04));
    306 	vgaw (ba, GREG_FEATURE_CONTROL_W, 0x00);
    307 
    308 	/* XXXX according to the NCR specs, this register should be set to 1
    309 	   XXXX before doing the MISC_OUTPUT setting and CLOCKING_MODE
    310 	   XXXX setting. */
    311 	WSeq (ba, SEQ_ID_RESET, 		0x03);
    312 
    313 	WSeq (ba, SEQ_ID_CLOCKING_MODE, 	0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8));
    314 	WSeq (ba, SEQ_ID_MAP_MASK, 		0x0f);
    315 	WSeq (ba, SEQ_ID_CHAR_MAP_SELECT, 	0x00);
    316 		/* odd/even write select + extended memory */
    317 	WSeq (ba, SEQ_ID_MEMORY_MODE, 	0x06);
    318 	/* XXXX I think this order of setting RESET is wrong... */
    319 	WSeq (ba, SEQ_ID_RESET, 		0x01);
    320 	WSeq (ba, SEQ_ID_RESET, 		0x03);
    321 #else
    322 	WSeq (ba, SEQ_ID_RESET, 		0x01);
    323 
    324 		/* set font width + rest of clocks */
    325 	WSeq (ba, SEQ_ID_EXT_CLOCK_MODE,	0x30 | (FW & 0x0f) | ((clksel & 4) / 4 * 0x40) );
    326 		/* another clock bit, plus hw stuff */
    327 	WSeq (ba, SEQ_ID_MISC_FEATURE_SEL,	0xf4 | (clksel & 8) );
    328 
    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 	WSeq (ba, SEQ_ID_CLOCKING_MODE, 	0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8));
    334 	WSeq (ba, SEQ_ID_MAP_MASK, 		0x0f);
    335 	WSeq (ba, SEQ_ID_CHAR_MAP_SELECT, 	0x00);
    336 		/* odd/even write select + extended memory */
    337 	WSeq (ba, SEQ_ID_MEMORY_MODE, 		0x06);
    338 	WSeq (ba, SEQ_ID_RESET, 		0x03);
    339 #endif
    340 
    341 		/* monochrome cursor */
    342 	WSeq (ba, SEQ_ID_CURSOR_CONTROL,	0x00);
    343 		/* bank0 */
    344 	WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI,	0x00);
    345 	WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO,	0x00);
    346 	WSeq (ba, SEQ_ID_DISP_OFF_HI , 		0x00);
    347 	WSeq (ba, SEQ_ID_DISP_OFF_LO , 		0x00);
    348 		/* bank0 */
    349 	WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI,	0x00);
    350 	WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO,	0x00);
    351 		/* 1M-chips + ena SEC + ena EMem + rw PrimA0/rw Sec/B0 */
    352 	WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA,	0x3 | 0x4 | 0x10 | 0x40);
    353 #if 0
    354 		/* set font width + rest of clocks */
    355 	WSeq (ba, SEQ_ID_EXT_CLOCK_MODE,	0x30 | (FW & 0x0f) | ((clksel & 4) / 4 * 0x40) );
    356 #endif
    357 	if (md->DEP == 4) {
    358 			/* no ext-chain4 + no host-addr-bit-16 */
    359 		WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR,	0x00);
    360 			/* no packed/nibble + no 256bit gfx format */
    361 		WSeq (ba, SEQ_ID_EXT_PIXEL_CNTL,	0x00);
    362 	}
    363 	else {
    364 		WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR,	0x02);
    365 			/* 256bit gfx format */
    366 		WSeq (ba, SEQ_ID_EXT_PIXEL_CNTL,	0x01);
    367 	}
    368 		/* AT-interface */
    369 	WSeq (ba, SEQ_ID_BUS_WIDTH_FEEDB,	0x06);
    370 		/* see fg/bg color expansion */
    371 	WSeq (ba, SEQ_ID_COLOR_EXP_WFG,		0x01);
    372 	WSeq (ba, SEQ_ID_COLOR_EXP_WBG,		0x00);
    373 	WSeq (ba, SEQ_ID_EXT_RW_CONTROL,	0x00);
    374 #if 0
    375 		/* another clock bit, plus hw stuff */
    376 	WSeq (ba, SEQ_ID_MISC_FEATURE_SEL,	0xf4 | (clksel & 8) );
    377 #endif
    378 		/* don't tristate PCLK and PIX */
    379 	WSeq (ba, SEQ_ID_COLOR_KEY_CNTL,	0x40 );
    380 		/* reset CRC circuit */
    381 	WSeq (ba, SEQ_ID_CRC_CONTROL,		0x00 );
    382 		/* set RAS/CAS swap */
    383 	WSeq (ba, SEQ_ID_PERF_SELECT,		0x20);
    384 
    385 	WCrt (ba, CRT_ID_END_VER_RETR,		(md->VSE & 0xf ) | 0x20);
    386 	WCrt (ba, CRT_ID_HOR_TOTAL,		md->HT   & 0xff);
    387 	WCrt (ba, CRT_ID_HOR_DISP_ENA_END,	(HDE-1)  & 0xff);
    388 	WCrt (ba, CRT_ID_START_HOR_BLANK,	md->HBS  & 0xff);
    389 	WCrt (ba, CRT_ID_END_HOR_BLANK,		(md->HBE & 0x1f) | 0x80);
    390 
    391 	WCrt (ba, CRT_ID_START_HOR_RETR,	md->HSS  & 0xff);
    392 	WCrt (ba, CRT_ID_END_HOR_RETR,		(md->HSE & 0x1f) | ((md->HBE & 0x20)/ 0x20 * 0x80));
    393 	WCrt (ba, CRT_ID_VER_TOTAL,		(md->VT  & 0xff));
    394 	WCrt (ba, CRT_ID_OVERFLOW,		(( (md->VSS  & 0x200) / 0x200 * 0x80)
    395 						 | ((VDE     & 0x200) / 0x200 * 0x40)
    396 						 | ((md->VT  & 0x200) / 0x200 * 0x20)
    397 						 | 				0x10
    398 						 | ((md->VBS & 0x100) / 0x100 * 8   )
    399 						 | ((md->VSS & 0x100) / 0x100 * 4   )
    400 						 | ((VDE     & 0x100) / 0x100 * 2   )
    401 						 | ((md->VT  & 0x100) / 0x100       )));
    402 	WCrt (ba, CRT_ID_PRESET_ROW_SCAN,	0x00);
    403 
    404 	if (md->DEP == 4) {
    405 		WCrt (ba, CRT_ID_MAX_SCAN_LINE, 	((  (md->FLG & MDF_DBL)/ MDF_DBL * 0x80)
    406 							 | 				   0x40
    407 							 | ((md->VBS & 0x200)/0x200	 * 0x20)
    408 							 | ((md->FY-1) 			 & 0x1f)));
    409 	}
    410 	else {
    411 		WCrt (ba, CRT_ID_MAX_SCAN_LINE, 	((  (md->FLG & MDF_DBL)/ MDF_DBL * 0x80)
    412 							 | 				   0x40
    413 							 | ((md->VBS & 0x200)/0x200	 * 0x20)
    414 							 | (0	 			 & 0x1f)));
    415 	}
    416 
    417 	WCrt (ba, CRT_ID_CURSOR_START,		(md->FY & 0x1f) - 2);
    418 	WCrt (ba, CRT_ID_CURSOR_END,		(md->FY & 0x1f) - 1);
    419 
    420 	WCrt (ba, CRT_ID_START_ADDR_HIGH,	0x00);
    421 	WCrt (ba, CRT_ID_START_ADDR_LOW,	0x00);
    422 
    423 	WCrt (ba, CRT_ID_CURSOR_LOC_HIGH,	0x00);
    424 	WCrt (ba, CRT_ID_CURSOR_LOC_LOW,	0x00);
    425 
    426 	WCrt (ba, CRT_ID_START_VER_RETR,	md->VSS    & 0xff);
    427 	WCrt (ba, CRT_ID_END_VER_RETR,		(md->VSE   & 0x0f) | 0x80 | 0x20);
    428 	WCrt (ba, CRT_ID_VER_DISP_ENA_END,	VDE        & 0xff);
    429 	if (md->DEP == 4)
    430 		WCrt (ba, CRT_ID_OFFSET,	(HDE / 2)  & 0xff);
    431 	else
    432 		WCrt (ba, CRT_ID_OFFSET,	(md->TX / 8)  & 0xff);
    433 
    434 	WCrt (ba, CRT_ID_UNDERLINE_LOC,		(md->FY-1) & 0x1f);
    435 	WCrt (ba, CRT_ID_START_VER_BLANK,	md->VBS    & 0xff);
    436 	WCrt (ba, CRT_ID_END_VER_BLANK,		md->VBE    & 0xff);
    437 		/* byte mode + wrap + select row scan counter + cms */
    438 	WCrt (ba, CRT_ID_MODE_CONTROL,		0xe3);
    439 	WCrt (ba, CRT_ID_LINE_COMPARE,		0xff);
    440 
    441 		/* enable extended end bits + those bits */
    442 	WCrt (ba, CRT_ID_EXT_HOR_TIMING1,	(           				 0x20
    443 						 | ((md->FLG & MDF_LACE)  / MDF_LACE   * 0x10)
    444 						 | ((md->HT  & 0x100) / 0x100          * 0x01)
    445 						 | (((HDE-1) & 0x100) / 0x100 	       * 0x02)
    446 						 | ((md->HBS & 0x100) / 0x100 	       * 0x04)
    447 						 | ((md->HSS & 0x100) / 0x100 	       * 0x08)));
    448 
    449 	if (md->DEP == 4)
    450 		WCrt (ba, CRT_ID_EXT_START_ADDR,	(((HDE / 2) & 0x100)/0x100 * 16));
    451 	else
    452 		WCrt (ba, CRT_ID_EXT_START_ADDR,	(((md->TX / 8) & 0x100)/0x100 * 16));
    453 
    454 	WCrt (ba, CRT_ID_EXT_HOR_TIMING2, 	(  ((md->HT  & 0x200)/ 0x200  	       * 0x01)
    455 						 | (((HDE-1) & 0x200)/ 0x200 	       * 0x02)
    456 						 | ((md->HBS & 0x200)/ 0x200 	       * 0x04)
    457 						 | ((md->HSS & 0x200)/ 0x200 	       * 0x08)
    458 						 | ((md->HBE & 0xc0) / 0x40  	       * 0x10)
    459 						 | ((md->HSE & 0x60) / 0x20  	       * 0x40)));
    460 
    461 	WCrt (ba, CRT_ID_EXT_VER_TIMING,	(  ((md->VSE & 0x10) / 0x10  	       * 0x80)
    462 						 | ((md->VBE & 0x300)/ 0x100 	       * 0x20)
    463 						 |				         0x10
    464 						 | ((md->VSS & 0x400)/ 0x400 	       * 0x08)
    465 						 | ((md->VBS & 0x400)/ 0x400 	       * 0x04)
    466 						 | ((VDE     & 0x400)/ 0x400 	       * 0x02)
    467 						 | ((md->VT  & 0x400)/ 0x400           * 0x01)));
    468 
    469 	WGfx (ba, GCT_ID_SET_RESET,		0x00);
    470 	WGfx (ba, GCT_ID_ENABLE_SET_RESET,	0x00);
    471 	WGfx (ba, GCT_ID_COLOR_COMPARE,		0x00);
    472 	WGfx (ba, GCT_ID_DATA_ROTATE,		0x00);
    473 	WGfx (ba, GCT_ID_READ_MAP_SELECT,	0x00);
    474 	WGfx (ba, GCT_ID_GRAPHICS_MODE,		0x00);
    475 	if (md->DEP == 4)
    476 		WGfx (ba, GCT_ID_MISC,			0x04);
    477 	else
    478 		WGfx (ba, GCT_ID_MISC,			0x05);
    479 	WGfx (ba, GCT_ID_COLOR_XCARE,		0xff);
    480 	WGfx (ba, GCT_ID_BITMASK,		0xff);
    481 
    482 	/* reset the Attribute Controller flipflop */
    483 	vgar (ba, GREG_STATUS1_R);
    484 	WAttr (ba, ACT_ID_PALETTE0,		0x00);
    485 	WAttr (ba, ACT_ID_PALETTE1,		0x01);
    486 	WAttr (ba, ACT_ID_PALETTE2,		0x02);
    487 	WAttr (ba, ACT_ID_PALETTE3,		0x03);
    488 	WAttr (ba, ACT_ID_PALETTE4,		0x04);
    489 	WAttr (ba, ACT_ID_PALETTE5,		0x05);
    490 	WAttr (ba, ACT_ID_PALETTE6,		0x06);
    491 	WAttr (ba, ACT_ID_PALETTE7,		0x07);
    492 	WAttr (ba, ACT_ID_PALETTE8,		0x08);
    493 	WAttr (ba, ACT_ID_PALETTE9,		0x09);
    494 	WAttr (ba, ACT_ID_PALETTE10,		0x0a);
    495 	WAttr (ba, ACT_ID_PALETTE11,		0x0b);
    496 	WAttr (ba, ACT_ID_PALETTE12,		0x0c);
    497 	WAttr (ba, ACT_ID_PALETTE13,		0x0d);
    498 	WAttr (ba, ACT_ID_PALETTE14,		0x0e);
    499 	WAttr (ba, ACT_ID_PALETTE15,		0x0f);
    500 
    501 	vgar (ba, GREG_STATUS1_R);
    502 	if (md->DEP == 4)
    503 		WAttr (ba, ACT_ID_ATTR_MODE_CNTL,	0x08);
    504 	else
    505 		WAttr (ba, ACT_ID_ATTR_MODE_CNTL,	0x09);
    506 
    507 	WAttr (ba, ACT_ID_OVERSCAN_COLOR,	0x00);
    508 	WAttr (ba, ACT_ID_COLOR_PLANE_ENA,	0x0f);
    509 	WAttr (ba, ACT_ID_HOR_PEL_PANNING,	0x00);
    510 	WAttr (ba, ACT_ID_COLOR_SELECT,	0x00);
    511 
    512 	vgar (ba, GREG_STATUS1_R);
    513 		/* I have *NO* idea what strobing reg-0x20 might do... */
    514 	vgaw (ba, ACT_ADDRESS_W, 0x20);
    515 
    516 	if (md->DEP == 4)
    517 		WCrt (ba, CRT_ID_MAX_SCAN_LINE,	( ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80)
    518 						|	                          0x40
    519 						| ((md->VBS & 0x200)/0x200	* 0x20)
    520 						| ((md->FY-1) 			& 0x1f)));
    521 	else
    522 		WCrt (ba, CRT_ID_MAX_SCAN_LINE,	( ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80)
    523 						|	                          0x40
    524 						| ((md->VBS & 0x200)/0x200	* 0x20)
    525 						| (0	 			& 0x1f)));
    526 
    527 
    528 	/* not it's time for guessing... */
    529 
    530 	vgaw (ba, VDAC_REG_D, 	   0x02);
    531 
    532 		/* if this does what I think it does, it selects DAC
    533 		   register 0, and writes the palette in subsequent
    534 		   registers, thus it works similar to the WD33C93
    535 		   select/data mechanism */
    536 	vgaw (ba, VDAC_REG_SELECT, 0x00);
    537 
    538 	{
    539 
    540 		short x = 15;
    541 		const unsigned char * col = md->PAL;
    542 		do {
    543 
    544 			vgaw (ba, VDAC_REG_DATA, *col++);
    545 			vgaw (ba, VDAC_REG_DATA, *col++);
    546 			vgaw (ba, VDAC_REG_DATA, *col++);
    547 
    548 
    549 		} while (x--);
    550 
    551 		if (md->DEP != 4) {
    552 			short x = 256-17;
    553 			unsigned char col = 16;
    554 			do {
    555 
    556 				vgaw(ba, VDAC_REG_DATA, col);
    557 				vgaw(ba, VDAC_REG_DATA, col);
    558 				vgaw(ba, VDAC_REG_DATA, col);
    559 				col++;
    560 
    561 			} while (x--);
    562 		}
    563 	}
    564 
    565 
    566 	/* now load the font into maps 2 (and 3 for fonts wider than 8 pixels) */
    567 	if (md->DEP == 4) {
    568 
    569 		/* first set the whole font memory to a test-pattern, so we
    570 		   can see if something that shouldn't be drawn IS drawn.. */
    571 		{
    572 			volatile unsigned char * c = fb;
    573 			long x;
    574 			Map(2);
    575 
    576 			for (x = 0; x < 65536; x++) {
    577 				*c++ = (x & 1)? 0xaa : 0x55;
    578 			}
    579 		}
    580 
    581 		{
    582 			volatile unsigned char * c = fb;
    583 			long x;
    584 			Map(3);
    585 
    586 			for (x = 0; x < 65536; x++) {
    587 				*c++ = (x & 1)? 0xaa : 0x55;
    588 			}
    589 		}
    590 
    591 		{
    592 		  /* ok, now position at first defined character, and
    593 		     copy over the images */
    594 		  volatile unsigned char * c = fb + md->FLo * 32;
    595 		  const unsigned char * f = md->FData;
    596 		  unsigned short z;
    597 
    598 		  Map(2);
    599 		  for (z = md->FLo; z <= md->FHi; z++) {
    600 
    601 			short y = md->FY-1;
    602 			if (md->FX > 8){
    603 				do {
    604 					*c++ = *f;
    605 					f += 2;
    606 				} while (y--);
    607 			}
    608 			else {
    609 				do {
    610 					*c++ = *f++;
    611 				} while (y--);
    612 			}
    613 
    614 			c += 32-md->FY;
    615 
    616 		  }
    617 
    618 		  if (md->FX > 8) {
    619 			unsigned short z;
    620 
    621 			Map(3);
    622 			c = fb + md->FLo*32;
    623 			f = md->FData+1;
    624 			for (z = md->FLo; z <= md->FHi; z++) {
    625 
    626 				short y = md->FY-1;
    627 				do {
    628 					*c++ = *f;
    629 					f += 2;
    630 				} while (y--);
    631 
    632 				c += 32-md->FY;
    633 
    634 			}
    635 		  }
    636 		}
    637 
    638 	}
    639 
    640 		/* select map 0 */
    641 	WGfx (ba, GCT_ID_READ_MAP_SELECT,	0);
    642 	if (md->DEP == 4)
    643 			/* allow writes into maps 0 and 1 */
    644 		WSeq (ba, SEQ_ID_MAP_MASK,		3);
    645 	else
    646 			/* allow writes into all maps */
    647 		WSeq (ba, SEQ_ID_MAP_MASK,		0x0f);
    648 
    649 		/* select extended chain4 addressing:
    650 		    !A0/!A1	map 0	character to be displayed
    651 		    !A1/ A1	map 1	attribute of that character
    652 		     A0/!A1	map 2	not used (masked out, ignored)
    653 		     A0/ A1 	map 3	not used (masked out, ignored) */
    654 	WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR,	RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) | 0x02);
    655 
    656 	if (md->DEP == 4) {
    657 		/* position in display memory */
    658 		unsigned short * c = (unsigned short *) fb;
    659 
    660 		/* fill with blank, white on black */
    661 		const unsigned short fill_val = 0x2010;
    662 		short x = md->XY;
    663 		do {
    664 			*c = fill_val;
    665 			c += 2;
    666 		} while (x--);
    667 
    668 		/* I won't comment this :-)) */
    669 		c = (unsigned short *) fb;
    670 		c += (md->TX-6)*2;
    671 		{
    672 		  unsigned short init_msg[6] = {0x520a, 0x450b, 0x540c, 0x490d, 0x4e0e, 0x410f};
    673 		  unsigned short * f = init_msg;
    674 		  x = 5;
    675 		  do {
    676 			*c = *f++;
    677 			c += 2;
    678 	 	  } while (x--);
    679 	 	}
    680 	}
    681 	else if (md->DEP == 8) {
    682 		/* could clear the gfx screen here, but that's what the X server does anyway */
    683 	        ;
    684 	}
    685 
    686 	gp->g_data	= (caddr_t) md;
    687 	gi->gd_regaddr  = (caddr_t) ((long)ba - (long)ZORRO2ADDR + (long)ZORRO2BASE);
    688 	gi->gd_regsize  = 64*1024;
    689 
    690 	gi->gd_fbaddr   = (caddr_t) ((long)fb - (long)ZORRO2ADDR + (long)ZORRO2BASE);
    691 #ifdef BANKEDDEVPAGER
    692 	gi->gd_fbsize	= 4*1024*1024;  /* XXX */
    693 	gi->gd_bank_size = 64*1024;
    694 #else
    695 	gi->gd_fbsize   = 64*1024;	/* larger, but that's whats mappable */
    696 #endif
    697 
    698 	gi->gd_colors   = 1 << md->DEP;
    699 	gi->gd_planes   = md->DEP;
    700 
    701 	gi->gd_fbwidth  = md->MW;
    702 	gi->gd_fbheight = md->MH;
    703 	gi->gd_fbx	= 0;
    704 	gi->gd_fby	= 0;
    705 	gi->gd_dwidth   = md->TX * md->FX;
    706 	gi->gd_dheight  = md->TY * md->FY;
    707 	gi->gd_dx	= 0;
    708 	gi->gd_dy	= 0;
    709 
    710 	/* initialized, works, return 1 */
    711 	return 1;
    712 }
    713 
    714 int rt_init (struct grf_softc *gp, struct amiga_device *ad, struct amiga_hw *ahw)
    715 {
    716   /* if already initialized, fail */
    717   if (gp->g_regkva)
    718     return 0;
    719 
    720   gp->g_regkva = ahw->hw_kva;
    721   gp->g_fbkva  = ahw->hw_kva + 64*1024;
    722 
    723   /* don't let them patch it out of bounds */
    724   if ((unsigned)retina_default_mon >= retina_mon_max
    725       || monitor_defs[retina_default_mon].DEP == 8)
    726     retina_default_mon = 0;
    727 
    728   current_mon = monitor_defs + retina_default_mon;
    729 
    730   retina_inited = rt_load_mon(gp, current_mon);
    731   return(retina_inited);		/* XXX Markus maybe you */
    732 					/* XXX can make this cleaner. */
    733 }
    734 
    735 static int
    736 rt_getvmode (gp, vm)
    737      struct grf_softc *gp;
    738      struct grfvideo_mode *vm;
    739 {
    740   struct MonDef *md;
    741 
    742   if (vm->mode_num && vm->mode_num > retina_mon_max)
    743     return EINVAL;
    744 
    745   if (! vm->mode_num)
    746     vm->mode_num = (current_mon - monitor_defs) + 1;
    747 
    748   md = monitor_defs + (vm->mode_num - 1);
    749   strncpy (vm->mode_descr, monitor_descr + (vm->mode_num - 1),
    750 	   sizeof (vm->mode_descr));
    751   vm->pixel_clock  = md->FQ;
    752   vm->disp_width   = md->MW;
    753   vm->disp_height  = md->MH;
    754   vm->depth        = md->DEP;
    755   vm->hblank_start = md->HBS;
    756   vm->hblank_stop  = md->HBE;
    757   vm->hsync_start  = md->HSS;
    758   vm->hsync_stop   = md->HSE;
    759   vm->htotal       = md->HT;
    760   vm->vblank_start = md->VBS;
    761   vm->vblank_stop  = md->VBE;
    762   vm->vsync_start  = md->VSS;
    763   vm->vsync_stop   = md->VSE;
    764   vm->vtotal       = md->VT;
    765 
    766   return 0;
    767 }
    768 
    769 
    770 static int
    771 rt_setvmode (gp, mode, txtonly)
    772      struct grf_softc *gp;
    773      unsigned mode;
    774      int txtonly;
    775 {
    776   struct MonDef *md;
    777   int error;
    778 
    779   if (!mode || mode > retina_mon_max)
    780     return EINVAL;
    781 
    782   if (txtonly && monitor_defs[mode-1].DEP == 8)
    783     return EINVAL;
    784 
    785   current_mon = monitor_defs + (mode - 1);
    786 
    787   error = rt_load_mon (gp, current_mon) ? 0 : EINVAL;
    788 
    789   return error;
    790 }
    791 
    792 
    793 /*
    794  * Change the mode of the display.
    795  * Return a UNIX error number or 0 for success.
    796  */
    797 rt_mode(gp, cmd, arg, a2, a3)
    798 	register struct grf_softc *gp;
    799 	int cmd;
    800 	void *arg;
    801 	int a2, a3;
    802 {
    803   /* implement these later... */
    804 
    805   switch (cmd)
    806     {
    807     case GM_GRFON:
    808       rt_setvmode (gp, retina_default_gfx + 1, 0);
    809       return 0;
    810 
    811     case GM_GRFOFF:
    812       rt_setvmode (gp, retina_default_mon + 1, 0);
    813       return 0;
    814 
    815     case GM_GRFCONFIG:
    816       return 0;
    817 
    818     case GM_GRFGETVMODE:
    819       return rt_getvmode (gp, (struct grfvideo_mode *) arg);
    820 
    821     case GM_GRFSETVMODE:
    822       return rt_setvmode (gp, *(unsigned *) arg, 1);
    823 
    824     case GM_GRFGETNUMVM:
    825       *(int *)arg = retina_mon_max;
    826       return 0;
    827 
    828 #ifdef BANKEDDEVPAGER
    829     case GM_GRFGETBANK:
    830       *(int *)arg = rt_getbank (gp, a2, a3);
    831       return 0;
    832 
    833     case GM_GRFGETCURBANK:
    834       *(int *)arg = rt_getcurbank (gp);
    835       return 0;
    836 
    837     case GM_GRFSETBANK:
    838       return rt_setbank (gp, arg);
    839 #endif
    840     case GM_GRFIOCTL:
    841       return rt_ioctl (gp, arg, a2);
    842 
    843     default:
    844       break;
    845     }
    846 
    847   return EINVAL;
    848 }
    849 
    850 int
    851 rt_ioctl (gp, cmd, data)
    852 	register struct grf_softc *gp;
    853 	int cmd;
    854 	void *data;
    855 {
    856   switch (cmd)
    857     {
    858     case GRFIOCGSPRITEPOS:
    859       return rt_getspritepos (gp, (struct grf_position *) data);
    860 
    861     case GRFIOCSSPRITEPOS:
    862       return rt_setspritepos (gp, (struct grf_position *) data);
    863 
    864     case GRFIOCSSPRITEINF:
    865       return rt_setspriteinfo (gp, (struct grf_spriteinfo *) data);
    866 
    867     case GRFIOCGSPRITEINF:
    868       return rt_getspriteinfo (gp, (struct grf_spriteinfo *) data);
    869 
    870     case GRFIOCGSPRITEMAX:
    871       return rt_getspritemax (gp, (struct grf_position *) data);
    872 
    873     case GRFIOCGETCMAP:
    874       return rt_getcmap (gp, (struct grf_colormap *) data);
    875 
    876     case GRFIOCPUTCMAP:
    877       return rt_putcmap (gp, (struct grf_colormap *) data);
    878 
    879     case GRFIOCBITBLT:
    880       return rt_bitblt (gp, (struct grf_bitblt *) data);
    881     }
    882 
    883   return EINVAL;
    884 }
    885 
    886 #ifdef BANKEDDEVPAGER
    887 
    888 /* Retina banks can overlap. Don't use this information (yet?), and
    889    only switch 64k sized banks. */
    890 
    891 int
    892 rt_getbank (gp, offs, prot)
    893      struct grf_softc *gp;
    894      off_t offs;
    895      int prot;
    896 {
    897   /* XXX */
    898   if (offs <  0 || offs >= 4*1024*1024)
    899     return -1;
    900   else
    901     return offs >> 16;
    902 }
    903 
    904 int
    905 rt_getcurbank (gp)
    906      struct grf_softc *gp;
    907 {
    908   struct grfinfo *gi = &gp->g_display;
    909   volatile unsigned char *ba;
    910   int bank;
    911 
    912   ba = gp->g_regkva;
    913   bank = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO) | (RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI) << 8);
    914 
    915   /* bank register is multiple of 64 byte, make this multiple of 64k */
    916   bank >>= 10;
    917   return bank;
    918 }
    919 
    920 int
    921 rt_setbank (gp, bank)
    922      struct grf_softc *gp;
    923      int bank;
    924 {
    925   volatile unsigned char *ba;
    926 
    927   ba = gp->g_regkva;
    928   /* bank register is multiple of 64 byte, make this multiple of 64k */
    929   bank <<= 10;
    930   WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, (unsigned char) bank);
    931   bank >>= 8;
    932   WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, (unsigned char) bank);
    933 
    934   return 0;
    935 }
    936 
    937 #endif
    938 
    939 int
    940 rt_getcmap (gfp, cmap)
    941      struct grf_softc *gfp;
    942      struct grf_colormap *cmap;
    943 {
    944   volatile unsigned char *ba;
    945   u_char red[256], green[256], blue[256], *rp, *gp, *bp;
    946   short x;
    947   int error;
    948 
    949   if (cmap->count == 0 || cmap->index >= 256)
    950     return 0;
    951 
    952   if (cmap->index + cmap->count > 256)
    953     cmap->count = 256 - cmap->index;
    954 
    955   ba = gfp->g_regkva;
    956   /* first read colors out of the chip, then copyout to userspace */
    957   vgaw (ba, VDAC_REG_SELECT, cmap->index);
    958   x = cmap->count - 1;
    959   rp = red + cmap->index;
    960   gp = green + cmap->index;
    961   bp = blue + cmap->index;
    962   do
    963     {
    964       *rp++ = vgar (ba, VDAC_REG_DATA);
    965       *gp++ = vgar (ba, VDAC_REG_DATA);
    966       *bp++ = vgar (ba, VDAC_REG_DATA);
    967     }
    968   while (x--);
    969 
    970   if (!(error = copyout (red + cmap->index, cmap->red, cmap->count))
    971       && !(error = copyout (green + cmap->index, cmap->green, cmap->count))
    972       && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count)))
    973     return 0;
    974 
    975   return error;
    976 }
    977 
    978 int
    979 rt_putcmap (gfp, cmap)
    980      struct grf_softc *gfp;
    981      struct grf_colormap *cmap;
    982 {
    983   volatile unsigned char *ba;
    984   u_char red[256], green[256], blue[256], *rp, *gp, *bp;
    985   short x;
    986   int error;
    987 
    988   if (cmap->count == 0 || cmap->index >= 256)
    989     return 0;
    990 
    991   if (cmap->index + cmap->count > 256)
    992     cmap->count = 256 - cmap->index;
    993 
    994   /* first copy the colors into kernelspace */
    995   if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
    996       && !(error = copyin (cmap->green, green + cmap->index, cmap->count))
    997       && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count)))
    998     {
    999       ba = gfp->g_regkva;
   1000       vgaw (ba, VDAC_REG_SELECT, cmap->index);
   1001       x = cmap->count - 1;
   1002       rp = red + cmap->index;
   1003       gp = green + cmap->index;
   1004       bp = blue + cmap->index;
   1005       do
   1006 	{
   1007 	  vgaw (ba, VDAC_REG_DATA, *rp++);
   1008 	  vgaw (ba, VDAC_REG_DATA, *gp++);
   1009 	  vgaw (ba, VDAC_REG_DATA, *bp++);
   1010 	}
   1011       while (x--);
   1012       return 0;
   1013     }
   1014   else
   1015     return error;
   1016 }
   1017 
   1018 int
   1019 rt_getspritepos (gp, pos)
   1020      struct grf_softc *gp;
   1021      struct grf_position *pos;
   1022 {
   1023   volatile unsigned char *ba;
   1024 
   1025   ba = gp->g_regkva;
   1026   pos->x = vgar (ba, SEQ_ID_CURSOR_X_LOC_LO) | (vgar (ba, SEQ_ID_CURSOR_X_LOC_HI) << 8);
   1027   pos->y = vgar (ba, SEQ_ID_CURSOR_Y_LOC_LO) | (vgar (ba, SEQ_ID_CURSOR_Y_LOC_HI) << 8);
   1028   return 0;
   1029 }
   1030 
   1031 int
   1032 rt_setspritepos (gp, pos)
   1033      struct grf_softc *gp;
   1034      struct grf_position *pos;
   1035 {
   1036   volatile unsigned char *ba;
   1037 
   1038   ba = gp->g_regkva;
   1039   vgaw (ba, SEQ_ID_CURSOR_X_LOC_LO, pos->x & 0xff);
   1040   vgaw (ba, SEQ_ID_CURSOR_X_LOC_HI, (pos->x >> 8) & 0x07);
   1041   vgaw (ba, SEQ_ID_CURSOR_Y_LOC_LO, pos->y & 0xff);
   1042   vgaw (ba, SEQ_ID_CURSOR_Y_LOC_HI, (pos->y >> 8) & 0x07);
   1043   return 0;
   1044 }
   1045 
   1046 /* assume an at least 2M retina (XXX), sprite is last in memory.
   1047    According to the bogus docs, the cursor can be at most 128 lines
   1048    in height, and the x-hostspot can be placed at most at pos 31,
   1049    this gives width of a long */
   1050 #define SPRITE_ADDR (2*1024*1024 - 128*4)
   1051 
   1052 int
   1053 rt_getspriteinfo (gp, info)
   1054      struct grf_softc *gp;
   1055      struct grf_spriteinfo *info;
   1056 {
   1057   volatile unsigned char *ba, *fb;
   1058 
   1059   ba = gp->g_regkva;
   1060   fb = gp->g_fbkva;
   1061   if (info->set & GRFSPRSET_ENABLE)
   1062     info->enable = vgar (ba, SEQ_ID_CURSOR_CONTROL) & 0x01;
   1063   if (info->set & GRFSPRSET_POS)
   1064     rt_getspritepos (gp, &info->pos);
   1065   if (info->set & GRFSPRSET_HOT)
   1066     {
   1067       info->hot.x = vgar (ba, SEQ_ID_CURSOR_X_INDEX) & 0x1f;
   1068       info->hot.y = vgar (ba, SEQ_ID_CURSOR_Y_INDEX) & 0x7f;
   1069     }
   1070   if (info->set & GRFSPRSET_CMAP)
   1071     {
   1072       struct grf_colormap cmap;
   1073       int index;
   1074       cmap.index = 0;
   1075       cmap.count = 256;
   1076       rt_getcmap (gp, &cmap);
   1077       index = vgar (ba, SEQ_ID_CURSOR_COLOR0);
   1078       info->cmap.red[0] = cmap.red[index];
   1079       info->cmap.green[0] = cmap.green[index];
   1080       info->cmap.blue[0] = cmap.blue[index];
   1081       index = vgar (ba, SEQ_ID_CURSOR_COLOR1);
   1082       info->cmap.red[1] = cmap.red[index];
   1083       info->cmap.green[1] = cmap.green[index];
   1084       info->cmap.blue[1] = cmap.blue[index];
   1085     }
   1086   if (info->set & GRFSPRSET_SHAPE)
   1087     {
   1088       int saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
   1089       int saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
   1090       int last_bank = SPRITE_ADDR >> 6;
   1091       int last_bank_lo = last_bank & 0xff;
   1092       int last_bank_hi = last_bank >> 8;
   1093       u_char mask;
   1094       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, last_bank_lo);
   1095       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, last_bank_hi);
   1096       copyout (fb, info->image, 128*4);
   1097       mask = RSeq (ba, SEQ_ID_CURSOR_PIXELMASK);
   1098       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, saved_bank_lo);
   1099       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, saved_bank_hi);
   1100       copyout (&mask, info->mask, 1);
   1101       info->size.x = 32; /* ??? */
   1102       info->size.y = (RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 6) << 4;
   1103     }
   1104 
   1105 }
   1106 
   1107 int
   1108 rt_setspriteinfo (gp, info)
   1109      struct grf_softc *gp;
   1110      struct grf_spriteinfo *info;
   1111 {
   1112   volatile unsigned char *ba, *fb;
   1113   u_char control;
   1114 
   1115   ba = gp->g_regkva;
   1116   fb = gp->g_fbkva;
   1117   control = vgar (ba, SEQ_ID_CURSOR_CONTROL);
   1118   if (info->set & GRFSPRSET_ENABLE)
   1119     {
   1120       if (info->enable)
   1121 	control |= 1;
   1122       else
   1123 	control &= ~1;
   1124       vgaw (ba, SEQ_ID_CURSOR_CONTROL, control);
   1125     }
   1126   if (info->set & GRFSPRSET_POS)
   1127     rt_setspritepos (gp, &info->pos);
   1128   if (info->set & GRFSPRSET_HOT)
   1129     {
   1130       vgaw (ba, SEQ_ID_CURSOR_X_INDEX, info->hot.x & 0x1f);
   1131       vgaw (ba, SEQ_ID_CURSOR_Y_INDEX, info->hot.y & 0x7f);
   1132     }
   1133   if (info->set & GRFSPRSET_CMAP)
   1134     {
   1135       /* hey cheat a bit here.. XXX */
   1136       vgaw (ba, SEQ_ID_CURSOR_COLOR0, 0);
   1137       vgaw (ba, SEQ_ID_CURSOR_COLOR1, 1);
   1138     }
   1139   if (info->set & GRFSPRSET_SHAPE)
   1140     {
   1141       int saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
   1142       int saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
   1143       int last_bank = SPRITE_ADDR >> 6;
   1144       int last_bank_lo = last_bank & 0xff;
   1145       int last_bank_hi = last_bank >> 8;
   1146       u_char mask;
   1147       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, last_bank_lo);
   1148       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, last_bank_hi);
   1149       copyin (info->image, fb, 128*4);
   1150       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, saved_bank_lo);
   1151       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, saved_bank_hi);
   1152       copyin (info->mask, &mask, 1);
   1153       WSeq (ba, SEQ_ID_CURSOR_PIXELMASK, mask);
   1154       /* info->size.x = 32; *//* ??? */
   1155 
   1156       info->size.y = (RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 6) << 4;
   1157       control = (control & ~6) | ((info->size.y >> 4) & 6);
   1158       vgaw (ba, SEQ_ID_CURSOR_CONTROL, control);
   1159 
   1160       /* sick intel bull-addressing.. */
   1161       WSeq (ba, SEQ_ID_CURSOR_STORE_LO, SPRITE_ADDR & 0x0f);
   1162       WSeq (ba, SEQ_ID_CURSOR_STORE_HI, 0);
   1163       WSeq (ba, SEQ_ID_CURSOR_ST_OFF_LO, (SPRITE_ADDR >> 4) & 0xff);
   1164       WSeq (ba, SEQ_ID_CURSOR_ST_OFF_HI, ((SPRITE_ADDR >> 4) >> 8) & 0xff);
   1165     }
   1166 
   1167   return 0;
   1168 }
   1169 
   1170 int
   1171 rt_getspritemax (gp, pos)
   1172      struct grf_softc *gp;
   1173      struct grf_position *pos;
   1174 {
   1175   pos->x = 32;
   1176   pos->y = 128;
   1177 
   1178   return 0;
   1179 }
   1180 
   1181 
   1182 /*
   1183  * !!! THIS AREA UNDER CONSTRUCTION !!!
   1184  */
   1185 
   1186 int
   1187 rt_bitblt (gp, bb)
   1188      struct grf_softc *gp;
   1189      struct grf_bitblt *bb;
   1190 {
   1191   return EINVAL;
   1192 
   1193 
   1194 #if 0
   1195   volatile unsigned char *ba, *fb;
   1196   u_char control;
   1197   u_char saved_bank_lo;
   1198   u_char saved_bank_hi;
   1199   u_char src_bank_lo, src_bank_hi;
   1200   u_char dst_bank_lo, dst_bank_hi;
   1201   u_long src_offset, dst_offset;
   1202   u_short src_bank, dst_bank;
   1203   u_char *srcp, *dstp;
   1204   short x, y;
   1205   u_long tot;
   1206 
   1207   ba = gp->g_regkva;
   1208   fb = gp->g_fbkva;
   1209 
   1210   saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
   1211   saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
   1212 
   1213   /* for now, only GRFBBcopy is supported, and only for depth 8. No
   1214      clipping is performed, either... */
   1215 
   1216   if (bb->op != GRFBBcopy && gp->g_display.gd_planes != 8)
   1217     return EINVAL;
   1218 
   1219   src_offset = op->src_x + op->src_y * gp->g_display.gd_fbwidth;
   1220   dst_offset = op->dst_x + op->dst_y * gp->g_display.gd_fbwidth;
   1221   tot = op->w * op->h;
   1222 
   1223   /* set write mode 1, "[...] data in the read latches is written
   1224      to memory during CPU memory write cycles. [...]" */
   1225   WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 1);
   1226   /* write to primary, read from secondary */
   1227   WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, (RSeq(ba, SEQ_ID_EXTENDED_MEM_ENA) & 0x1f) | 0 );
   1228 
   1229   if (src_offset < dst_offset)
   1230     {
   1231       /* start at end */
   1232       src_offset += tot;
   1233       dst_offset += tot;
   1234     }
   1235 
   1236   src_bank_lo = (src_offset >> 6) & 0xff;
   1237   src_bank_hi = (src_offset >> 14) & 0xff;
   1238   dst_bank_lo = (dst_offset >> 6) & 0xff;
   1239   dst_bank_hi = (dst_offset >> 14) & 0xff;
   1240 
   1241   while (tot)
   1242     {
   1243       WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, src_bank_lo);
   1244       WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, src_bank_hi);
   1245       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, dst_bank_lo);
   1246       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, dst_bank_hi);
   1247 
   1248       if (src_offset < dst_offset)
   1249 	{
   1250 
   1251 
   1252 	}
   1253       else
   1254 	{
   1255 
   1256 	}
   1257     }
   1258 
   1259 
   1260 #endif
   1261 }
   1262 
   1263 
   1264 #endif	/* NGRF */
   1265