xref: /netbsd-src/sys/arch/amiga/dev/grf_rt.c (revision 448e711c7835101c94f75b7ebddf58046df58290)
1 #include "grf.h"
2 #if NGRF > 0
3 
4 /* Graphics routines for the Retina board,
5    using the NCR 77C22E+ VGA controller. */
6 
7 #include "sys/param.h"
8 #include "sys/errno.h"
9 #include "grfioctl.h"
10 #include "grfvar.h"
11 #include "grf_rtreg.h"
12 #include "../include/cpu.h"
13 #include "device.h"
14 
15 extern caddr_t ZORRO2ADDR;
16 
17 /* NOTE: this driver for the MacroSystem Retina board was only possible,
18          because MacroSystem provided information about the pecularities
19          of the board. THANKS! Competition in Europe among gfx board
20          manufacturers is rather tough, so Lutz Vieweg, who wrote the
21          initial driver, has made an agreement with MS not to document
22          the driver source (see also his Copyright disclaimer below).
23          -> ALL comments after
24 	 -> "/* -------------- START OF CODE -------------- * /"
25 	 -> have been added by myself (mw) from studying the publically
26 	 -> available "NCR 77C22E+" Data Manual
27 
28 	 Lutz' original driver source (without any of my comments) is
29 	 available on request. */
30 
31 
32 /* This code offers low-level routines to access the Retina graphics-board
33    manufactured by MS MacroSystem GmbH from within NetBSD for the Amiga.
34    No warranties for any kind of function at all - this code may crash
35    your hardware and scratch your harddisk.
36    Use at your own risk.
37    Freely distributable.
38 
39    Written by Lutz Vieweg 07/93
40 
41    Thanks to MacroSystem for providing me with the neccessary information
42    to create theese routines. The sparse documentation of this code
43    results from the agreements between MS and me.
44 */
45 
46 extern unsigned char kernel_font_width, kernel_font_height;
47 extern unsigned char kernel_font_lo, kernel_font_hi;
48 extern unsigned char kernel_font[];
49 
50 
51 #define MDF_DBL 1
52 #define MDF_LACE 2
53 #define MDF_CLKDIV2 4
54 
55 
56 /* standard-palette definition */
57 
58 unsigned char NCRStdPalette[16*3] = {
59 /*   R   G   B  */
60 	  0,  0,  0,
61 	192,192,192,
62 	128,  0,  0,
63 	  0,128,  0,
64 	  0,  0,128,
65 	128,128,  0,
66 	  0,128,128,
67 	128,  0,128,
68 	 64, 64, 64, /* the higher 8 colors have more intensity for  */
69 	255,255,255, /* compatibility with standard attributes       */
70 	255,  0,  0,
71 	  0,255,  0,
72 	  0,  0,255,
73 	255,255,  0,
74 	  0,255,255,
75 	255,  0,255
76 };
77 
78 
79 /* The following structures are examples for monitor-definitions. To make one
80    of your own, first use "DefineMonitor" and create the 8-bit monitor-mode of
81    your dreams. Then save it, and make a structure from the values provided in
82    the file DefineMonitor stored - the labels in the comment above the
83    structure definition show where to put what value.
84 
85    Then you'll need to adapt your monitor-definition to the font you want to
86    use. Be FX the width of the font, then the following modifications have to
87    be applied to your values:
88 
89    HBS = (HBS * 4) / FX
90    HSS = (HSS * 4) / FX
91    HSE = (HSE * 4) / FX
92    HBE = (HBE * 4) / FX
93    HT  = (HT  * 4) / FX
94 
95    Make sure your maximum width (MW) and height (MH) are even multiples of
96    the fonts' width and height.
97 */
98 
99 #if 0
100 /* horizontal 31.5 kHz */
101 
102 /*                                      FQ     FLG    MW   MH   HBS HSS HSE HBE  HT  VBS  VSS  VSE  VBE   VT  */
103    struct MonDef MON_640_512_60  = { 50000000,  28,  640, 512,   81, 86, 93, 98, 95, 513, 513, 521, 535, 535,
104    /* Depth,           PAL, TX,  TY,    XY,FontX, FontY,    FontData,  FLo,  Fhi */
105           4, NCRStdPalette, 80,  64,  5120,    8,     8, kernel_font,   32,  255};
106 
107 /* horizontal 38kHz */
108 
109    struct MonDef MON_768_600_60  = { 75000000,  28,  768, 600,   97, 99,107,120,117, 601, 615, 625, 638, 638,
110           4, NCRStdPalette, 96,  75,  7200,    8,     8, kernel_font,   32,  255};
111 
112 /* horizontal 64kHz */
113 
114    struct MonDef MON_768_600_80  = { 50000000, 24,  768, 600,   97,104,112,122,119, 601, 606, 616, 628, 628,
115           4, NCRStdPalette, 96,  75,  7200,    8,     8, kernel_font,   32,  255};
116 
117 #if 0
118    struct MonDef MON_1024_768_80 = { 90000000, 24, 1024, 768,  129,130,141,172,169, 769, 770, 783, 804, 804,
119           4, NCRStdPalette,128,  96, 12288,    8,     8, kernel_font,   32,  255};
120 #else
121    struct MonDef MON_1024_768_80 = { 90000000, 0, 1024, 768,  257,258,278,321,320, 769, 770, 783, 804, 804,
122           4, NCRStdPalette,128,  96, 12288,    8,     8, kernel_font,   32,  255};
123 #endif
124 
125    struct MonDef MON_1024_1024_59= { 90000000, 24, 1024,1024,  129,130,141,173,170,1025,1059,1076,1087,1087,
126           4, NCRStdPalette,128, 128, 16384,    8,     8, kernel_font,   32,  255};
127 
128 /* WARNING: THE FOLLOWING MONITOR MODES EXCEED THE 90-MHz LIMIT THE PROCESSOR
129             HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
130             MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)!     */
131 
132    struct MonDef MON_1280_1024_60= {110000000,  24, 1280,1024,  161,162,176,211,208,1025,1026,1043,1073,1073,
133           4, NCRStdPalette,160, 128, 20480,    8,     8, kernel_font,   32,  255};
134 
135 /* horizontal 75kHz */
136 
137    struct MonDef MON_1280_1024_69= {120000000,  24, 1280,1024,  161,162,175,200,197,1025,1026,1043,1073,1073,
138           4, NCRStdPalette,160, 128, 20480,    8,     8, kernel_font,   32,  255};
139 
140 #else
141 
142 struct MonDef monitor_defs[] = {
143 /* horizontal 31.5 kHz */
144 
145    { 50000000,  28,  640, 512,   81, 86, 93, 98, 95, 513, 513, 521, 535, 535,
146           4, NCRStdPalette, 80,  64,  5120,    8,     8, kernel_font,   32,  255},
147 
148 /* horizontal 38kHz */
149 
150    { 75000000,  28,  768, 600,   97, 99,107,120,117, 601, 615, 625, 638, 638,
151           4, NCRStdPalette, 96,  75,  7200,    8,     8, kernel_font,   32,  255},
152 
153 /* horizontal 64kHz */
154 
155    { 50000000, 24,  768, 600,   97,104,112,122,119, 601, 606, 616, 628, 628,
156           4, NCRStdPalette, 96,  75,  7200,    8,     8, kernel_font,   32,  255},
157 
158 
159 
160    { 90000000, 24, 1024, 768,  129,130,141,172,169, 769, 770, 783, 804, 804,
161           4, NCRStdPalette,128,  96, 12288,    8,     8, kernel_font,   32,  255},
162 
163    { 100000000, 24, 1024, 768,  129,130,141,172,169, 769, 770, 783, 804, 804,
164           4, NCRStdPalette,128,  96, 12288,    8,     8, kernel_font,   32,  255},
165 
166    { 110000000, 24, 1024, 768,  129,130,141,172,169, 769, 770, 783, 804, 804,
167           4, NCRStdPalette,128,  96, 12288,    8,     8, kernel_font,   32,  255},
168 
169    { 120000000, 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    { 13000000, 24, 1024, 768,  129,130,141,172,169, 769, 770, 783, 804, 804,
173           4, NCRStdPalette,128,  96, 12288,    8,     8, kernel_font,   32,  255},
174 
175    { 72000000, 24, 1024, 768,  129,130,141,172,169, 769, 770, 783, 804, 804,
176           4, NCRStdPalette,128,  96, 12288,    8,     8, kernel_font,   32,  255},
177 
178    { 75000000, 24, 1024, 768,  129,130,141,172,169, 769, 770, 783, 804, 804,
179           4, NCRStdPalette,128,  96, 12288,    8,     8, kernel_font,   32,  255},
180 
181 
182 
183 
184    { 90000000, 24, 1024, 768,  129,130,139,161,160, 769, 770, 783, 804, 804,
185           4, NCRStdPalette,128,  96, 12288,    8,     8, kernel_font,   32,  255},
186 
187    { 90000000, 24, 1024,1024,  129,130,141,173,170,1025,1059,1076,1087,1087,
188           4, NCRStdPalette,128, 128, 16384,    8,     8, kernel_font,   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,  24, 1280,1024,  161,162,176,211,208,1025,1026,1043,1073,1073,
195           4, NCRStdPalette,160, 128, 20480,    8,     8, kernel_font,   32,  255},
196 
197 /* horizontal 75kHz */
198 
199    {120000000,  24, 1280,1024,  161,162,175,200,197,1025,1026,1043,1073,1073,
200           4, NCRStdPalette,160, 128, 20480,    8,     8, kernel_font,   32,  255},
201 
202 };
203 
204 static const char *monitor_descr[] = {
205   "80x64 (640x512) 31.5kHz",
206   "96x75 (768x600) 38kHz",
207   "96x75 (768x600) 64kHz",
208   "128x96 (1024x768) 64kHz",
209   "128x128 (1024x1024) 64kHz",
210   "160x128 (1280x1024) 64kHz ***EXCEEDS CHIP LIMIT!!!***",
211   "160x128 (1280x1024) 75kHz ***EXCEEDS CHIP LIMIT!!!***",
212 };
213 
214 int retina_mon_max = sizeof (monitor_defs)/sizeof (monitor_defs[0]);
215 
216 /* patchable */
217 int retina_default_mon = 2;
218 
219 #endif
220 
221 
222 static struct MonDef *current_mon;
223 
224 /* -------------- START OF CODE -------------- */
225 
226 
227 static const long FQTab[16] =
228 { 25175000,  28322000,  36000000,  65000000,
229   44900000,  50000000,  80000000,  75000000,
230   56644000,  63000000,  72000000, 130000000,
231   90000000, 100000000, 110000000, 120000000 };
232 
233 
234 /*--------------------------------------------------*/
235 /*--------------------------------------------------*/
236 
237 #if 0
238 static struct MonDef *default_monitor = &DEFAULT_MONDEF;
239 #endif
240 
241 
242 static int rt_load_mon (struct grf_softc *gp, struct MonDef *md)
243 {
244 	struct grfinfo *gi = &gp->g_display;
245 	volatile unsigned char *ba;
246 	volatile unsigned char *fb;
247 	short FW, clksel, HDE, VDE;
248 
249 	for (clksel = 15; clksel; clksel--) {
250 		if (FQTab[clksel] == md->FQ) break;
251 	}
252 	if (clksel < 0) return 0;
253 
254 	ba = gp->g_regkva;;
255 	fb = gp->g_fbkva;
256 
257 	switch (md->FX) {
258 	case 4:
259 		FW = 0;
260 		break;
261 	case 7:
262 		FW = 1;
263 		break;
264 	case 8:
265 		FW = 2;
266 		break;
267 	case 9:
268 		FW = 3;
269 		break;
270 	case 10:
271 		FW = 4;
272 		break;
273 	case 11:
274 		FW = 5;
275 		break;
276 	case 12:
277 		FW = 6;
278 		break;
279 	case 13:
280 		FW = 7;
281 		break;
282 	case 14:
283 		FW = 8;
284 		break;
285 	case 15:
286 		FW = 9;
287 		break;
288 	case 16:
289 		FW = 11;
290 		break;
291 	default:
292 		return 0;
293 		break;
294 	};
295 
296 	HDE = (md->MW+md->FX-1)/md->FX;
297 	VDE = md->MH-1;
298 
299 	/* hmm... */
300 	fb[0x8000] = 0;
301 
302 		/* enable extension registers */
303 	WSeq (ba, SEQ_ID_EXTENDED_ENABLE,	0x05);
304 
305 #if 0
306 	/* program the clock oscillator */
307 	vgaw (ba, GREG_MISC_OUTPUT_W, 0xe3 | ((clksel & 3) * 0x04));
308 	vgaw (ba, GREG_FEATURE_CONTROL_W, 0x00);
309 
310 	/* XXXX according to the NCR specs, this register should be set to 1
311 	   XXXX before doing the MISC_OUTPUT setting and CLOCKING_MODE
312 	   XXXX setting. */
313 	WSeq (ba, SEQ_ID_RESET, 		0x03);
314 
315 	WSeq (ba, SEQ_ID_CLOCKING_MODE, 	0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8));
316 	WSeq (ba, SEQ_ID_MAP_MASK, 		0x0f);
317 	WSeq (ba, SEQ_ID_CHAR_MAP_SELECT, 	0x00);
318 		/* odd/even write select + extended memory */
319 	WSeq (ba, SEQ_ID_MEMORY_MODE, 	0x06);
320 	/* XXXX I think this order of setting RESET is wrong... */
321 	WSeq (ba, SEQ_ID_RESET, 		0x01);
322 	WSeq (ba, SEQ_ID_RESET, 		0x03);
323 #else
324 	WSeq (ba, SEQ_ID_RESET, 		0x01);
325 
326 		/* set font width + rest of clocks */
327 	WSeq (ba, SEQ_ID_EXT_CLOCK_MODE,	0x30 | (FW & 0x0f) | ((clksel & 4) / 4 * 0x40) );
328 		/* another clock bit, plus hw stuff */
329 	WSeq (ba, SEQ_ID_MISC_FEATURE_SEL,	0xf4 | (clksel & 8) );
330 
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 	WSeq (ba, SEQ_ID_CLOCKING_MODE, 	0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8));
336 	WSeq (ba, SEQ_ID_MAP_MASK, 		0x0f);
337 	WSeq (ba, SEQ_ID_CHAR_MAP_SELECT, 	0x00);
338 		/* odd/even write select + extended memory */
339 	WSeq (ba, SEQ_ID_MEMORY_MODE, 		0x06);
340 	WSeq (ba, SEQ_ID_RESET, 		0x03);
341 #endif
342 
343 		/* monochrome cursor */
344 	WSeq (ba, SEQ_ID_CURSOR_CONTROL,	0x00);
345 		/* bank0 */
346 	WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI,	0x00);
347 	WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO,	0x00);
348 	WSeq (ba, 0x1a , 0x00);  /* these are reserved, really set them to 0 ??? */
349 	WSeq (ba, 0x1b , 0x00);  /* these are reserved, really set them to 0 ??? */
350 		/* bank0 */
351 	WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI,	0x00);
352 	WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO,	0x00);
353 		/* 1M-chips + ena SEC + ena EMem + rw PrimA0/rw Sec/B0 */
354 	WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA,	0x3 | 0x4 | 0x10 | 0x40);
355 #if 0
356 		/* set font width + rest of clocks */
357 	WSeq (ba, SEQ_ID_EXT_CLOCK_MODE,	0x30 | (FW & 0x0f) | ((clksel & 4) / 4 * 0x40) );
358 #endif
359 		/* no ext-chain4 + no host-addr-bit-16 */
360 	WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR,	0x00);
361 		/* no packed/nibble + no 256bit gfx format */
362 	WSeq (ba, SEQ_ID_EXT_PIXEL_CNTL,	0x00);
363 		/* AT-interface */
364 	WSeq (ba, SEQ_ID_BUS_WIDTH_FEEDB,	0x06);
365 		/* see fg/bg color expansion */
366 	WSeq (ba, SEQ_ID_COLOR_EXP_WFG,		0x01);
367 	WSeq (ba, SEQ_ID_COLOR_EXP_WBG,		0x00);
368 	WSeq (ba, SEQ_ID_EXT_RW_CONTROL,	0x00);
369 #if 0
370 		/* another clock bit, plus hw stuff */
371 	WSeq (ba, SEQ_ID_MISC_FEATURE_SEL,	0xf4 | (clksel & 8) );
372 #endif
373 		/* don't tristate PCLK and PIX */
374 	WSeq (ba, SEQ_ID_COLOR_KEY_CNTL,	0x40 );
375 		/* reset CRC circuit */
376 	WSeq (ba, SEQ_ID_CRC_CONTROL,		0x00 );
377 		/* set RAS/CAS swap */
378 	WSeq (ba, SEQ_ID_PERF_SELECT,		0x20);
379 
380 	WCrt (ba, CRT_ID_END_VER_RETR,		(md->VSE & 0xf ) | 0x20);
381 	WCrt (ba, CRT_ID_HOR_TOTAL,		md->HT   & 0xff);
382 	WCrt (ba, CRT_ID_HOR_DISP_ENA_END,	(HDE-1)  & 0xff);
383 	WCrt (ba, CRT_ID_START_HOR_BLANK,	md->HBS  & 0xff);
384 	WCrt (ba, CRT_ID_END_HOR_BLANK,		(md->HBE & 0x1f) | 0x80);
385 
386 	WCrt (ba, CRT_ID_START_HOR_RETR,	md->HSS  & 0xff);
387 	WCrt (ba, CRT_ID_END_HOR_RETR,		(md->HSE & 0x1f) | ((md->HBE & 0x20)/ 0x20 * 0x80));
388 	WCrt (ba, CRT_ID_VER_TOTAL,		(md->VT  & 0xff));
389 	WCrt (ba, CRT_ID_OVERFLOW,		(( (md->VSS  & 0x200) / 0x200 * 0x80)
390 						 | ((VDE     & 0x200) / 0x200 * 0x40)
391 						 | ((md->VT  & 0x200) / 0x200 * 0x20)
392 						 | 				0x10
393 						 | ((md->VBS & 0x100) / 0x100 * 8   )
394 						 | ((md->VSS & 0x100) / 0x100 * 4   )
395 						 | ((VDE     & 0x100) / 0x100 * 2   )
396 						 | ((md->VT  & 0x100) / 0x100       )));
397 	WCrt (ba, CRT_ID_PRESET_ROW_SCAN,	0x00);
398 
399 	WCrt (ba, CRT_ID_MAX_SCAN_LINE, 	((  (md->FLG & MDF_DBL)/ MDF_DBL * 0x80)
400 						 | 				   0x40
401 						 | ((md->VBS & 0x200)/0x200	 * 0x20)
402 						 | ((md->FY-1) 			 & 0x1f)));
403 
404 	WCrt (ba, CRT_ID_CURSOR_START,		(md->FY & 0x1f) - 2);
405 	WCrt (ba, CRT_ID_CURSOR_END,		(md->FY & 0x1f) - 1);
406 
407 	WCrt (ba, CRT_ID_START_ADDR_HIGH,	0x00);
408 	WCrt (ba, CRT_ID_START_ADDR_LOW,	0x00);
409 
410 	WCrt (ba, CRT_ID_CURSOR_LOC_HIGH,	0x00);
411 	WCrt (ba, CRT_ID_CURSOR_LOC_LOW,	0x00);
412 
413 	WCrt (ba, CRT_ID_START_VER_RETR,	md->VSS    & 0xff);
414 	WCrt (ba, CRT_ID_END_VER_RETR,		(md->VSE   & 0x0f) | 0x80 | 0x20);
415 	WCrt (ba, CRT_ID_VER_DISP_ENA_END,	VDE        & 0xff);
416 	WCrt (ba, CRT_ID_OFFSET,		(HDE / 2)  & 0xff);
417 	WCrt (ba, CRT_ID_UNDERLINE_LOC,		(md->FY-1) & 0x1f);
418 	WCrt (ba, CRT_ID_START_VER_BLANK,	md->VBS    & 0xff);
419 	WCrt (ba, CRT_ID_END_VER_BLANK,		md->VBE    & 0xff);
420 		/* byte mode + wrap + select row scan counter + cms */
421 	WCrt (ba, CRT_ID_MODE_CONTROL,		0xe3);
422 	WCrt (ba, CRT_ID_LINE_COMPARE,		0xff);
423 
424 		/* enable extended end bits + those bits */
425 	WCrt (ba, CRT_ID_EXT_HOR_TIMING1,	(           				 0x20
426 						 | ((md->FLG & MDF_LACE)  / MDF_LACE   * 0x10)
427 						 | ((md->HT  & 0x100) / 0x100          * 0x01)
428 						 | (((HDE-1) & 0x100) / 0x100 	       * 0x02)
429 						 | ((md->HBS & 0x100) / 0x100 	       * 0x04)
430 						 | ((md->HSS & 0x100) / 0x100 	       * 0x08)));
431 
432 	WCrt (ba, CRT_ID_EXT_START_ADDR,	(((HDE / 2) & 0x100)/0x100 * 16));
433 
434 	WCrt (ba, CRT_ID_EXT_HOR_TIMING2, 	(  ((md->HT  & 0x200)/ 0x200  	       * 0x01)
435 						 | (((HDE-1) & 0x200)/ 0x200 	       * 0x02)
436 						 | ((md->HBS & 0x200)/ 0x200 	       * 0x04)
437 						 | ((md->HSS & 0x200)/ 0x200 	       * 0x08)
438 						 | ((md->HBE & 0xc0) / 0x40  	       * 0x10)
439 						 | ((md->HSE & 0x60) / 0x20  	       * 0x40)));
440 
441 	WCrt (ba, CRT_ID_EXT_VER_TIMING,	(  ((md->VSE & 0x10) / 0x10  	       * 0x80)
442 						 | ((md->VBE & 0x300)/ 0x100 	       * 0x20)
443 						 |				         0x10
444 						 | ((md->VSS & 0x400)/ 0x400 	       * 0x08)
445 						 | ((md->VBS & 0x400)/ 0x400 	       * 0x04)
446 						 | ((VDE     & 0x400)/ 0x400 	       * 0x02)
447 						 | ((md->VT  & 0x400)/ 0x400           * 0x01)));
448 
449 	WGfx (ba, GCT_ID_SET_RESET,		0x00);
450 	WGfx (ba, GCT_ID_ENABLE_SET_RESET,	0x00);
451 	WGfx (ba, GCT_ID_COLOR_COMPARE,		0x00);
452 	WGfx (ba, GCT_ID_DATA_ROTATE,		0x00);
453 	WGfx (ba, GCT_ID_READ_MAP_SELECT,	0x00);
454 	WGfx (ba, GCT_ID_GRAPHICS_MODE,		0x00);
455 	WGfx (ba, GCT_ID_MISC,			0x04);
456 	WGfx (ba, GCT_ID_COLOR_XCARE,		0xff);
457 	WGfx (ba, GCT_ID_BITMASK,		0xff);
458 
459 	/* reset the Attribute Controller flipflop */
460 	vgar (ba, GREG_STATUS1_R);
461 	WAttr (ba, ACT_ID_PALETTE0,		0x00);
462 	WAttr (ba, ACT_ID_PALETTE1,		0x01);
463 	WAttr (ba, ACT_ID_PALETTE2,		0x02);
464 	WAttr (ba, ACT_ID_PALETTE3,		0x03);
465 	WAttr (ba, ACT_ID_PALETTE4,		0x04);
466 	WAttr (ba, ACT_ID_PALETTE5,		0x05);
467 	WAttr (ba, ACT_ID_PALETTE6,		0x06);
468 	WAttr (ba, ACT_ID_PALETTE7,		0x07);
469 	WAttr (ba, ACT_ID_PALETTE8,		0x08);
470 	WAttr (ba, ACT_ID_PALETTE9,		0x09);
471 	WAttr (ba, ACT_ID_PALETTE10,		0x0a);
472 	WAttr (ba, ACT_ID_PALETTE11,		0x0b);
473 	WAttr (ba, ACT_ID_PALETTE12,		0x0c);
474 	WAttr (ba, ACT_ID_PALETTE13,		0x0d);
475 	WAttr (ba, ACT_ID_PALETTE14,		0x0e);
476 	WAttr (ba, ACT_ID_PALETTE15,		0x0f);
477 
478 	vgar (ba, GREG_STATUS1_R);
479 	WAttr (ba, ACT_ID_ATTR_MODE_CNTL,	0x08);
480 
481 	WAttr (ba, ACT_ID_OVERSCAN_COLOR,	0x00);
482 	WAttr (ba, ACT_ID_COLOR_PLANE_ENA,	0x0f);
483 	WAttr (ba, ACT_ID_HOR_PEL_PANNING,	0x00);
484 	WAttr (ba, ACT_ID_COLOR_SELECT,	0x00);
485 
486 	vgar (ba, GREG_STATUS1_R);
487 		/* I have *NO* idea what strobing reg-0x20 might do... */
488 	vgaw (ba, ACT_ADDRESS_W, 0x20);
489 
490 	WCrt (ba, CRT_ID_MAX_SCAN_LINE,		( ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80)
491 						|	                          0x40
492 						| ((md->VBS & 0x200)/0x200	* 0x20)
493 						| ((md->FY-1) 			& 0x1f)));
494 
495 
496 	/* not it's time for guessing... */
497 
498 	vgaw (ba, VDAC_REG_D, 	   0x02);
499 
500 		/* if this does what I think it does, it selects DAC
501 		   register 0, and writes the palette in subsequent
502 		   registers, thus it works similar to the WD33C93
503 		   select/data mechanism */
504 	vgaw (ba, VDAC_REG_SELECT, 0x00);
505 
506 	{
507 
508 		short x = 15;
509 		const unsigned char * col = md->PAL;
510 		do {
511 
512 			vgaw (ba, VDAC_REG_DATA, *col++);
513 			vgaw (ba, VDAC_REG_DATA, *col++);
514 			vgaw (ba, VDAC_REG_DATA, *col++);
515 
516 
517 		} while (x--);
518 
519 	}
520 
521 
522 	/* now load the font into maps 2 (and 3 for fonts wider than 8 pixels) */
523 	{
524 
525 		/* first set the whole font memory to a test-pattern, so we
526 		   can see if something that shouldn't be drawn IS drawn.. */
527 		{
528 			unsigned char * c = fb;
529 			long x;
530 			Map(2);
531 
532 			for (x = 0; x < 65536; x++) {
533 				*c++ = (x & 1)? 0xaa : 0x55;
534 			}
535 		}
536 
537 		{
538 			unsigned char * c = fb;
539 			long x;
540 			Map(3);
541 
542 			for (x = 0; x < 65536; x++) {
543 				*c++ = (x & 1)? 0xaa : 0x55;
544 			}
545 		}
546 
547 		{
548 		  /* ok, now position at first defined character, and
549 		     copy over the images */
550 		  unsigned char * c = fb + md->FLo * 32;
551 		  const unsigned char * f = md->FData;
552 		  unsigned short z;
553 
554 		  Map(2);
555 		  for (z = md->FLo; z <= md->FHi; z++) {
556 
557 			short y = md->FY-1;
558 			if (md->FX > 8){
559 				do {
560 					*c++ = *f;
561 					f += 2;
562 				} while (y--);
563 			}
564 			else {
565 				do {
566 					*c++ = *f++;
567 				} while (y--);
568 			}
569 
570 			c += 32-md->FY;
571 
572 		  }
573 
574 		  if (md->FX > 8) {
575 			unsigned short z;
576 
577 			Map(3);
578 			c = fb + md->FLo*32;
579 			f = md->FData+1;
580 			for (z = md->FLo; z <= md->FHi; z++) {
581 
582 				short y = md->FY-1;
583 				do {
584 					*c++ = *f;
585 					f += 2;
586 				} while (y--);
587 
588 				c += 32-md->FY;
589 
590 			}
591 		  }
592 		}
593 
594 	}
595 
596 		/* select map 0 */
597 	WGfx (ba, GCT_ID_READ_MAP_SELECT,	0);
598 		/* allow writes into maps 0 and 1 */
599 	WSeq (ba, SEQ_ID_MAP_MASK,		3);
600 		/* select extended chain4 addressing:
601 		    !A0/!A1	map 0	character to be displayed
602 		    !A1/ A1	map 1	attribute of that character
603 		     A0/!A1	map 2	not used (masked out, ignored)
604 		     A0/ A1 	map 3	not used (masked out, ignored) */
605 	WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR,	RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) | 0x02);
606 
607 	{
608 		/* position in display memory */
609 		unsigned short * c = (unsigned short *) fb;
610 
611 		/* fill with blank, white on black */
612 		const unsigned short fill_val = 0x2010;
613 		short x = md->XY;
614 		do {
615 			*c = fill_val;
616 			c += 2;
617 		} while (x--);
618 
619 		/* I won't comment this :-)) */
620 		c = (unsigned short *) fb;
621 		c += (md->TX-6)*2;
622 		{
623 		  unsigned short init_msg[6] = {0x520a, 0x450b, 0x540c, 0x490d, 0x4e0e, 0x410f};
624 		  unsigned short * f = init_msg;
625 		  x = 5;
626 		  do {
627 			*c = *f++;
628 			c += 2;
629 	 	  } while (x--);
630 	 	}
631 
632 
633 	}
634 
635 
636 	gp->g_data	= (caddr_t) md;
637 	gi->gd_regaddr  = (long)ba - (long)ZORRO2ADDR + (long)ZORRO2BASE;;
638 	gi->gd_regsize  = 64*1024;
639 
640 	gi->gd_fbaddr   = (long)fb - (long)ZORRO2ADDR + (long)ZORRO2BASE;
641 	gi->gd_fbsize   = 64*1024;	/* larger, but that's whats mappable */
642 
643 	gi->gd_colors   = 1 << md->DEP;
644 	gi->gd_planes   = md->DEP;
645 
646 	gi->gd_fbwidth  = md->MW;
647 	gi->gd_fbheight = md->MH;
648 	gi->gd_fbx	= 0;
649 	gi->gd_fby	= 0;
650 	gi->gd_dwidth   = md->TX * md->FX;
651 	gi->gd_dheight  = md->TY * md->FY;
652 	gi->gd_dx	= 0;
653 	gi->gd_dy	= 0;
654 
655 	/* initialized, works, return 1 */
656 	return 1;
657 }
658 
659 int rt_init (struct grf_softc *gp, struct amiga_device *ad, struct amiga_hw *ahw)
660 {
661   /* if already initialized, fail */
662   if (gp->g_regkva)
663     return 0;
664 
665   gp->g_regkva = ahw->hw_kva;
666   gp->g_fbkva  = ahw->hw_kva + 64*1024;
667 
668   /* don't let them patch it out of bounds */
669   if ((unsigned)retina_default_mon >= retina_mon_max)
670     retina_default_mon = 0;
671 
672   current_mon = monitor_defs + retina_default_mon;
673 
674   return rt_load_mon (gp, current_mon);
675 }
676 
677 static int
678 rt_getvmode (gp, vm)
679      struct grf_softc *gp;
680      struct grfvideo_mode *vm;
681 {
682   struct MonDef *md;
683 
684   if (vm->mode_num && vm->mode_num > retina_mon_max)
685     return EINVAL;
686 
687   if (! vm->mode_num)
688     vm->mode_num = (current_mon - monitor_defs) + 1;
689 
690   md = monitor_defs + (vm->mode_num - 1);
691   strncpy (vm->mode_descr, monitor_descr + (vm->mode_num - 1),
692 	   sizeof (vm->mode_descr));
693   vm->pixel_clock  = md->FQ;
694   vm->disp_width   = md->MW;
695   vm->disp_height  = md->MH;
696   vm->depth        = md->DEP;
697   vm->hblank_start = md->HBS;
698   vm->hblank_stop  = md->HBE;
699   vm->hsync_start  = md->HSS;
700   vm->hsync_stop   = md->HSE;
701   vm->htotal       = md->HT;
702   vm->vblank_start = md->VBS;
703   vm->vblank_stop  = md->VBE;
704   vm->vsync_start  = md->VSS;
705   vm->vsync_stop   = md->VSE;
706   vm->vtotal       = md->VT;
707 
708   return 0;
709 }
710 
711 
712 static int
713 rt_setvmode (gp, mode)
714      struct grf_softc *gp;
715      unsigned mode;
716 {
717   struct MonDef *md;
718 
719   if (!mode || mode > retina_mon_max)
720     return EINVAL;
721 
722   current_mon = monitor_defs + (mode - 1);
723   return rt_load_mon (gp, current_mon) ? 0 : EINVAL;
724 }
725 
726 
727 /*
728  * Change the mode of the display.
729  * Right now all we can do is grfon/grfoff.
730  * Return a UNIX error number or 0 for success.
731  */
732 rt_mode(gp, cmd, arg)
733 	register struct grf_softc *gp;
734 	int cmd;
735 	void *arg;
736 {
737   /* implement these later... */
738 
739   switch (cmd)
740     {
741     case GM_GRFON:
742       return 0;
743 
744     case GM_GRFOFF:
745       return 0;
746 
747     case GM_GRFCONFIG:
748       return 0;
749 
750     case GM_GRFGETVMODE:
751       return rt_getvmode (gp, (struct grfvideo_mode *) arg);
752 
753     case GM_GRFSETVMODE:
754       return rt_setvmode (gp, *(unsigned *) arg);
755 
756     case GM_GRFGETNUMVM:
757       *(int *)arg = retina_mon_max;
758       return 0;
759 
760     default:
761       break;
762     }
763 
764   return EINVAL;
765 }
766 
767 #endif	/* NGRF */
768