Home | History | Annotate | Line # | Download | only in dev
grf_rt.c revision 1.8
      1 /*
      2  *	$Id: grf_rt.c,v 1.8 1994/02/17 09:10:35 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_width, kernel_font_height;
     56 extern unsigned char kernel_font_lo, kernel_font_hi;
     57 extern unsigned char kernel_font[];
     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,   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,   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,   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,   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,   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,   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,   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,   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,   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,   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,   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,   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,   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,   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,   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,   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,   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   if (rt_load_mon (gp, current_mon))
    731 	  retina_inited = rt_load_mon(gp, current_mon);
    732 
    733   return(retina_inited);		/* XXX Markus maybe you */
    734 					/* XXX can make this cleaner. */
    735 }
    736 
    737 static int
    738 rt_getvmode (gp, vm)
    739      struct grf_softc *gp;
    740      struct grfvideo_mode *vm;
    741 {
    742   struct MonDef *md;
    743 
    744   if (vm->mode_num && vm->mode_num > retina_mon_max)
    745     return EINVAL;
    746 
    747   if (! vm->mode_num)
    748     vm->mode_num = (current_mon - monitor_defs) + 1;
    749 
    750   md = monitor_defs + (vm->mode_num - 1);
    751   strncpy (vm->mode_descr, monitor_descr + (vm->mode_num - 1),
    752 	   sizeof (vm->mode_descr));
    753   vm->pixel_clock  = md->FQ;
    754   vm->disp_width   = md->MW;
    755   vm->disp_height  = md->MH;
    756   vm->depth        = md->DEP;
    757   vm->hblank_start = md->HBS;
    758   vm->hblank_stop  = md->HBE;
    759   vm->hsync_start  = md->HSS;
    760   vm->hsync_stop   = md->HSE;
    761   vm->htotal       = md->HT;
    762   vm->vblank_start = md->VBS;
    763   vm->vblank_stop  = md->VBE;
    764   vm->vsync_start  = md->VSS;
    765   vm->vsync_stop   = md->VSE;
    766   vm->vtotal       = md->VT;
    767 
    768   return 0;
    769 }
    770 
    771 
    772 static int
    773 rt_setvmode (gp, mode, txtonly)
    774      struct grf_softc *gp;
    775      unsigned mode;
    776      int txtonly;
    777 {
    778   struct MonDef *md;
    779   int error;
    780 
    781   if (!mode || mode > retina_mon_max)
    782     return EINVAL;
    783 
    784   if (txtonly && monitor_defs[mode-1].DEP == 8)
    785     return EINVAL;
    786 
    787   current_mon = monitor_defs + (mode - 1);
    788 
    789   error = rt_load_mon (gp, current_mon) ? 0 : EINVAL;
    790 
    791   return error;
    792 }
    793 
    794 
    795 /*
    796  * Change the mode of the display.
    797  * Return a UNIX error number or 0 for success.
    798  */
    799 rt_mode(gp, cmd, arg, a2, a3)
    800 	register struct grf_softc *gp;
    801 	int cmd;
    802 	void *arg;
    803 	int a2, a3;
    804 {
    805   /* implement these later... */
    806 
    807   switch (cmd)
    808     {
    809     case GM_GRFON:
    810       rt_setvmode (gp, retina_default_gfx + 1, 0);
    811       return 0;
    812 
    813     case GM_GRFOFF:
    814       rt_setvmode (gp, retina_default_mon + 1, 0);
    815       return 0;
    816 
    817     case GM_GRFCONFIG:
    818       return 0;
    819 
    820     case GM_GRFGETVMODE:
    821       return rt_getvmode (gp, (struct grfvideo_mode *) arg);
    822 
    823     case GM_GRFSETVMODE:
    824       return rt_setvmode (gp, *(unsigned *) arg, 1);
    825 
    826     case GM_GRFGETNUMVM:
    827       *(int *)arg = retina_mon_max;
    828       return 0;
    829 
    830 #ifdef BANKEDDEVPAGER
    831     case GM_GRFGETBANK:
    832       *(int *)arg = rt_getbank (gp, a2, a3);
    833       return 0;
    834 
    835     case GM_GRFGETCURBANK:
    836       *(int *)arg = rt_getcurbank (gp);
    837       return 0;
    838 
    839     case GM_GRFSETBANK:
    840       return rt_setbank (gp, arg);
    841 #endif
    842     case GM_GRFIOCTL:
    843       return rt_ioctl (gp, arg, a2);
    844 
    845     default:
    846       break;
    847     }
    848 
    849   return EINVAL;
    850 }
    851 
    852 int
    853 rt_ioctl (gp, cmd, data)
    854 	register struct grf_softc *gp;
    855 	int cmd;
    856 	void *data;
    857 {
    858   switch (cmd)
    859     {
    860     case GRFIOCGSPRITEPOS:
    861       return rt_getspritepos (gp, (struct grf_position *) data);
    862 
    863     case GRFIOCSSPRITEPOS:
    864       return rt_setspritepos (gp, (struct grf_position *) data);
    865 
    866     case GRFIOCSSPRITEINF:
    867       return rt_setspriteinfo (gp, (struct grf_spriteinfo *) data);
    868 
    869     case GRFIOCGSPRITEINF:
    870       return rt_getspriteinfo (gp, (struct grf_spriteinfo *) data);
    871 
    872     case GRFIOCGSPRITEMAX:
    873       return rt_getspritemax (gp, (struct grf_position *) data);
    874 
    875     case GRFIOCGETCMAP:
    876       return rt_getcmap (gp, (struct grf_colormap *) data);
    877 
    878     case GRFIOCPUTCMAP:
    879       return rt_putcmap (gp, (struct grf_colormap *) data);
    880 
    881     case GRFIOCBITBLT:
    882       return rt_bitblt (gp, (struct grf_bitblt *) data);
    883     }
    884 
    885   return EINVAL;
    886 }
    887 
    888 #ifdef BANKEDDEVPAGER
    889 
    890 /* Retina banks can overlap. Don't use this information (yet?), and
    891    only switch 64k sized banks. */
    892 
    893 int
    894 rt_getbank (gp, offs, prot)
    895      struct grf_softc *gp;
    896      off_t offs;
    897      int prot;
    898 {
    899   /* XXX */
    900   if (offs <  0 || offs >= 4*1024*1024)
    901     return -1;
    902   else
    903     return offs >> 16;
    904 }
    905 
    906 int
    907 rt_getcurbank (gp)
    908      struct grf_softc *gp;
    909 {
    910   struct grfinfo *gi = &gp->g_display;
    911   volatile unsigned char *ba;
    912   int bank;
    913 
    914   ba = gp->g_regkva;
    915   bank = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO) | (RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI) << 8);
    916 
    917   /* bank register is multiple of 64 byte, make this multiple of 64k */
    918   bank >>= 10;
    919   return bank;
    920 }
    921 
    922 int
    923 rt_setbank (gp, bank)
    924      struct grf_softc *gp;
    925      int bank;
    926 {
    927   volatile unsigned char *ba;
    928 
    929   ba = gp->g_regkva;
    930   /* bank register is multiple of 64 byte, make this multiple of 64k */
    931   bank <<= 10;
    932   WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, (unsigned char) bank);
    933   bank >>= 8;
    934   WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, (unsigned char) bank);
    935 
    936   return 0;
    937 }
    938 
    939 #endif
    940 
    941 int
    942 rt_getcmap (gfp, cmap)
    943      struct grf_softc *gfp;
    944      struct grf_colormap *cmap;
    945 {
    946   volatile unsigned char *ba;
    947   u_char red[256], green[256], blue[256], *rp, *gp, *bp;
    948   short x;
    949   int error;
    950 
    951   if (cmap->count == 0 || cmap->index >= 256)
    952     return 0;
    953 
    954   if (cmap->index + cmap->count > 256)
    955     cmap->count = 256 - cmap->index;
    956 
    957   ba = gfp->g_regkva;
    958   /* first read colors out of the chip, then copyout to userspace */
    959   vgaw (ba, VDAC_REG_SELECT, cmap->index);
    960   x = cmap->count - 1;
    961   rp = red + cmap->index;
    962   gp = green + cmap->index;
    963   bp = blue + cmap->index;
    964   do
    965     {
    966       *rp++ = vgar (ba, VDAC_REG_DATA);
    967       *gp++ = vgar (ba, VDAC_REG_DATA);
    968       *bp++ = vgar (ba, VDAC_REG_DATA);
    969     }
    970   while (x--);
    971 
    972   if (!(error = copyout (red + cmap->index, cmap->red, cmap->count))
    973       && !(error = copyout (green + cmap->index, cmap->green, cmap->count))
    974       && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count)))
    975     return 0;
    976 
    977   return error;
    978 }
    979 
    980 int
    981 rt_putcmap (gfp, cmap)
    982      struct grf_softc *gfp;
    983      struct grf_colormap *cmap;
    984 {
    985   volatile unsigned char *ba;
    986   u_char red[256], green[256], blue[256], *rp, *gp, *bp;
    987   short x;
    988   int error;
    989 
    990   if (cmap->count == 0 || cmap->index >= 256)
    991     return 0;
    992 
    993   if (cmap->index + cmap->count > 256)
    994     cmap->count = 256 - cmap->index;
    995 
    996   /* first copy the colors into kernelspace */
    997   if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
    998       && !(error = copyin (cmap->green, green + cmap->index, cmap->count))
    999       && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count)))
   1000     {
   1001       ba = gfp->g_regkva;
   1002       vgaw (ba, VDAC_REG_SELECT, cmap->index);
   1003       x = cmap->count - 1;
   1004       rp = red + cmap->index;
   1005       gp = green + cmap->index;
   1006       bp = blue + cmap->index;
   1007       do
   1008 	{
   1009 	  vgaw (ba, VDAC_REG_DATA, *rp++);
   1010 	  vgaw (ba, VDAC_REG_DATA, *gp++);
   1011 	  vgaw (ba, VDAC_REG_DATA, *bp++);
   1012 	}
   1013       while (x--);
   1014       return 0;
   1015     }
   1016   else
   1017     return error;
   1018 }
   1019 
   1020 int
   1021 rt_getspritepos (gp, pos)
   1022      struct grf_softc *gp;
   1023      struct grf_position *pos;
   1024 {
   1025   volatile unsigned char *ba;
   1026 
   1027   ba = gp->g_regkva;
   1028   pos->x = vgar (ba, SEQ_ID_CURSOR_X_LOC_LO) | (vgar (ba, SEQ_ID_CURSOR_X_LOC_HI) << 8);
   1029   pos->y = vgar (ba, SEQ_ID_CURSOR_Y_LOC_LO) | (vgar (ba, SEQ_ID_CURSOR_Y_LOC_HI) << 8);
   1030   return 0;
   1031 }
   1032 
   1033 int
   1034 rt_setspritepos (gp, pos)
   1035      struct grf_softc *gp;
   1036      struct grf_position *pos;
   1037 {
   1038   volatile unsigned char *ba;
   1039 
   1040   ba = gp->g_regkva;
   1041   vgaw (ba, SEQ_ID_CURSOR_X_LOC_LO, pos->x & 0xff);
   1042   vgaw (ba, SEQ_ID_CURSOR_X_LOC_HI, (pos->x >> 8) & 0x07);
   1043   vgaw (ba, SEQ_ID_CURSOR_Y_LOC_LO, pos->y & 0xff);
   1044   vgaw (ba, SEQ_ID_CURSOR_Y_LOC_HI, (pos->y >> 8) & 0x07);
   1045   return 0;
   1046 }
   1047 
   1048 /* assume an at least 2M retina (XXX), sprite is last in memory.
   1049    According to the bogus docs, the cursor can be at most 128 lines
   1050    in height, and the x-hostspot can be placed at most at pos 31,
   1051    this gives width of a long */
   1052 #define SPRITE_ADDR (2*1024*1024 - 128*4)
   1053 
   1054 int
   1055 rt_getspriteinfo (gp, info)
   1056      struct grf_softc *gp;
   1057      struct grf_spriteinfo *info;
   1058 {
   1059   volatile unsigned char *ba, *fb;
   1060 
   1061   ba = gp->g_regkva;
   1062   fb = gp->g_fbkva;
   1063   if (info->set & GRFSPRSET_ENABLE)
   1064     info->enable = vgar (ba, SEQ_ID_CURSOR_CONTROL) & 0x01;
   1065   if (info->set & GRFSPRSET_POS)
   1066     rt_getspritepos (gp, &info->pos);
   1067   if (info->set & GRFSPRSET_HOT)
   1068     {
   1069       info->hot.x = vgar (ba, SEQ_ID_CURSOR_X_INDEX) & 0x1f;
   1070       info->hot.y = vgar (ba, SEQ_ID_CURSOR_Y_INDEX) & 0x7f;
   1071     }
   1072   if (info->set & GRFSPRSET_CMAP)
   1073     {
   1074       struct grf_colormap cmap;
   1075       int index;
   1076       cmap.index = 0;
   1077       cmap.count = 256;
   1078       rt_getcmap (gp, &cmap);
   1079       index = vgar (ba, SEQ_ID_CURSOR_COLOR0);
   1080       info->cmap.red[0] = cmap.red[index];
   1081       info->cmap.green[0] = cmap.green[index];
   1082       info->cmap.blue[0] = cmap.blue[index];
   1083       index = vgar (ba, SEQ_ID_CURSOR_COLOR1);
   1084       info->cmap.red[1] = cmap.red[index];
   1085       info->cmap.green[1] = cmap.green[index];
   1086       info->cmap.blue[1] = cmap.blue[index];
   1087     }
   1088   if (info->set & GRFSPRSET_SHAPE)
   1089     {
   1090       int saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
   1091       int saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
   1092       int last_bank = SPRITE_ADDR >> 6;
   1093       int last_bank_lo = last_bank & 0xff;
   1094       int last_bank_hi = last_bank >> 8;
   1095       u_char mask;
   1096       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, last_bank_lo);
   1097       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, last_bank_hi);
   1098       copyout (fb, info->image, 128*4);
   1099       mask = RSeq (ba, SEQ_ID_CURSOR_PIXELMASK);
   1100       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, saved_bank_lo);
   1101       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, saved_bank_hi);
   1102       copyout (&mask, info->mask, 1);
   1103       info->size.x = 32; /* ??? */
   1104       info->size.y = (RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 6) << 4;
   1105     }
   1106 
   1107 }
   1108 
   1109 int
   1110 rt_setspriteinfo (gp, info)
   1111      struct grf_softc *gp;
   1112      struct grf_spriteinfo *info;
   1113 {
   1114   volatile unsigned char *ba, *fb;
   1115   u_char control;
   1116 
   1117   ba = gp->g_regkva;
   1118   fb = gp->g_fbkva;
   1119   control = vgar (ba, SEQ_ID_CURSOR_CONTROL);
   1120   if (info->set & GRFSPRSET_ENABLE)
   1121     {
   1122       if (info->enable)
   1123 	control |= 1;
   1124       else
   1125 	control &= ~1;
   1126       vgaw (ba, SEQ_ID_CURSOR_CONTROL, control);
   1127     }
   1128   if (info->set & GRFSPRSET_POS)
   1129     rt_setspritepos (gp, &info->pos);
   1130   if (info->set & GRFSPRSET_HOT)
   1131     {
   1132       vgaw (ba, SEQ_ID_CURSOR_X_INDEX, info->hot.x & 0x1f);
   1133       vgaw (ba, SEQ_ID_CURSOR_Y_INDEX, info->hot.y & 0x7f);
   1134     }
   1135   if (info->set & GRFSPRSET_CMAP)
   1136     {
   1137       /* hey cheat a bit here.. XXX */
   1138       vgaw (ba, SEQ_ID_CURSOR_COLOR0, 0);
   1139       vgaw (ba, SEQ_ID_CURSOR_COLOR1, 1);
   1140     }
   1141   if (info->set & GRFSPRSET_SHAPE)
   1142     {
   1143       int saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
   1144       int saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
   1145       int last_bank = SPRITE_ADDR >> 6;
   1146       int last_bank_lo = last_bank & 0xff;
   1147       int last_bank_hi = last_bank >> 8;
   1148       u_char mask;
   1149       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, last_bank_lo);
   1150       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, last_bank_hi);
   1151       copyin (info->image, fb, 128*4);
   1152       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, saved_bank_lo);
   1153       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, saved_bank_hi);
   1154       copyin (info->mask, &mask, 1);
   1155       WSeq (ba, SEQ_ID_CURSOR_PIXELMASK, mask);
   1156       /* info->size.x = 32; *//* ??? */
   1157 
   1158       info->size.y = (RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 6) << 4;
   1159       control = (control & ~6) | ((info->size.y >> 4) & 6);
   1160       vgaw (ba, SEQ_ID_CURSOR_CONTROL, control);
   1161 
   1162       /* sick intel bull-addressing.. */
   1163       WSeq (ba, SEQ_ID_CURSOR_STORE_LO, SPRITE_ADDR & 0x0f);
   1164       WSeq (ba, SEQ_ID_CURSOR_STORE_HI, 0);
   1165       WSeq (ba, SEQ_ID_CURSOR_ST_OFF_LO, (SPRITE_ADDR >> 4) & 0xff);
   1166       WSeq (ba, SEQ_ID_CURSOR_ST_OFF_HI, ((SPRITE_ADDR >> 4) >> 8) & 0xff);
   1167     }
   1168 
   1169   return 0;
   1170 }
   1171 
   1172 int
   1173 rt_getspritemax (gp, pos)
   1174      struct grf_softc *gp;
   1175      struct grf_position *pos;
   1176 {
   1177   pos->x = 32;
   1178   pos->y = 128;
   1179 
   1180   return 0;
   1181 }
   1182 
   1183 
   1184 /*
   1185  * !!! THIS AREA UNDER CONSTRUCTION !!!
   1186  */
   1187 
   1188 int
   1189 rt_bitblt (gp, bb)
   1190      struct grf_softc *gp;
   1191      struct grf_bitblt *bb;
   1192 {
   1193   return EINVAL;
   1194 
   1195 
   1196 #if 0
   1197   volatile unsigned char *ba, *fb;
   1198   u_char control;
   1199   u_char saved_bank_lo;
   1200   u_char saved_bank_hi;
   1201   u_char src_bank_lo, src_bank_hi;
   1202   u_char dst_bank_lo, dst_bank_hi;
   1203   u_long src_offset, dst_offset;
   1204   u_short src_bank, dst_bank;
   1205   u_char *srcp, *dstp;
   1206   short x, y;
   1207   u_long tot;
   1208 
   1209   ba = gp->g_regkva;
   1210   fb = gp->g_fbkva;
   1211 
   1212   saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
   1213   saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
   1214 
   1215   /* for now, only GRFBBcopy is supported, and only for depth 8. No
   1216      clipping is performed, either... */
   1217 
   1218   if (bb->op != GRFBBcopy && gp->g_display.gd_planes != 8)
   1219     return EINVAL;
   1220 
   1221   src_offset = op->src_x + op->src_y * gp->g_display.gd_fbwidth;
   1222   dst_offset = op->dst_x + op->dst_y * gp->g_display.gd_fbwidth;
   1223   tot = op->w * op->h;
   1224 
   1225   /* set write mode 1, "[...] data in the read latches is written
   1226      to memory during CPU memory write cycles. [...]" */
   1227   WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 1);
   1228   /* write to primary, read from secondary */
   1229   WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, (RSeq(ba, SEQ_ID_EXTENDED_MEM_ENA) & 0x1f) | 0 );
   1230 
   1231   if (src_offset < dst_offset)
   1232     {
   1233       /* start at end */
   1234       src_offset += tot;
   1235       dst_offset += tot;
   1236     }
   1237 
   1238   src_bank_lo = (src_offset >> 6) & 0xff;
   1239   src_bank_hi = (src_offset >> 14) & 0xff;
   1240   dst_bank_lo = (dst_offset >> 6) & 0xff;
   1241   dst_bank_hi = (dst_offset >> 14) & 0xff;
   1242 
   1243   while (tot)
   1244     {
   1245       WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, src_bank_lo);
   1246       WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, src_bank_hi);
   1247       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, dst_bank_lo);
   1248       WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, dst_bank_hi);
   1249 
   1250       if (src_offset < dst_offset)
   1251 	{
   1252 
   1253 
   1254 	}
   1255       else
   1256 	{
   1257 
   1258 	}
   1259     }
   1260 
   1261 
   1262 #endif
   1263 }
   1264 
   1265 
   1266 #endif	/* NGRF */
   1267