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