grf_rt.c revision 1.37 1 /* $NetBSD: grf_rt.c,v 1.37 1999/03/25 23:20:00 is 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 __P((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 neccessary 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 __P((struct MonDef *));
262 static int rt_load_mon __P((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(mdp)
270 struct MonDef *mdp;
271 {
272 short clksel;
273
274 for (clksel = 15; clksel; clksel--) {
275 if (FQTab[clksel] == mdp->FQ)
276 break;
277 }
278 if (clksel < 0)
279 return(0);
280 if (mdp->DEP != 4)
281 return(1);
282 if (mdp->FX == 4 || (mdp->FX >= 7 && mdp->FX <= 16))
283 return(1);
284 return(0);
285 }
286
287 static int
288 rt_load_mon(gp, md)
289 struct grf_softc *gp;
290 struct MonDef *md;
291 {
292 struct grfinfo *gi = &gp->g_display;
293 volatile caddr_t ba, fb;
294 short FW, clksel, HDE, VDE;
295
296 for (clksel = 15; clksel; clksel--) {
297 if (FQTab[clksel] == md->FQ) break;
298 }
299 if (clksel < 0)
300 return(0);
301
302 ba = gp->g_regkva;;
303 fb = gp->g_fbkva;
304
305 FW = 0;
306 if (md->DEP == 4) {
307 switch (md->FX) {
308 case 4:
309 FW = 0;
310 break;
311 case 7:
312 FW = 1;
313 break;
314 case 8:
315 FW = 2;
316 break;
317 case 9:
318 FW = 3;
319 break;
320 case 10:
321 FW = 4;
322 break;
323 case 11:
324 FW = 5;
325 break;
326 case 12:
327 FW = 6;
328 break;
329 case 13:
330 FW = 7;
331 break;
332 case 14:
333 FW = 8;
334 break;
335 case 15:
336 FW = 9;
337 break;
338 case 16:
339 FW = 11;
340 break;
341 default:
342 return(0);
343 break;
344 };
345 }
346
347 if (md->DEP == 4) HDE = (md->MW+md->FX-1)/md->FX;
348 else HDE = (md->MW+3)/4;
349 VDE = md->MH-1;
350
351 /* hmm... */
352 fb[0x8000] = 0;
353
354 /* enable extension registers */
355 WSeq (ba, SEQ_ID_EXTENDED_ENABLE, 0x05);
356
357 #if 0
358 /* program the clock oscillator */
359 vgaw (ba, GREG_MISC_OUTPUT_W, 0xe3 | ((clksel & 3) * 0x04));
360 vgaw (ba, GREG_FEATURE_CONTROL_W, 0x00);
361
362 /* XXXX according to the NCR specs, this register should be set to 1
363 XXXX before doing the MISC_OUTPUT setting and CLOCKING_MODE
364 XXXX setting. */
365 WSeq (ba, SEQ_ID_RESET, 0x03);
366
367 WSeq (ba, SEQ_ID_CLOCKING_MODE, 0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8));
368 WSeq (ba, SEQ_ID_MAP_MASK, 0x0f);
369 WSeq (ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
370 /* odd/even write select + extended memory */
371 WSeq (ba, SEQ_ID_MEMORY_MODE, 0x06);
372 /* XXXX I think this order of setting RESET is wrong... */
373 WSeq (ba, SEQ_ID_RESET, 0x01);
374 WSeq (ba, SEQ_ID_RESET, 0x03);
375 #else
376 WSeq (ba, SEQ_ID_RESET, 0x01);
377
378 /* set font width + rest of clocks */
379 WSeq (ba, SEQ_ID_EXT_CLOCK_MODE, 0x30 | (FW & 0x0f) | ((clksel & 4) / 4 * 0x40) );
380 /* another clock bit, plus hw stuff */
381 WSeq (ba, SEQ_ID_MISC_FEATURE_SEL, 0xf4 | (clksel & 8) );
382
383 /* program the clock oscillator */
384 vgaw (ba, GREG_MISC_OUTPUT_W, 0xe3 | ((clksel & 3) * 0x04));
385 vgaw (ba, GREG_FEATURE_CONTROL_W, 0x00);
386
387 WSeq (ba, SEQ_ID_CLOCKING_MODE, 0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8));
388 WSeq (ba, SEQ_ID_MAP_MASK, 0x0f);
389 WSeq (ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
390 /* odd/even write select + extended memory */
391 WSeq (ba, SEQ_ID_MEMORY_MODE, 0x06);
392 WSeq (ba, SEQ_ID_RESET, 0x03);
393 #endif
394
395 /* monochrome cursor */
396 WSeq (ba, SEQ_ID_CURSOR_CONTROL, 0x00);
397 /* bank0 */
398 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, 0x00);
399 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, 0x00);
400 WSeq (ba, SEQ_ID_DISP_OFF_HI , 0x00);
401 WSeq (ba, SEQ_ID_DISP_OFF_LO , 0x00);
402 /* bank0 */
403 WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, 0x00);
404 WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, 0x00);
405 /* 1M-chips + ena SEC + ena EMem + rw PrimA0/rw Sec/B0 */
406 WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, 0x3 | 0x4 | 0x10 | 0x40);
407 #if 0
408 /* set font width + rest of clocks */
409 WSeq (ba, SEQ_ID_EXT_CLOCK_MODE, 0x30 | (FW & 0x0f) | ((clksel & 4) / 4 * 0x40) );
410 #endif
411 if (md->DEP == 4) {
412 /* no ext-chain4 + no host-addr-bit-16 */
413 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, 0x00);
414 /* no packed/nibble + no 256bit gfx format */
415 WSeq (ba, SEQ_ID_EXT_PIXEL_CNTL, 0x00);
416 }
417 else {
418 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, 0x02);
419 /* 256bit gfx format */
420 WSeq (ba, SEQ_ID_EXT_PIXEL_CNTL, 0x01);
421 }
422 /* AT-interface */
423 WSeq (ba, SEQ_ID_BUS_WIDTH_FEEDB, 0x06);
424 /* see fg/bg color expansion */
425 WSeq (ba, SEQ_ID_COLOR_EXP_WFG, 0x01);
426 WSeq (ba, SEQ_ID_COLOR_EXP_WBG, 0x00);
427 WSeq (ba, SEQ_ID_EXT_RW_CONTROL, 0x00);
428 #if 0
429 /* another clock bit, plus hw stuff */
430 WSeq (ba, SEQ_ID_MISC_FEATURE_SEL, 0xf4 | (clksel & 8) );
431 #endif
432 /* don't tristate PCLK and PIX */
433 WSeq (ba, SEQ_ID_COLOR_KEY_CNTL, 0x40 );
434 /* reset CRC circuit */
435 WSeq (ba, SEQ_ID_CRC_CONTROL, 0x00 );
436 /* set RAS/CAS swap */
437 WSeq (ba, SEQ_ID_PERF_SELECT, 0x20);
438
439 WCrt (ba, CRT_ID_END_VER_RETR, (md->VSE & 0xf ) | 0x20);
440 WCrt (ba, CRT_ID_HOR_TOTAL, md->HT & 0xff);
441 WCrt (ba, CRT_ID_HOR_DISP_ENA_END, (HDE-1) & 0xff);
442 WCrt (ba, CRT_ID_START_HOR_BLANK, md->HBS & 0xff);
443 WCrt (ba, CRT_ID_END_HOR_BLANK, (md->HBE & 0x1f) | 0x80);
444
445 WCrt (ba, CRT_ID_START_HOR_RETR, md->HSS & 0xff);
446 WCrt (ba, CRT_ID_END_HOR_RETR, (md->HSE & 0x1f) | ((md->HBE & 0x20)/ 0x20 * 0x80));
447 WCrt (ba, CRT_ID_VER_TOTAL, (md->VT & 0xff));
448 WCrt (ba, CRT_ID_OVERFLOW, (( (md->VSS & 0x200) / 0x200 * 0x80)
449 | ((VDE & 0x200) / 0x200 * 0x40)
450 | ((md->VT & 0x200) / 0x200 * 0x20)
451 | 0x10
452 | ((md->VBS & 0x100) / 0x100 * 8 )
453 | ((md->VSS & 0x100) / 0x100 * 4 )
454 | ((VDE & 0x100) / 0x100 * 2 )
455 | ((md->VT & 0x100) / 0x100 )));
456 WCrt (ba, CRT_ID_PRESET_ROW_SCAN, 0x00);
457
458 if (md->DEP == 4) {
459 WCrt (ba, CRT_ID_MAX_SCAN_LINE, (( (md->FLG & MDF_DBL)/ MDF_DBL * 0x80)
460 | 0x40
461 | ((md->VBS & 0x200)/0x200 * 0x20)
462 | ((md->FY-1) & 0x1f)));
463 }
464 else {
465 WCrt (ba, CRT_ID_MAX_SCAN_LINE, (( (md->FLG & MDF_DBL)/ MDF_DBL * 0x80)
466 | 0x40
467 | ((md->VBS & 0x200)/0x200 * 0x20)
468 | (0 & 0x1f)));
469 }
470
471 WCrt (ba, CRT_ID_CURSOR_START, (md->FY & 0x1f) - 2);
472 WCrt (ba, CRT_ID_CURSOR_END, (md->FY & 0x1f) - 1);
473
474 WCrt (ba, CRT_ID_START_ADDR_HIGH, 0x00);
475 WCrt (ba, CRT_ID_START_ADDR_LOW, 0x00);
476
477 WCrt (ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
478 WCrt (ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
479
480 WCrt (ba, CRT_ID_START_VER_RETR, md->VSS & 0xff);
481 WCrt (ba, CRT_ID_END_VER_RETR, (md->VSE & 0x0f) | 0x80 | 0x20);
482 WCrt (ba, CRT_ID_VER_DISP_ENA_END, VDE & 0xff);
483 if (md->DEP == 4)
484 WCrt (ba, CRT_ID_OFFSET, (HDE / 2) & 0xff);
485 else
486 WCrt (ba, CRT_ID_OFFSET, (md->TX / 8) & 0xff);
487
488 WCrt (ba, CRT_ID_UNDERLINE_LOC, (md->FY-1) & 0x1f);
489 WCrt (ba, CRT_ID_START_VER_BLANK, md->VBS & 0xff);
490 WCrt (ba, CRT_ID_END_VER_BLANK, md->VBE & 0xff);
491 /* byte mode + wrap + select row scan counter + cms */
492 WCrt (ba, CRT_ID_MODE_CONTROL, 0xe3);
493 WCrt (ba, CRT_ID_LINE_COMPARE, 0xff);
494
495 /* enable extended end bits + those bits */
496 WCrt (ba, CRT_ID_EXT_HOR_TIMING1, ( 0x20
497 | ((md->FLG & MDF_LACE) / MDF_LACE * 0x10)
498 | ((md->HT & 0x100) / 0x100 * 0x01)
499 | (((HDE-1) & 0x100) / 0x100 * 0x02)
500 | ((md->HBS & 0x100) / 0x100 * 0x04)
501 | ((md->HSS & 0x100) / 0x100 * 0x08)));
502
503 if (md->DEP == 4)
504 WCrt (ba, CRT_ID_EXT_START_ADDR, (((HDE / 2) & 0x100)/0x100 * 16));
505 else
506 WCrt (ba, CRT_ID_EXT_START_ADDR, (((md->TX / 8) & 0x100)/0x100 * 16));
507
508 WCrt (ba, CRT_ID_EXT_HOR_TIMING2, ( ((md->HT & 0x200)/ 0x200 * 0x01)
509 | (((HDE-1) & 0x200)/ 0x200 * 0x02)
510 | ((md->HBS & 0x200)/ 0x200 * 0x04)
511 | ((md->HSS & 0x200)/ 0x200 * 0x08)
512 | ((md->HBE & 0xc0) / 0x40 * 0x10)
513 | ((md->HSE & 0x60) / 0x20 * 0x40)));
514
515 WCrt (ba, CRT_ID_EXT_VER_TIMING, ( ((md->VSE & 0x10) / 0x10 * 0x80)
516 | ((md->VBE & 0x300)/ 0x100 * 0x20)
517 | 0x10
518 | ((md->VSS & 0x400)/ 0x400 * 0x08)
519 | ((md->VBS & 0x400)/ 0x400 * 0x04)
520 | ((VDE & 0x400)/ 0x400 * 0x02)
521 | ((md->VT & 0x400)/ 0x400 * 0x01)));
522
523 WGfx (ba, GCT_ID_SET_RESET, 0x00);
524 WGfx (ba, GCT_ID_ENABLE_SET_RESET, 0x00);
525 WGfx (ba, GCT_ID_COLOR_COMPARE, 0x00);
526 WGfx (ba, GCT_ID_DATA_ROTATE, 0x00);
527 WGfx (ba, GCT_ID_READ_MAP_SELECT, 0x00);
528 WGfx (ba, GCT_ID_GRAPHICS_MODE, 0x00);
529 if (md->DEP == 4)
530 WGfx (ba, GCT_ID_MISC, 0x04);
531 else
532 WGfx (ba, GCT_ID_MISC, 0x05);
533 WGfx (ba, GCT_ID_COLOR_XCARE, 0xff);
534 WGfx (ba, GCT_ID_BITMASK, 0xff);
535
536 /* reset the Attribute Controller flipflop */
537 vgar (ba, GREG_STATUS1_R);
538 WAttr (ba, ACT_ID_PALETTE0, 0x00);
539 WAttr (ba, ACT_ID_PALETTE1, 0x01);
540 WAttr (ba, ACT_ID_PALETTE2, 0x02);
541 WAttr (ba, ACT_ID_PALETTE3, 0x03);
542 WAttr (ba, ACT_ID_PALETTE4, 0x04);
543 WAttr (ba, ACT_ID_PALETTE5, 0x05);
544 WAttr (ba, ACT_ID_PALETTE6, 0x06);
545 WAttr (ba, ACT_ID_PALETTE7, 0x07);
546 WAttr (ba, ACT_ID_PALETTE8, 0x08);
547 WAttr (ba, ACT_ID_PALETTE9, 0x09);
548 WAttr (ba, ACT_ID_PALETTE10, 0x0a);
549 WAttr (ba, ACT_ID_PALETTE11, 0x0b);
550 WAttr (ba, ACT_ID_PALETTE12, 0x0c);
551 WAttr (ba, ACT_ID_PALETTE13, 0x0d);
552 WAttr (ba, ACT_ID_PALETTE14, 0x0e);
553 WAttr (ba, ACT_ID_PALETTE15, 0x0f);
554
555 vgar (ba, GREG_STATUS1_R);
556 if (md->DEP == 4)
557 WAttr (ba, ACT_ID_ATTR_MODE_CNTL, 0x08);
558 else
559 WAttr (ba, ACT_ID_ATTR_MODE_CNTL, 0x09);
560
561 WAttr (ba, ACT_ID_OVERSCAN_COLOR, 0x00);
562 WAttr (ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
563 WAttr (ba, ACT_ID_HOR_PEL_PANNING, 0x00);
564 WAttr (ba, ACT_ID_COLOR_SELECT, 0x00);
565
566 vgar (ba, GREG_STATUS1_R);
567 /* I have *NO* idea what strobing reg-0x20 might do... */
568 vgaw (ba, ACT_ADDRESS_W, 0x20);
569
570 if (md->DEP == 4)
571 WCrt (ba, CRT_ID_MAX_SCAN_LINE, ( ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80)
572 | 0x40
573 | ((md->VBS & 0x200)/0x200 * 0x20)
574 | ((md->FY-1) & 0x1f)));
575 else
576 WCrt (ba, CRT_ID_MAX_SCAN_LINE, ( ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80)
577 | 0x40
578 | ((md->VBS & 0x200)/0x200 * 0x20)
579 | (0 & 0x1f)));
580
581
582 /* not it's time for guessing... */
583
584 vgaw (ba, VDAC_REG_D, 0x02);
585
586 /* if this does what I think it does, it selects DAC
587 register 0, and writes the palette in subsequent
588 registers, thus it works similar to the WD33C93
589 select/data mechanism */
590 vgaw (ba, VDAC_REG_SELECT, 0x00);
591
592 {
593
594 short x = 15;
595 const unsigned char * col = md->PAL;
596 do {
597
598 vgaw (ba, VDAC_REG_DATA, *col++);
599 vgaw (ba, VDAC_REG_DATA, *col++);
600 vgaw (ba, VDAC_REG_DATA, *col++);
601
602
603 } while (x--);
604
605 if (md->DEP != 4) {
606 short x = 256-17;
607 unsigned char col = 16;
608 do {
609
610 vgaw(ba, VDAC_REG_DATA, col);
611 vgaw(ba, VDAC_REG_DATA, col);
612 vgaw(ba, VDAC_REG_DATA, col);
613 col++;
614
615 } while (x--);
616 }
617 }
618
619
620 /* now load the font into maps 2 (and 3 for fonts wider than 8 pixels) */
621 if (md->DEP == 4) {
622
623 /* first set the whole font memory to a test-pattern, so we
624 can see if something that shouldn't be drawn IS drawn.. */
625 {
626 volatile caddr_t c = fb;
627 long x;
628 Map(2);
629
630 for (x = 0; x < 65536; x++) {
631 *c++ = (x & 1)? 0xaa : 0x55;
632 }
633 }
634
635 {
636 volatile caddr_t c = fb;
637 long x;
638 Map(3);
639
640 for (x = 0; x < 65536; x++) {
641 *c++ = (x & 1)? 0xaa : 0x55;
642 }
643 }
644
645 {
646 /* ok, now position at first defined character, and
647 copy over the images */
648 volatile caddr_t c = fb + md->FLo * 32;
649 const unsigned char * f = md->FData;
650 unsigned short z;
651
652 Map(2);
653 for (z = md->FLo; z <= md->FHi; z++) {
654
655 short y = md->FY-1;
656 if (md->FX > 8){
657 do {
658 *c++ = *f;
659 f += 2;
660 } while (y--);
661 }
662 else {
663 do {
664 *c++ = *f++;
665 } while (y--);
666 }
667
668 c += 32-md->FY;
669
670 }
671
672 if (md->FX > 8) {
673 unsigned short z;
674
675 Map(3);
676 c = fb + md->FLo*32;
677 f = md->FData+1;
678 for (z = md->FLo; z <= md->FHi; z++) {
679
680 short y = md->FY-1;
681 do {
682 *c++ = *f;
683 f += 2;
684 } while (y--);
685
686 c += 32-md->FY;
687
688 }
689 }
690 }
691
692 }
693
694 /* select map 0 */
695 WGfx (ba, GCT_ID_READ_MAP_SELECT, 0);
696 if (md->DEP == 4)
697 /* allow writes into maps 0 and 1 */
698 WSeq (ba, SEQ_ID_MAP_MASK, 3);
699 else
700 /* allow writes into all maps */
701 WSeq (ba, SEQ_ID_MAP_MASK, 0x0f);
702
703 /* select extended chain4 addressing:
704 !A0/!A1 map 0 character to be displayed
705 !A1/ A1 map 1 attribute of that character
706 A0/!A1 map 2 not used (masked out, ignored)
707 A0/ A1 map 3 not used (masked out, ignored) */
708 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) | 0x02);
709
710 if (md->DEP == 4) {
711 /* position in display memory */
712 unsigned short * c = (unsigned short *) fb;
713
714 /* fill with blank, white on black */
715 const unsigned short fill_val = 0x2010;
716 short x = md->XY;
717 do {
718 *c = fill_val;
719 c += 2; } while (x--);
720
721 /* I won't comment this :-)) */
722 c = (unsigned short *) fb;
723 c += (md->TX-6)*2;
724 {
725 unsigned short init_msg[6] = {0x520a, 0x450b, 0x540c, 0x490d, 0x4e0e, 0x410f};
726 unsigned short * f = init_msg;
727 x = 5;
728 do {
729 *c = *f++;
730 c += 2;
731 } while (x--);
732 }
733 }
734 else if (md->DEP == 8) {
735 /* could clear the gfx screen here, but that's what the X server does anyway */
736 ;
737 }
738
739 gp->g_data = (caddr_t)md;
740 gi->gd_regaddr = (caddr_t)ztwopa(ba);
741 gi->gd_regsize = 64*1024;
742
743 gi->gd_fbaddr = (caddr_t)ztwopa(fb);
744 #ifdef BANKEDDEVPAGER
745 gi->gd_fbsize = 4*1024*1024; /* XXX */
746 gi->gd_bank_size = 64*1024;
747 #else
748 gi->gd_fbsize = 64*1024; /* larger, but that's whats mappable */
749 #endif
750
751 gi->gd_colors = 1 << md->DEP;
752 gi->gd_planes = md->DEP;
753
754 gi->gd_fbwidth = md->MW;
755 gi->gd_fbheight = md->MH;
756 gi->gd_fbx = 0;
757 gi->gd_fby = 0;
758 gi->gd_dwidth = md->TX * md->FX;
759 gi->gd_dheight = md->TY * md->FY;
760 gi->gd_dx = 0;
761 gi->gd_dy = 0;
762
763 /* initialized, works, return 1 */
764 return(1);
765 }
766
767 void grfrtattach __P((struct device *, struct device *, void *));
768 int grfrtprint __P((void *, const char *));
769 int grfrtmatch __P((struct device *, struct cfdata *, void *));
770
771 int rt_mode __P((struct grf_softc *, u_long, void *, u_long, int));
772 static int rt_getvmode __P((struct grf_softc *, struct grfvideo_mode *));
773 static int rt_setvmode __P((struct grf_softc *, unsigned, int));
774 int rt_getspritepos __P((struct grf_softc *, struct grf_position *));
775 int rt_setspritepos __P((struct grf_softc *, struct grf_position *));
776 int rt_getspriteinfo __P((struct grf_softc *, struct grf_spriteinfo *));
777 int rt_setspriteinfo __P((struct grf_softc *, struct grf_spriteinfo *));
778 int rt_getspritemax __P((struct grf_softc *, struct grf_position *));
779 int rt_getcmap __P((struct grf_softc *, struct grf_colormap *));
780 int rt_putcmap __P((struct grf_softc *, struct grf_colormap *));
781 int rt_bitblt __P((struct grf_softc *, struct grf_bitblt *));
782 int rt_blank __P((struct grf_softc *, int *));
783
784 struct cfattach grfrt_ca = {
785 sizeof(struct grf_softc), grfrtmatch, grfrtattach
786 };
787
788 /*
789 * only used in console init
790 */
791 static struct cfdata *cfdata;
792
793 /*
794 * we make sure to only init things once. this is somewhat
795 * tricky regarding the console.
796 */
797 int
798 grfrtmatch(pdp, cfp, auxp)
799 struct device *pdp;
800 struct cfdata *cfp;
801 void *auxp;
802 {
803 #ifdef RETINACONSOLE
804 static int rtconunit = -1;
805 #endif
806 struct zbus_args *zap;
807
808 zap = auxp;
809
810 /*
811 * allow only one retina console
812 */
813 if (amiga_realconfig == 0)
814 #ifdef RETINACONSOLE
815 if (rtconunit != -1)
816 #endif
817 return(0);
818 /*
819 * check that this is a retina board.
820 */
821 if (zap->manid != 18260 || zap->prodid != 6)
822 return(0);
823
824 #ifdef RETINACONSOLE
825 if (amiga_realconfig == 0 || rtconunit != cfp->cf_unit) {
826 #endif
827 if ((unsigned)retina_default_mon >= retina_mon_max ||
828 monitor_defs[retina_default_mon].DEP == 8)
829 retina_default_mon = 0;
830
831 current_mon = monitor_defs + retina_default_mon;
832 if (retina_alive(current_mon) == 0)
833 return(0);
834 #ifdef RETINACONSOLE
835 if (amiga_realconfig == 0) {
836 rtconunit = cfp->cf_unit;
837 cfdata = cfp;
838 }
839 }
840 #endif
841 return(1);
842 }
843
844 /*
845 * attach to the grfbus (zbus)
846 */
847 void
848 grfrtattach(pdp, dp, auxp)
849 struct device *pdp, *dp;
850 void *auxp;
851 {
852 static struct grf_softc congrf;
853 struct zbus_args *zap;
854 struct grf_softc *gp;
855
856 zap = auxp;
857
858 if (dp == NULL)
859 gp = &congrf;
860 else
861 gp = (struct grf_softc *)dp;
862
863 if (dp != NULL && congrf.g_regkva != 0) {
864 /*
865 * we inited earlier just copy the info
866 * take care not to copy the device struct though.
867 */
868 bcopy(&congrf.g_display, &gp->g_display,
869 (char *)&gp[1] - (char *)&gp->g_display);
870 } else {
871 gp->g_regkva = (volatile caddr_t)zap->va;
872 gp->g_fbkva = (volatile caddr_t)zap->va + 64 * 1024;
873 gp->g_unit = GRF_RETINAII_UNIT;
874 gp->g_flags = GF_ALIVE;
875 gp->g_mode = rt_mode;
876 gp->g_conpri = grfrt_cnprobe();
877 grfrt_iteinit(gp);
878 (void)rt_load_mon(gp, current_mon);
879 }
880 if (dp != NULL)
881 printf("\n");
882 /*
883 * attach grf
884 */
885 amiga_config_found(cfdata, &gp->g_device, gp, grfrtprint);
886 }
887
888 int
889 grfrtprint(auxp, pnp)
890 void *auxp;
891 const char *pnp;
892 {
893 if (pnp)
894 printf("grf%d at %s", ((struct grf_softc *)auxp)->g_unit,
895 pnp);
896 return(UNCONF);
897 }
898
899 static int
900 rt_getvmode (gp, vm)
901 struct grf_softc *gp;
902 struct grfvideo_mode *vm;
903 {
904 struct MonDef *md;
905 int vmul;
906
907 if (vm->mode_num && vm->mode_num > retina_mon_max)
908 return (EINVAL);
909
910 if (! vm->mode_num)
911 vm->mode_num = (current_mon - monitor_defs) + 1;
912
913 md = monitor_defs + (vm->mode_num - 1);
914 strncpy (vm->mode_descr, monitor_descr[vm->mode_num - 1],
915 sizeof (vm->mode_descr));
916 vm->pixel_clock = md->FQ;
917 vm->disp_width = md->MW;
918 vm->disp_height = md->MH;
919 vm->depth = md->DEP;
920
921 /*
922 * From observation of the monitor definition table above, I guess that
923 * the horizontal timings are in units of longwords. Hence, I get the
924 * pixels by multiplication with 32 and division by the depth.
925 * The text modes, apparently marked by depth == 4, are even more wierd.
926 * According to a comment above, they are computed from a depth==8 mode
927 * (thats for us: * 32 / 8) by applying another factor of 4 / font width.
928 * Reverse applying the latter formula most of the constants cancel
929 * themselves and we are left with a nice (* font width).
930 * That is, internal timings are in units of longwords for graphics
931 * modes, or in units of characters widths for text modes.
932 * We better don't WRITE modes until this has been real live checked.
933 * - Ignatios Souvatzis
934 */
935
936 if (md->DEP != 4) {
937 vm->hblank_start = md->HBS * 32 / md->DEP;
938 vm->hsync_start = md->HSS * 32 / md->DEP;
939 vm->hsync_stop = md->HSE * 32 / md->DEP;
940 vm->htotal = md->HT * 32 / md->DEP;
941 } else {
942 vm->hblank_start = md->HBS * md->FX;
943 vm->hsync_start = md->HSS * md->FX;
944 vm->hsync_stop = md->HSE * md->FX;
945 vm->htotal = md->HT * md->FX;
946 }
947
948
949 /* XXX move vm->disp_flags and vmul to rt_load_mon
950 * if rt_setvmode can add new modes with grfconfig */
951 vm->disp_flags = 0;
952 vmul = 2;
953 if (md->FLG & MDF_DBL) {
954 vm->disp_flags |= GRF_FLAGS_DBLSCAN;
955 vmul = 4;
956 }
957 if (md->FLG & MDF_LACE) {
958 vm->disp_flags |= GRF_FLAGS_LACE;
959 vmul = 1;
960 }
961 vm->vblank_start = md->VBS * vmul / 2;
962 vm->vsync_start = md->VSS * vmul / 2;
963 vm->vsync_stop = md->VSE * vmul / 2;
964 vm->vtotal = md->VT * vmul / 2;
965
966 return (0);
967 }
968
969
970 static int
971 rt_setvmode (gp, mode, txtonly)
972 struct grf_softc *gp;
973 unsigned mode;
974 int txtonly;
975 {
976 int error;
977
978 if (!mode || mode > retina_mon_max)
979 return (EINVAL);
980
981 if (txtonly && monitor_defs[mode-1].DEP == 8)
982 return (EINVAL);
983
984 current_mon = monitor_defs + (mode - 1);
985
986 error = rt_load_mon (gp, current_mon) ? 0 : EINVAL;
987
988 return (error);
989 }
990
991
992 /*
993 * Change the mode of the display.
994 * Return a UNIX error number or 0 for success.
995 */
996 int
997 rt_mode(gp, cmd, arg, a2, a3)
998 struct grf_softc *gp;
999 u_long cmd;
1000 void *arg;
1001 u_long a2;
1002 int a3;
1003 {
1004 /* implement these later... */
1005
1006 switch (cmd) {
1007 case GM_GRFON:
1008 rt_setvmode (gp, retina_default_gfx + 1, 0);
1009 return (0);
1010
1011 case GM_GRFOFF:
1012 rt_setvmode (gp, retina_default_mon + 1, 0);
1013 return (0);
1014
1015 case GM_GRFCONFIG:
1016 return (0);
1017
1018 case GM_GRFGETVMODE:
1019 return (rt_getvmode (gp, (struct grfvideo_mode *) arg));
1020
1021 case GM_GRFSETVMODE:
1022 return (rt_setvmode (gp, *(unsigned *) arg, 1));
1023
1024 case GM_GRFGETNUMVM:
1025 *(int *)arg = retina_mon_max;
1026 return (0);
1027
1028 #ifdef BANKEDDEVPAGER
1029 case GM_GRFGETBANK:
1030 *(int *)arg = rt_getbank (gp, a2, a3);
1031 return (0);
1032
1033 case GM_GRFGETCURBANK:
1034 *(int *)arg = rt_getcurbank (gp);
1035 return (0);
1036
1037 case GM_GRFSETBANK:
1038 return (rt_setbank (gp, arg));
1039 #endif
1040 case GM_GRFIOCTL:
1041 return (rt_ioctl (gp, a2, arg));
1042
1043 default:
1044 break;
1045 }
1046
1047 return (EINVAL);
1048 }
1049
1050 int
1051 rt_ioctl (gp, cmd, data)
1052 register struct grf_softc *gp;
1053 u_long cmd;
1054 void *data;
1055 {
1056 switch (cmd) {
1057 case GRFIOCGSPRITEPOS:
1058 return (rt_getspritepos (gp, (struct grf_position *) data));
1059
1060 case GRFIOCSSPRITEPOS:
1061 return (rt_setspritepos (gp, (struct grf_position *) data));
1062
1063 case GRFIOCSSPRITEINF:
1064 return (rt_setspriteinfo (gp, (struct grf_spriteinfo *) data));
1065
1066 case GRFIOCGSPRITEINF:
1067 return (rt_getspriteinfo (gp, (struct grf_spriteinfo *) data));
1068
1069 case GRFIOCGSPRITEMAX:
1070 return (rt_getspritemax (gp, (struct grf_position *) data));
1071
1072 case GRFIOCGETCMAP:
1073 return (rt_getcmap (gp, (struct grf_colormap *) data));
1074
1075 case GRFIOCPUTCMAP:
1076 return (rt_putcmap (gp, (struct grf_colormap *) data));
1077
1078 case GRFIOCBITBLT:
1079 return (rt_bitblt (gp, (struct grf_bitblt *) data));
1080
1081 case GRFIOCBLANK:
1082 return (rt_blank(gp, (int *)data));
1083 }
1084
1085 return (EINVAL);
1086 }
1087
1088 #ifdef BANKEDDEVPAGER
1089
1090 /* Retina banks can overlap. Don't use this information (yet?), and
1091 only switch 64k sized banks. */
1092
1093 int
1094 rt_getbank (gp, offs, prot)
1095 struct grf_softc *gp;
1096 u_long offs;
1097 int prot;
1098 {
1099 /* XXX */
1100 if (offs < 0 || offs >= 4*1024*1024)
1101 return (-1);
1102 else
1103 return (offs >> 16);
1104 }
1105
1106
1107 int
1108 rt_getcurbank (gp)
1109 struct grf_softc *gp;
1110 {
1111 struct grfinfo *gi = &gp->g_display;
1112 volatile unsigned char *ba;
1113 int bank;
1114
1115 ba = gp->g_regkva;
1116 bank = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO) |
1117 (RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI) << 8);
1118
1119 /* bank register is multiple of 64 byte, make this multiple of 64k */
1120 bank >>= 10;
1121 return (bank);
1122 }
1123
1124
1125 int
1126 rt_setbank (gp, bank)
1127 struct grf_softc *gp;
1128 int bank;
1129 {
1130 volatile unsigned char *ba;
1131
1132 ba = gp->g_regkva;
1133 /* bank register is multiple of 64 byte, make this multiple of 64k */
1134 bank <<= 10;
1135 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, (unsigned char) bank);
1136 bank >>= 8;
1137 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, (unsigned char) bank);
1138
1139 return (0);
1140 }
1141
1142 #endif /* BANKEDDEVPAGER */
1143
1144
1145 int
1146 rt_getcmap (gfp, cmap)
1147 struct grf_softc *gfp;
1148 struct grf_colormap *cmap;
1149 {
1150 volatile unsigned char *ba;
1151 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
1152 short x;
1153 int error;
1154
1155 if (cmap->count == 0 || cmap->index >= 256)
1156 return (0);
1157
1158 if (cmap->index + cmap->count > 256)
1159 cmap->count = 256 - cmap->index;
1160
1161 ba = gfp->g_regkva;
1162 /* first read colors out of the chip, then copyout to userspace */
1163 vgaw (ba, VDAC_REG_SELECT, cmap->index);
1164 x = cmap->count - 1;
1165 rp = red + cmap->index;
1166 gp = green + cmap->index;
1167 bp = blue + cmap->index;
1168 do {
1169 *rp++ = vgar (ba, VDAC_REG_DATA);
1170 *gp++ = vgar (ba, VDAC_REG_DATA);
1171 *bp++ = vgar (ba, VDAC_REG_DATA);
1172 }
1173 while (x--);
1174
1175 if (!(error = copyout (red + cmap->index, cmap->red, cmap->count))
1176 && !(error = copyout (green + cmap->index, cmap->green, cmap->count))
1177 && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count)))
1178 return (0);
1179
1180 return (error);
1181 }
1182
1183 int
1184 rt_putcmap (gfp, cmap)
1185 struct grf_softc *gfp;
1186 struct grf_colormap *cmap;
1187 {
1188 volatile unsigned char *ba;
1189 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
1190 short x;
1191 int error;
1192
1193 if (cmap->count == 0 || cmap->index >= 256)
1194 return 0;
1195
1196 if (cmap->index + cmap->count > 256)
1197 cmap->count = 256 - cmap->index;
1198
1199 /* first copy the colors into kernelspace */
1200 if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
1201 && !(error = copyin (cmap->green, green + cmap->index, cmap->count))
1202 && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count)))
1203 {
1204 ba = gfp->g_regkva;
1205 vgaw (ba, VDAC_REG_SELECT, cmap->index);
1206 x = cmap->count - 1;
1207 rp = red + cmap->index;
1208 gp = green + cmap->index;
1209 bp = blue + cmap->index;
1210 do {
1211 vgaw (ba, VDAC_REG_DATA, *rp++);
1212 vgaw (ba, VDAC_REG_DATA, *gp++);
1213 vgaw (ba, VDAC_REG_DATA, *bp++);
1214 }
1215 while (x--);
1216 return (0);
1217 } else
1218 return (error);
1219 }
1220
1221
1222 int
1223 rt_getspritepos (gp, pos)
1224 struct grf_softc *gp;
1225 struct grf_position *pos;
1226 {
1227 volatile unsigned char *ba;
1228
1229 ba = gp->g_regkva;
1230 pos->x = vgar (ba, SEQ_ID_CURSOR_X_LOC_LO) |
1231 (vgar (ba, SEQ_ID_CURSOR_X_LOC_HI) << 8);
1232 pos->y = vgar (ba, SEQ_ID_CURSOR_Y_LOC_LO) |
1233 (vgar (ba, SEQ_ID_CURSOR_Y_LOC_HI) << 8);
1234 return (0);
1235 }
1236
1237 int
1238 rt_setspritepos (gp, pos)
1239 struct grf_softc *gp;
1240 struct grf_position *pos;
1241 {
1242 volatile unsigned char *ba;
1243
1244 ba = gp->g_regkva;
1245 vgaw (ba, SEQ_ID_CURSOR_X_LOC_LO, pos->x & 0xff);
1246 vgaw (ba, SEQ_ID_CURSOR_X_LOC_HI, (pos->x >> 8) & 0x07);
1247 vgaw (ba, SEQ_ID_CURSOR_Y_LOC_LO, pos->y & 0xff);
1248 vgaw (ba, SEQ_ID_CURSOR_Y_LOC_HI, (pos->y >> 8) & 0x07);
1249 return (0);
1250 }
1251
1252 /* assume an at least 2M retina (XXX), sprite is last in memory.
1253 * According to the bogus docs, the cursor can be at most 128 lines
1254 * in height, and the x-hostspot can be placed at most at pos 31,
1255 * this gives width of a long
1256 */
1257 #define SPRITE_ADDR (2*1024*1024 - 128*4)
1258
1259 int
1260 rt_getspriteinfo (gp, info)
1261 struct grf_softc *gp;
1262 struct grf_spriteinfo *info;
1263 {
1264 volatile caddr_t ba, fb;
1265
1266 ba = gp->g_regkva;
1267 fb = gp->g_fbkva;
1268 if (info->set & GRFSPRSET_ENABLE)
1269 info->enable = vgar (ba, SEQ_ID_CURSOR_CONTROL) & 0x01;
1270 if (info->set & GRFSPRSET_POS)
1271 rt_getspritepos (gp, &info->pos);
1272 if (info->set & GRFSPRSET_HOT) {
1273 info->hot.x = vgar (ba, SEQ_ID_CURSOR_X_INDEX) & 0x1f;
1274 info->hot.y = vgar (ba, SEQ_ID_CURSOR_Y_INDEX) & 0x7f;
1275 }
1276 if (info->set & GRFSPRSET_CMAP) {
1277 struct grf_colormap cmap;
1278 int index;
1279 cmap.index = 0;
1280 cmap.count = 256;
1281 rt_getcmap (gp, &cmap);
1282 index = vgar (ba, SEQ_ID_CURSOR_COLOR0);
1283 info->cmap.red[0] = cmap.red[index];
1284 info->cmap.green[0] = cmap.green[index];
1285 info->cmap.blue[0] = cmap.blue[index];
1286 index = vgar (ba, SEQ_ID_CURSOR_COLOR1);
1287 info->cmap.red[1] = cmap.red[index];
1288 info->cmap.green[1] = cmap.green[index];
1289 info->cmap.blue[1] = cmap.blue[index];
1290 }
1291 if (info->set & GRFSPRSET_SHAPE) {
1292 int saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
1293 int saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
1294 int last_bank = SPRITE_ADDR >> 6;
1295 int last_bank_lo = last_bank & 0xff;
1296 int last_bank_hi = last_bank >> 8;
1297 u_char mask;
1298 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, last_bank_lo);
1299 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, last_bank_hi);
1300 copyout (fb, info->image, 128*4);
1301 mask = RSeq (ba, SEQ_ID_CURSOR_PIXELMASK);
1302 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, saved_bank_lo);
1303 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, saved_bank_hi);
1304 copyout (&mask, info->mask, 1);
1305 info->size.x = 32; /* ??? */
1306 info->size.y = (RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 6) << 4;
1307 }
1308
1309 return (0);
1310 }
1311
1312
1313 int
1314 rt_setspriteinfo (gp, info)
1315 struct grf_softc *gp;
1316 struct grf_spriteinfo *info;
1317 {
1318 volatile caddr_t ba, fb;
1319 u_char control;
1320
1321 ba = gp->g_regkva;
1322 fb = gp->g_fbkva;
1323 control = vgar (ba, SEQ_ID_CURSOR_CONTROL);
1324 if (info->set & GRFSPRSET_ENABLE) {
1325 if (info->enable)
1326 control |= 1;
1327 else
1328 control &= ~1;
1329 vgaw (ba, SEQ_ID_CURSOR_CONTROL, control);
1330 }
1331 if (info->set & GRFSPRSET_POS)
1332 rt_setspritepos (gp, &info->pos);
1333 if (info->set & GRFSPRSET_HOT) {
1334 vgaw (ba, SEQ_ID_CURSOR_X_INDEX, info->hot.x & 0x1f);
1335 vgaw (ba, SEQ_ID_CURSOR_Y_INDEX, info->hot.y & 0x7f);
1336 }
1337 if (info->set & GRFSPRSET_CMAP) {
1338 /* hey cheat a bit here.. XXX */
1339 vgaw (ba, SEQ_ID_CURSOR_COLOR0, 0);
1340 vgaw (ba, SEQ_ID_CURSOR_COLOR1, 1);
1341 }
1342 if (info->set & GRFSPRSET_SHAPE) {
1343 int saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
1344 int saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
1345 int last_bank = SPRITE_ADDR >> 6;
1346 int last_bank_lo = last_bank & 0xff;
1347 int last_bank_hi = last_bank >> 8;
1348 u_char mask;
1349 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, last_bank_lo);
1350 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, last_bank_hi);
1351 copyin (info->image, fb, 128*4);
1352 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, saved_bank_lo);
1353 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, saved_bank_hi);
1354 copyin (info->mask, &mask, 1);
1355 WSeq (ba, SEQ_ID_CURSOR_PIXELMASK, mask);
1356 /* info->size.x = 32; *//* ??? */
1357
1358 info->size.y = (RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 6) << 4;
1359 control = (control & ~6) | ((info->size.y >> 4) & 6);
1360 vgaw (ba, SEQ_ID_CURSOR_CONTROL, control);
1361
1362 /* sick intel bull-addressing.. */
1363 WSeq (ba, SEQ_ID_CURSOR_STORE_LO, SPRITE_ADDR & 0x0f);
1364 WSeq (ba, SEQ_ID_CURSOR_STORE_HI, 0);
1365 WSeq (ba, SEQ_ID_CURSOR_ST_OFF_LO, (SPRITE_ADDR >> 4) & 0xff);
1366 WSeq (ba, SEQ_ID_CURSOR_ST_OFF_HI, ((SPRITE_ADDR >> 4) >> 8) & 0xff);
1367 }
1368
1369 return (0);
1370 }
1371
1372
1373 int
1374 rt_getspritemax (gp, pos)
1375 struct grf_softc *gp;
1376 struct grf_position *pos;
1377 {
1378 pos->x = 32;
1379 pos->y = 128;
1380
1381 return (0);
1382 }
1383
1384
1385 /*
1386 * !!! THIS AREA UNDER CONSTRUCTION !!!
1387 */
1388
1389 int
1390 rt_bitblt (gp, bb)
1391 struct grf_softc *gp;
1392 struct grf_bitblt *bb;
1393 {
1394 return (EINVAL);
1395
1396 #if 0
1397 volatile caddr_t ba, fb;
1398 u_char control;
1399 u_char saved_bank_lo;
1400 u_char saved_bank_hi;
1401 u_char src_bank_lo, src_bank_hi;
1402 u_char dst_bank_lo, dst_bank_hi;
1403 u_long src_offset, dst_offset;
1404 u_short src_bank, dst_bank;
1405 u_char *srcp, *dstp;
1406 short x, y;
1407 u_long tot;
1408
1409 ba = gp->g_regkva;
1410 fb = gp->g_fbkva;
1411
1412 saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
1413 saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
1414
1415 /* for now, only GRFBBcopy is supported, and only for depth 8. No
1416 clipping is performed, either... */
1417
1418 if (bb->op != GRFBBcopy && gp->g_display.gd_planes != 8)
1419 return EINVAL;
1420
1421 src_offset = op->src_x + op->src_y * gp->g_display.gd_fbwidth;
1422 dst_offset = op->dst_x + op->dst_y * gp->g_display.gd_fbwidth;
1423 tot = op->w * op->h;
1424
1425 /* set write mode 1, "[...] data in the read latches is written
1426 to memory during CPU memory write cycles. [...]" */
1427 WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 1);
1428 /* write to primary, read from secondary */
1429 WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, (RSeq(ba, SEQ_ID_EXTENDED_MEM_ENA) & 0x1f) | 0 );
1430
1431 if (src_offset < dst_offset)
1432 {
1433 /* start at end */
1434 src_offset += tot;
1435 dst_offset += tot;
1436 }
1437
1438 src_bank_lo = (src_offset >> 6) & 0xff;
1439 src_bank_hi = (src_offset >> 14) & 0xff;
1440 dst_bank_lo = (dst_offset >> 6) & 0xff;
1441 dst_bank_hi = (dst_offset >> 14) & 0xff;
1442
1443 while (tot)
1444 {
1445 WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, src_bank_lo);
1446 WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, src_bank_hi);
1447 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, dst_bank_lo);
1448 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, dst_bank_hi);
1449
1450 if (src_offset < dst_offset)
1451 {
1452
1453
1454 }
1455 else
1456 {
1457
1458 }
1459 }
1460
1461
1462 #endif
1463 }
1464
1465
1466 int
1467 rt_blank(gp, on)
1468 struct grf_softc *gp;
1469 int *on;
1470 {
1471 struct MonDef *md = (struct MonDef *)gp->g_data;
1472 int r;
1473
1474 r = 0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8);
1475
1476 WSeq(gp->g_regkva, SEQ_ID_CLOCKING_MODE, *on > 0 ? r : 0x21);
1477
1478 return(0);
1479 }
1480
1481 #endif /* NGRF */
1482