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