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