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