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