grf_rt.c revision 1.24 1 /* $NetBSD: grf_rt.c,v 1.24 1996/03/17 01:17:18 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/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 *, void *, void *));
767
768 struct cfattach grfrt_ca = {
769 sizeof(struct grf_softc), grfrtmatch, grfrtattach
770 };
771
772 struct cfdriver grfrt_cd = {
773 NULL, "grfrt", DV_DULL, NULL, 0
774 };
775
776 /*
777 * only used in console init
778 */
779 static struct cfdata *cfdata;
780
781 /*
782 * we make sure to only init things once. this is somewhat
783 * tricky regarding the console.
784 */
785 int
786 grfrtmatch(pdp, match, auxp)
787 struct device *pdp;
788 void *match, *auxp;
789 {
790 struct cfdata *cfp = match;
791 #ifdef RETINACONSOLE
792 static int rtconunit = -1;
793 #endif
794 struct zbus_args *zap;
795
796 zap = auxp;
797
798 /*
799 * allow only one retina console
800 */
801 if (amiga_realconfig == 0)
802 #ifdef RETINACONSOLE
803 if (rtconunit != -1)
804 #endif
805 return(0);
806 /*
807 * check that this is a retina board.
808 */
809 if (zap->manid != 18260 || zap->prodid != 6)
810 return(0);
811
812 #ifdef RETINACONSOLE
813 if (amiga_realconfig == 0 || rtconunit != cfp->cf_unit) {
814 #endif
815 if ((unsigned)retina_default_mon >= retina_mon_max ||
816 monitor_defs[retina_default_mon].DEP == 8)
817 retina_default_mon = 0;
818
819 current_mon = monitor_defs + retina_default_mon;
820 if (retina_alive(current_mon) == 0)
821 return(0);
822 #ifdef RETINACONSOLE
823 if (amiga_realconfig == 0) {
824 rtconunit = cfp->cf_unit;
825 cfdata = cfp;
826 }
827 }
828 #endif
829 return(1);
830 }
831
832 /*
833 * attach to the grfbus (zbus)
834 */
835 void
836 grfrtattach(pdp, dp, auxp)
837 struct device *pdp, *dp;
838 void *auxp;
839 {
840 static struct grf_softc congrf;
841 static int coninited;
842 struct zbus_args *zap;
843 struct grf_softc *gp;
844
845 zap = auxp;
846
847 if (dp == NULL)
848 gp = &congrf;
849 else
850 gp = (struct grf_softc *)dp;
851
852 if (dp != NULL && congrf.g_regkva != 0) {
853 /*
854 * we inited earlier just copy the info
855 * take care not to copy the device struct though.
856 */
857 bcopy(&congrf.g_display, &gp->g_display,
858 (char *)&gp[1] - (char *)&gp->g_display);
859 } else {
860 gp->g_regkva = (volatile caddr_t)zap->va;
861 gp->g_fbkva = (volatile caddr_t)zap->va + 64 * 1024;
862 gp->g_unit = GRF_RETINAII_UNIT;
863 gp->g_flags = GF_ALIVE;
864 gp->g_mode = rt_mode;
865 gp->g_conpri = grfrt_cnprobe();
866 grfrt_iteinit(gp);
867 (void)rt_load_mon(gp, current_mon);
868 }
869 if (dp != NULL)
870 printf("\n");
871 /*
872 * attach grf
873 */
874 amiga_config_found(cfdata, &gp->g_device, gp, grfrtprint);
875 }
876
877 int
878 grfrtprint(auxp, pnp)
879 void *auxp;
880 char *pnp;
881 {
882 if (pnp)
883 printf("grf%d at %s", ((struct grf_softc *)auxp)->g_unit,
884 pnp);
885 return(UNCONF);
886 }
887
888 static int
889 rt_getvmode (gp, vm)
890 struct grf_softc *gp;
891 struct grfvideo_mode *vm;
892 {
893 struct MonDef *md;
894
895 if (vm->mode_num && vm->mode_num > retina_mon_max)
896 return EINVAL;
897
898 if (! vm->mode_num)
899 vm->mode_num = (current_mon - monitor_defs) + 1;
900
901 md = monitor_defs + (vm->mode_num - 1);
902 strncpy (vm->mode_descr, monitor_descr + (vm->mode_num - 1),
903 sizeof (vm->mode_descr));
904 vm->pixel_clock = md->FQ;
905 vm->disp_width = md->MW;
906 vm->disp_height = md->MH;
907 vm->depth = md->DEP;
908
909 /*
910 * From observation of the monitor definition table above, I guess that
911 * the horizontal timings are in units of longwords. Hence, I get the
912 * pixels by multiplication with 32 and division by the depth.
913 * The text modes, apparently marked by depth == 4, are even more wierd.
914 * According to a comment above, they are computed from a depth==8 mode
915 * (thats for us: * 32 / 8) by applying another factor of 4 / font width.
916 * Reverse applying the latter formula most of the constants cancel
917 * themselves and we are left with a nice (* font width).
918 * That is, internal timings are in units of longwords for graphics
919 * modes, or in units of characters widths for text modes.
920 * We better don't WRITE modes until this has been real live checked.
921 * - Ignatios Souvatzis
922 */
923
924 if (md->DEP == 4) {
925 vm->hblank_start = md->HBS * 32 / md->DEP;
926 vm->hblank_stop = md->HBE * 32 / md->DEP;
927 vm->hsync_start = md->HSS * 32 / md->DEP;
928 vm->hsync_stop = md->HSE * 32 / md->DEP;
929 vm->htotal = md->HT * 32 / md->DEP;
930 } else {
931 vm->hblank_start = md->HBS * md->FX;
932 vm->hblank_stop = md->HBE * md->FX;
933 vm->hsync_start = md->HSS * md->FX;
934 vm->hsync_stop = md->HSE * md->FX;
935 vm->htotal = md->HT * md->FX;
936 }
937 vm->vblank_start = md->VBS;
938 vm->vblank_stop = md->VBE;
939 vm->vsync_start = md->VSS;
940 vm->vsync_stop = md->VSE;
941 vm->vtotal = md->VT;
942
943 return 0;
944 }
945
946
947 static int
948 rt_setvmode (gp, mode, txtonly)
949 struct grf_softc *gp;
950 unsigned mode;
951 int txtonly;
952 {
953 struct MonDef *md;
954 int error;
955
956 if (!mode || mode > retina_mon_max)
957 return EINVAL;
958
959 if (txtonly && monitor_defs[mode-1].DEP == 8)
960 return EINVAL;
961
962 current_mon = monitor_defs + (mode - 1);
963
964 error = rt_load_mon (gp, current_mon) ? 0 : EINVAL;
965
966 return error;
967 }
968
969
970 /*
971 * Change the mode of the display.
972 * Return a UNIX error number or 0 for success.
973 */
974 int
975 rt_mode(gp, cmd, arg, a2, a3)
976 struct grf_softc *gp;
977 int cmd;
978 void *arg;
979 int a2, a3;
980 {
981 /* implement these later... */
982
983 switch (cmd)
984 {
985 case GM_GRFON:
986 rt_setvmode (gp, retina_default_gfx + 1, 0);
987 return 0;
988
989 case GM_GRFOFF:
990 rt_setvmode (gp, retina_default_mon + 1, 0);
991 return 0;
992
993 case GM_GRFCONFIG:
994 return 0;
995
996 case GM_GRFGETVMODE:
997 return rt_getvmode (gp, (struct grfvideo_mode *) arg);
998
999 case GM_GRFSETVMODE:
1000 return rt_setvmode (gp, *(unsigned *) arg, 1);
1001
1002 case GM_GRFGETNUMVM:
1003 *(int *)arg = retina_mon_max;
1004 return 0;
1005
1006 #ifdef BANKEDDEVPAGER
1007 case GM_GRFGETBANK:
1008 *(int *)arg = rt_getbank (gp, a2, a3);
1009 return 0;
1010
1011 case GM_GRFGETCURBANK:
1012 *(int *)arg = rt_getcurbank (gp);
1013 return 0;
1014
1015 case GM_GRFSETBANK:
1016 return rt_setbank (gp, arg);
1017 #endif
1018 case GM_GRFIOCTL:
1019 return rt_ioctl (gp, (u_long)arg, (void *)a2);
1020
1021 default:
1022 break;
1023 }
1024
1025 return EINVAL;
1026 }
1027
1028 int
1029 rt_ioctl (gp, cmd, data)
1030 register struct grf_softc *gp;
1031 u_long cmd;
1032 void *data;
1033 {
1034 switch (cmd)
1035 {
1036 case GRFIOCGSPRITEPOS:
1037 return rt_getspritepos (gp, (struct grf_position *) data);
1038
1039 case GRFIOCSSPRITEPOS:
1040 return rt_setspritepos (gp, (struct grf_position *) data);
1041
1042 case GRFIOCSSPRITEINF:
1043 return rt_setspriteinfo (gp, (struct grf_spriteinfo *) data);
1044
1045 case GRFIOCGSPRITEINF:
1046 return rt_getspriteinfo (gp, (struct grf_spriteinfo *) data);
1047
1048 case GRFIOCGSPRITEMAX:
1049 return rt_getspritemax (gp, (struct grf_position *) data);
1050
1051 case GRFIOCGETCMAP:
1052 return rt_getcmap (gp, (struct grf_colormap *) data);
1053
1054 case GRFIOCPUTCMAP:
1055 return rt_putcmap (gp, (struct grf_colormap *) data);
1056
1057 case GRFIOCBITBLT:
1058 return rt_bitblt (gp, (struct grf_bitblt *) data);
1059 }
1060
1061 return EINVAL;
1062 }
1063
1064 #ifdef BANKEDDEVPAGER
1065
1066 /* Retina banks can overlap. Don't use this information (yet?), and
1067 only switch 64k sized banks. */
1068
1069 int
1070 rt_getbank (gp, offs, prot)
1071 struct grf_softc *gp;
1072 off_t offs;
1073 int prot;
1074 {
1075 /* XXX */
1076 if (offs < 0 || offs >= 4*1024*1024)
1077 return -1;
1078 else
1079 return offs >> 16;
1080 }
1081
1082 int
1083 rt_getcurbank (gp)
1084 struct grf_softc *gp;
1085 {
1086 struct grfinfo *gi = &gp->g_display;
1087 volatile unsigned char *ba;
1088 int bank;
1089
1090 ba = gp->g_regkva;
1091 bank = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO) | (RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI) << 8);
1092
1093 /* bank register is multiple of 64 byte, make this multiple of 64k */
1094 bank >>= 10;
1095 return bank;
1096 }
1097
1098 int
1099 rt_setbank (gp, bank)
1100 struct grf_softc *gp;
1101 int bank;
1102 {
1103 volatile unsigned char *ba;
1104
1105 ba = gp->g_regkva;
1106 /* bank register is multiple of 64 byte, make this multiple of 64k */
1107 bank <<= 10;
1108 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, (unsigned char) bank);
1109 bank >>= 8;
1110 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, (unsigned char) bank);
1111
1112 return 0;
1113 }
1114
1115 #endif
1116
1117 int
1118 rt_getcmap (gfp, cmap)
1119 struct grf_softc *gfp;
1120 struct grf_colormap *cmap;
1121 {
1122 volatile unsigned char *ba;
1123 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
1124 short x;
1125 int error;
1126
1127 if (cmap->count == 0 || cmap->index >= 256)
1128 return 0;
1129
1130 if (cmap->index + cmap->count > 256)
1131 cmap->count = 256 - cmap->index;
1132
1133 ba = gfp->g_regkva;
1134 /* first read colors out of the chip, then copyout to userspace */
1135 vgaw (ba, VDAC_REG_SELECT, cmap->index);
1136 x = cmap->count - 1;
1137 rp = red + cmap->index;
1138 gp = green + cmap->index;
1139 bp = blue + cmap->index;
1140 do
1141 {
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 (gfp, cmap)
1158 struct grf_softc *gfp;
1159 struct grf_colormap *cmap;
1160 {
1161 volatile unsigned char *ba;
1162 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
1163 short x;
1164 int error;
1165
1166 if (cmap->count == 0 || cmap->index >= 256)
1167 return 0;
1168
1169 if (cmap->index + cmap->count > 256)
1170 cmap->count = 256 - cmap->index;
1171
1172 /* first copy the colors into kernelspace */
1173 if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
1174 && !(error = copyin (cmap->green, green + cmap->index, cmap->count))
1175 && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count)))
1176 {
1177 ba = gfp->g_regkva;
1178 vgaw (ba, VDAC_REG_SELECT, cmap->index);
1179 x = cmap->count - 1;
1180 rp = red + cmap->index;
1181 gp = green + cmap->index;
1182 bp = blue + cmap->index;
1183 do
1184 {
1185 vgaw (ba, VDAC_REG_DATA, *rp++);
1186 vgaw (ba, VDAC_REG_DATA, *gp++);
1187 vgaw (ba, VDAC_REG_DATA, *bp++);
1188 }
1189 while (x--);
1190 return 0;
1191 }
1192 else
1193 return error;
1194 }
1195
1196 int
1197 rt_getspritepos (gp, pos)
1198 struct grf_softc *gp;
1199 struct grf_position *pos;
1200 {
1201 volatile unsigned char *ba;
1202
1203 ba = gp->g_regkva;
1204 pos->x = vgar (ba, SEQ_ID_CURSOR_X_LOC_LO) | (vgar (ba, SEQ_ID_CURSOR_X_LOC_HI) << 8);
1205 pos->y = vgar (ba, SEQ_ID_CURSOR_Y_LOC_LO) | (vgar (ba, SEQ_ID_CURSOR_Y_LOC_HI) << 8);
1206 return 0;
1207 }
1208
1209 int
1210 rt_setspritepos (gp, pos)
1211 struct grf_softc *gp;
1212 struct grf_position *pos;
1213 {
1214 volatile unsigned char *ba;
1215
1216 ba = gp->g_regkva;
1217 vgaw (ba, SEQ_ID_CURSOR_X_LOC_LO, pos->x & 0xff);
1218 vgaw (ba, SEQ_ID_CURSOR_X_LOC_HI, (pos->x >> 8) & 0x07);
1219 vgaw (ba, SEQ_ID_CURSOR_Y_LOC_LO, pos->y & 0xff);
1220 vgaw (ba, SEQ_ID_CURSOR_Y_LOC_HI, (pos->y >> 8) & 0x07);
1221 return 0;
1222 }
1223
1224 /* assume an at least 2M retina (XXX), sprite is last in memory.
1225 According to the bogus docs, the cursor can be at most 128 lines
1226 in height, and the x-hostspot can be placed at most at pos 31,
1227 this gives width of a long */
1228 #define SPRITE_ADDR (2*1024*1024 - 128*4)
1229
1230 int
1231 rt_getspriteinfo (gp, info)
1232 struct grf_softc *gp;
1233 struct grf_spriteinfo *info;
1234 {
1235 volatile unsigned char *ba, *fb;
1236
1237 ba = gp->g_regkva;
1238 fb = gp->g_fbkva;
1239 if (info->set & GRFSPRSET_ENABLE)
1240 info->enable = vgar (ba, SEQ_ID_CURSOR_CONTROL) & 0x01;
1241 if (info->set & GRFSPRSET_POS)
1242 rt_getspritepos (gp, &info->pos);
1243 if (info->set & GRFSPRSET_HOT)
1244 {
1245 info->hot.x = vgar (ba, SEQ_ID_CURSOR_X_INDEX) & 0x1f;
1246 info->hot.y = vgar (ba, SEQ_ID_CURSOR_Y_INDEX) & 0x7f;
1247 }
1248 if (info->set & GRFSPRSET_CMAP)
1249 {
1250 struct grf_colormap cmap;
1251 int index;
1252 cmap.index = 0;
1253 cmap.count = 256;
1254 rt_getcmap (gp, &cmap);
1255 index = vgar (ba, SEQ_ID_CURSOR_COLOR0);
1256 info->cmap.red[0] = cmap.red[index];
1257 info->cmap.green[0] = cmap.green[index];
1258 info->cmap.blue[0] = cmap.blue[index];
1259 index = vgar (ba, SEQ_ID_CURSOR_COLOR1);
1260 info->cmap.red[1] = cmap.red[index];
1261 info->cmap.green[1] = cmap.green[index];
1262 info->cmap.blue[1] = cmap.blue[index];
1263 }
1264 if (info->set & GRFSPRSET_SHAPE)
1265 {
1266 int saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
1267 int saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
1268 int last_bank = SPRITE_ADDR >> 6;
1269 int last_bank_lo = last_bank & 0xff;
1270 int last_bank_hi = last_bank >> 8;
1271 u_char mask;
1272 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, last_bank_lo);
1273 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, last_bank_hi);
1274 copyout (fb, info->image, 128*4);
1275 mask = RSeq (ba, SEQ_ID_CURSOR_PIXELMASK);
1276 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, saved_bank_lo);
1277 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, saved_bank_hi);
1278 copyout (&mask, info->mask, 1);
1279 info->size.x = 32; /* ??? */
1280 info->size.y = (RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 6) << 4;
1281 }
1282
1283 }
1284
1285 int
1286 rt_setspriteinfo (gp, info)
1287 struct grf_softc *gp;
1288 struct grf_spriteinfo *info;
1289 {
1290 volatile unsigned char *ba, *fb;
1291 u_char control;
1292
1293 ba = gp->g_regkva;
1294 fb = gp->g_fbkva;
1295 control = vgar (ba, SEQ_ID_CURSOR_CONTROL);
1296 if (info->set & GRFSPRSET_ENABLE)
1297 {
1298 if (info->enable)
1299 control |= 1;
1300 else
1301 control &= ~1;
1302 vgaw (ba, SEQ_ID_CURSOR_CONTROL, control);
1303 }
1304 if (info->set & GRFSPRSET_POS)
1305 rt_setspritepos (gp, &info->pos);
1306 if (info->set & GRFSPRSET_HOT)
1307 {
1308 vgaw (ba, SEQ_ID_CURSOR_X_INDEX, info->hot.x & 0x1f);
1309 vgaw (ba, SEQ_ID_CURSOR_Y_INDEX, info->hot.y & 0x7f);
1310 }
1311 if (info->set & GRFSPRSET_CMAP)
1312 {
1313 /* hey cheat a bit here.. XXX */
1314 vgaw (ba, SEQ_ID_CURSOR_COLOR0, 0);
1315 vgaw (ba, SEQ_ID_CURSOR_COLOR1, 1);
1316 }
1317 if (info->set & GRFSPRSET_SHAPE)
1318 {
1319 int saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
1320 int saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
1321 int last_bank = SPRITE_ADDR >> 6;
1322 int last_bank_lo = last_bank & 0xff;
1323 int last_bank_hi = last_bank >> 8;
1324 u_char mask;
1325 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, last_bank_lo);
1326 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, last_bank_hi);
1327 copyin (info->image, fb, 128*4);
1328 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, saved_bank_lo);
1329 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, saved_bank_hi);
1330 copyin (info->mask, &mask, 1);
1331 WSeq (ba, SEQ_ID_CURSOR_PIXELMASK, mask);
1332 /* info->size.x = 32; *//* ??? */
1333
1334 info->size.y = (RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 6) << 4;
1335 control = (control & ~6) | ((info->size.y >> 4) & 6);
1336 vgaw (ba, SEQ_ID_CURSOR_CONTROL, control);
1337
1338 /* sick intel bull-addressing.. */
1339 WSeq (ba, SEQ_ID_CURSOR_STORE_LO, SPRITE_ADDR & 0x0f);
1340 WSeq (ba, SEQ_ID_CURSOR_STORE_HI, 0);
1341 WSeq (ba, SEQ_ID_CURSOR_ST_OFF_LO, (SPRITE_ADDR >> 4) & 0xff);
1342 WSeq (ba, SEQ_ID_CURSOR_ST_OFF_HI, ((SPRITE_ADDR >> 4) >> 8) & 0xff);
1343 }
1344
1345 return 0;
1346 }
1347
1348 int
1349 rt_getspritemax (gp, pos)
1350 struct grf_softc *gp;
1351 struct grf_position *pos;
1352 {
1353 pos->x = 32;
1354 pos->y = 128;
1355
1356 return 0;
1357 }
1358
1359
1360 /*
1361 * !!! THIS AREA UNDER CONSTRUCTION !!!
1362 */
1363
1364 int
1365 rt_bitblt (gp, bb)
1366 struct grf_softc *gp;
1367 struct grf_bitblt *bb;
1368 {
1369 return EINVAL;
1370
1371
1372 #if 0
1373 volatile unsigned char *ba, *fb;
1374 u_char control;
1375 u_char saved_bank_lo;
1376 u_char saved_bank_hi;
1377 u_char src_bank_lo, src_bank_hi;
1378 u_char dst_bank_lo, dst_bank_hi;
1379 u_long src_offset, dst_offset;
1380 u_short src_bank, dst_bank;
1381 u_char *srcp, *dstp;
1382 short x, y;
1383 u_long tot;
1384
1385 ba = gp->g_regkva;
1386 fb = gp->g_fbkva;
1387
1388 saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
1389 saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
1390
1391 /* for now, only GRFBBcopy is supported, and only for depth 8. No
1392 clipping is performed, either... */
1393
1394 if (bb->op != GRFBBcopy && gp->g_display.gd_planes != 8)
1395 return EINVAL;
1396
1397 src_offset = op->src_x + op->src_y * gp->g_display.gd_fbwidth;
1398 dst_offset = op->dst_x + op->dst_y * gp->g_display.gd_fbwidth;
1399 tot = op->w * op->h;
1400
1401 /* set write mode 1, "[...] data in the read latches is written
1402 to memory during CPU memory write cycles. [...]" */
1403 WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 1);
1404 /* write to primary, read from secondary */
1405 WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, (RSeq(ba, SEQ_ID_EXTENDED_MEM_ENA) & 0x1f) | 0 );
1406
1407 if (src_offset < dst_offset)
1408 {
1409 /* start at end */
1410 src_offset += tot;
1411 dst_offset += tot;
1412 }
1413
1414 src_bank_lo = (src_offset >> 6) & 0xff;
1415 src_bank_hi = (src_offset >> 14) & 0xff;
1416 dst_bank_lo = (dst_offset >> 6) & 0xff;
1417 dst_bank_hi = (dst_offset >> 14) & 0xff;
1418
1419 while (tot)
1420 {
1421 WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, src_bank_lo);
1422 WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, src_bank_hi);
1423 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, dst_bank_lo);
1424 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, dst_bank_hi);
1425
1426 if (src_offset < dst_offset)
1427 {
1428
1429
1430 }
1431 else
1432 {
1433
1434 }
1435 }
1436
1437
1438 #endif
1439 }
1440
1441
1442 #endif /* NGRF */
1443