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