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