grf_rt.c revision 1.23 1 /* $NetBSD: grf_rt.c,v 1.23 1996/01/28 19:19:12 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
905 /*
906 * From observation of the monitor definition table above, I guess that
907 * the horizontal timings are in units of longwords. Hence, I get the
908 * pixels by multiplication with 32 and division by the depth.
909 * The text modes, apparently marked by depth == 4, are even more wierd.
910 * According to a comment above, they are computed from a depth==8 mode
911 * (thats for us: * 32 / 8) by applying another factor of 4 / font width.
912 * Reverse applying the latter formula most of the constants cancel
913 * themselves and we are left with a nice (* font width).
914 * That is, internal timings are in units of longwords for graphics
915 * modes, or in units of characters widths for text modes.
916 * We better don't WRITE modes until this has been real live checked.
917 * - Ignatios Souvatzis
918 */
919
920 if (md->DEP == 4) {
921 vm->hblank_start = md->HBS * 32 / md->DEP;
922 vm->hblank_stop = md->HBE * 32 / md->DEP;
923 vm->hsync_start = md->HSS * 32 / md->DEP;
924 vm->hsync_stop = md->HSE * 32 / md->DEP;
925 vm->htotal = md->HT * 32 / md->DEP;
926 } else {
927 vm->hblank_start = md->HBS * md->FX;
928 vm->hblank_stop = md->HBE * md->FX;
929 vm->hsync_start = md->HSS * md->FX;
930 vm->hsync_stop = md->HSE * md->FX;
931 vm->htotal = md->HT * md->FX;
932 }
933 vm->vblank_start = md->VBS;
934 vm->vblank_stop = md->VBE;
935 vm->vsync_start = md->VSS;
936 vm->vsync_stop = md->VSE;
937 vm->vtotal = md->VT;
938
939 return 0;
940 }
941
942
943 static int
944 rt_setvmode (gp, mode, txtonly)
945 struct grf_softc *gp;
946 unsigned mode;
947 int txtonly;
948 {
949 struct MonDef *md;
950 int error;
951
952 if (!mode || mode > retina_mon_max)
953 return EINVAL;
954
955 if (txtonly && monitor_defs[mode-1].DEP == 8)
956 return EINVAL;
957
958 current_mon = monitor_defs + (mode - 1);
959
960 error = rt_load_mon (gp, current_mon) ? 0 : EINVAL;
961
962 return error;
963 }
964
965
966 /*
967 * Change the mode of the display.
968 * Return a UNIX error number or 0 for success.
969 */
970 int
971 rt_mode(gp, cmd, arg, a2, a3)
972 struct grf_softc *gp;
973 int cmd;
974 void *arg;
975 int a2, a3;
976 {
977 /* implement these later... */
978
979 switch (cmd)
980 {
981 case GM_GRFON:
982 rt_setvmode (gp, retina_default_gfx + 1, 0);
983 return 0;
984
985 case GM_GRFOFF:
986 rt_setvmode (gp, retina_default_mon + 1, 0);
987 return 0;
988
989 case GM_GRFCONFIG:
990 return 0;
991
992 case GM_GRFGETVMODE:
993 return rt_getvmode (gp, (struct grfvideo_mode *) arg);
994
995 case GM_GRFSETVMODE:
996 return rt_setvmode (gp, *(unsigned *) arg, 1);
997
998 case GM_GRFGETNUMVM:
999 *(int *)arg = retina_mon_max;
1000 return 0;
1001
1002 #ifdef BANKEDDEVPAGER
1003 case GM_GRFGETBANK:
1004 *(int *)arg = rt_getbank (gp, a2, a3);
1005 return 0;
1006
1007 case GM_GRFGETCURBANK:
1008 *(int *)arg = rt_getcurbank (gp);
1009 return 0;
1010
1011 case GM_GRFSETBANK:
1012 return rt_setbank (gp, arg);
1013 #endif
1014 case GM_GRFIOCTL:
1015 return rt_ioctl (gp, (u_long)arg, (void *)a2);
1016
1017 default:
1018 break;
1019 }
1020
1021 return EINVAL;
1022 }
1023
1024 int
1025 rt_ioctl (gp, cmd, data)
1026 register struct grf_softc *gp;
1027 u_long cmd;
1028 void *data;
1029 {
1030 switch (cmd)
1031 {
1032 case GRFIOCGSPRITEPOS:
1033 return rt_getspritepos (gp, (struct grf_position *) data);
1034
1035 case GRFIOCSSPRITEPOS:
1036 return rt_setspritepos (gp, (struct grf_position *) data);
1037
1038 case GRFIOCSSPRITEINF:
1039 return rt_setspriteinfo (gp, (struct grf_spriteinfo *) data);
1040
1041 case GRFIOCGSPRITEINF:
1042 return rt_getspriteinfo (gp, (struct grf_spriteinfo *) data);
1043
1044 case GRFIOCGSPRITEMAX:
1045 return rt_getspritemax (gp, (struct grf_position *) data);
1046
1047 case GRFIOCGETCMAP:
1048 return rt_getcmap (gp, (struct grf_colormap *) data);
1049
1050 case GRFIOCPUTCMAP:
1051 return rt_putcmap (gp, (struct grf_colormap *) data);
1052
1053 case GRFIOCBITBLT:
1054 return rt_bitblt (gp, (struct grf_bitblt *) data);
1055 }
1056
1057 return EINVAL;
1058 }
1059
1060 #ifdef BANKEDDEVPAGER
1061
1062 /* Retina banks can overlap. Don't use this information (yet?), and
1063 only switch 64k sized banks. */
1064
1065 int
1066 rt_getbank (gp, offs, prot)
1067 struct grf_softc *gp;
1068 off_t offs;
1069 int prot;
1070 {
1071 /* XXX */
1072 if (offs < 0 || offs >= 4*1024*1024)
1073 return -1;
1074 else
1075 return offs >> 16;
1076 }
1077
1078 int
1079 rt_getcurbank (gp)
1080 struct grf_softc *gp;
1081 {
1082 struct grfinfo *gi = &gp->g_display;
1083 volatile unsigned char *ba;
1084 int bank;
1085
1086 ba = gp->g_regkva;
1087 bank = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO) | (RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI) << 8);
1088
1089 /* bank register is multiple of 64 byte, make this multiple of 64k */
1090 bank >>= 10;
1091 return bank;
1092 }
1093
1094 int
1095 rt_setbank (gp, bank)
1096 struct grf_softc *gp;
1097 int bank;
1098 {
1099 volatile unsigned char *ba;
1100
1101 ba = gp->g_regkva;
1102 /* bank register is multiple of 64 byte, make this multiple of 64k */
1103 bank <<= 10;
1104 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, (unsigned char) bank);
1105 bank >>= 8;
1106 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, (unsigned char) bank);
1107
1108 return 0;
1109 }
1110
1111 #endif
1112
1113 int
1114 rt_getcmap (gfp, cmap)
1115 struct grf_softc *gfp;
1116 struct grf_colormap *cmap;
1117 {
1118 volatile unsigned char *ba;
1119 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
1120 short x;
1121 int error;
1122
1123 if (cmap->count == 0 || cmap->index >= 256)
1124 return 0;
1125
1126 if (cmap->index + cmap->count > 256)
1127 cmap->count = 256 - cmap->index;
1128
1129 ba = gfp->g_regkva;
1130 /* first read colors out of the chip, then copyout to userspace */
1131 vgaw (ba, VDAC_REG_SELECT, cmap->index);
1132 x = cmap->count - 1;
1133 rp = red + cmap->index;
1134 gp = green + cmap->index;
1135 bp = blue + cmap->index;
1136 do
1137 {
1138 *rp++ = vgar (ba, VDAC_REG_DATA);
1139 *gp++ = vgar (ba, VDAC_REG_DATA);
1140 *bp++ = vgar (ba, VDAC_REG_DATA);
1141 }
1142 while (x--);
1143
1144 if (!(error = copyout (red + cmap->index, cmap->red, cmap->count))
1145 && !(error = copyout (green + cmap->index, cmap->green, cmap->count))
1146 && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count)))
1147 return 0;
1148
1149 return error;
1150 }
1151
1152 int
1153 rt_putcmap (gfp, cmap)
1154 struct grf_softc *gfp;
1155 struct grf_colormap *cmap;
1156 {
1157 volatile unsigned char *ba;
1158 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
1159 short x;
1160 int error;
1161
1162 if (cmap->count == 0 || cmap->index >= 256)
1163 return 0;
1164
1165 if (cmap->index + cmap->count > 256)
1166 cmap->count = 256 - cmap->index;
1167
1168 /* first copy the colors into kernelspace */
1169 if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
1170 && !(error = copyin (cmap->green, green + cmap->index, cmap->count))
1171 && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count)))
1172 {
1173 ba = gfp->g_regkva;
1174 vgaw (ba, VDAC_REG_SELECT, cmap->index);
1175 x = cmap->count - 1;
1176 rp = red + cmap->index;
1177 gp = green + cmap->index;
1178 bp = blue + cmap->index;
1179 do
1180 {
1181 vgaw (ba, VDAC_REG_DATA, *rp++);
1182 vgaw (ba, VDAC_REG_DATA, *gp++);
1183 vgaw (ba, VDAC_REG_DATA, *bp++);
1184 }
1185 while (x--);
1186 return 0;
1187 }
1188 else
1189 return error;
1190 }
1191
1192 int
1193 rt_getspritepos (gp, pos)
1194 struct grf_softc *gp;
1195 struct grf_position *pos;
1196 {
1197 volatile unsigned char *ba;
1198
1199 ba = gp->g_regkva;
1200 pos->x = vgar (ba, SEQ_ID_CURSOR_X_LOC_LO) | (vgar (ba, SEQ_ID_CURSOR_X_LOC_HI) << 8);
1201 pos->y = vgar (ba, SEQ_ID_CURSOR_Y_LOC_LO) | (vgar (ba, SEQ_ID_CURSOR_Y_LOC_HI) << 8);
1202 return 0;
1203 }
1204
1205 int
1206 rt_setspritepos (gp, pos)
1207 struct grf_softc *gp;
1208 struct grf_position *pos;
1209 {
1210 volatile unsigned char *ba;
1211
1212 ba = gp->g_regkva;
1213 vgaw (ba, SEQ_ID_CURSOR_X_LOC_LO, pos->x & 0xff);
1214 vgaw (ba, SEQ_ID_CURSOR_X_LOC_HI, (pos->x >> 8) & 0x07);
1215 vgaw (ba, SEQ_ID_CURSOR_Y_LOC_LO, pos->y & 0xff);
1216 vgaw (ba, SEQ_ID_CURSOR_Y_LOC_HI, (pos->y >> 8) & 0x07);
1217 return 0;
1218 }
1219
1220 /* assume an at least 2M retina (XXX), sprite is last in memory.
1221 According to the bogus docs, the cursor can be at most 128 lines
1222 in height, and the x-hostspot can be placed at most at pos 31,
1223 this gives width of a long */
1224 #define SPRITE_ADDR (2*1024*1024 - 128*4)
1225
1226 int
1227 rt_getspriteinfo (gp, info)
1228 struct grf_softc *gp;
1229 struct grf_spriteinfo *info;
1230 {
1231 volatile unsigned char *ba, *fb;
1232
1233 ba = gp->g_regkva;
1234 fb = gp->g_fbkva;
1235 if (info->set & GRFSPRSET_ENABLE)
1236 info->enable = vgar (ba, SEQ_ID_CURSOR_CONTROL) & 0x01;
1237 if (info->set & GRFSPRSET_POS)
1238 rt_getspritepos (gp, &info->pos);
1239 if (info->set & GRFSPRSET_HOT)
1240 {
1241 info->hot.x = vgar (ba, SEQ_ID_CURSOR_X_INDEX) & 0x1f;
1242 info->hot.y = vgar (ba, SEQ_ID_CURSOR_Y_INDEX) & 0x7f;
1243 }
1244 if (info->set & GRFSPRSET_CMAP)
1245 {
1246 struct grf_colormap cmap;
1247 int index;
1248 cmap.index = 0;
1249 cmap.count = 256;
1250 rt_getcmap (gp, &cmap);
1251 index = vgar (ba, SEQ_ID_CURSOR_COLOR0);
1252 info->cmap.red[0] = cmap.red[index];
1253 info->cmap.green[0] = cmap.green[index];
1254 info->cmap.blue[0] = cmap.blue[index];
1255 index = vgar (ba, SEQ_ID_CURSOR_COLOR1);
1256 info->cmap.red[1] = cmap.red[index];
1257 info->cmap.green[1] = cmap.green[index];
1258 info->cmap.blue[1] = cmap.blue[index];
1259 }
1260 if (info->set & GRFSPRSET_SHAPE)
1261 {
1262 int saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
1263 int saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
1264 int last_bank = SPRITE_ADDR >> 6;
1265 int last_bank_lo = last_bank & 0xff;
1266 int last_bank_hi = last_bank >> 8;
1267 u_char mask;
1268 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, last_bank_lo);
1269 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, last_bank_hi);
1270 copyout (fb, info->image, 128*4);
1271 mask = RSeq (ba, SEQ_ID_CURSOR_PIXELMASK);
1272 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, saved_bank_lo);
1273 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, saved_bank_hi);
1274 copyout (&mask, info->mask, 1);
1275 info->size.x = 32; /* ??? */
1276 info->size.y = (RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 6) << 4;
1277 }
1278
1279 }
1280
1281 int
1282 rt_setspriteinfo (gp, info)
1283 struct grf_softc *gp;
1284 struct grf_spriteinfo *info;
1285 {
1286 volatile unsigned char *ba, *fb;
1287 u_char control;
1288
1289 ba = gp->g_regkva;
1290 fb = gp->g_fbkva;
1291 control = vgar (ba, SEQ_ID_CURSOR_CONTROL);
1292 if (info->set & GRFSPRSET_ENABLE)
1293 {
1294 if (info->enable)
1295 control |= 1;
1296 else
1297 control &= ~1;
1298 vgaw (ba, SEQ_ID_CURSOR_CONTROL, control);
1299 }
1300 if (info->set & GRFSPRSET_POS)
1301 rt_setspritepos (gp, &info->pos);
1302 if (info->set & GRFSPRSET_HOT)
1303 {
1304 vgaw (ba, SEQ_ID_CURSOR_X_INDEX, info->hot.x & 0x1f);
1305 vgaw (ba, SEQ_ID_CURSOR_Y_INDEX, info->hot.y & 0x7f);
1306 }
1307 if (info->set & GRFSPRSET_CMAP)
1308 {
1309 /* hey cheat a bit here.. XXX */
1310 vgaw (ba, SEQ_ID_CURSOR_COLOR0, 0);
1311 vgaw (ba, SEQ_ID_CURSOR_COLOR1, 1);
1312 }
1313 if (info->set & GRFSPRSET_SHAPE)
1314 {
1315 int saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
1316 int saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
1317 int last_bank = SPRITE_ADDR >> 6;
1318 int last_bank_lo = last_bank & 0xff;
1319 int last_bank_hi = last_bank >> 8;
1320 u_char mask;
1321 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, last_bank_lo);
1322 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, last_bank_hi);
1323 copyin (info->image, fb, 128*4);
1324 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, saved_bank_lo);
1325 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, saved_bank_hi);
1326 copyin (info->mask, &mask, 1);
1327 WSeq (ba, SEQ_ID_CURSOR_PIXELMASK, mask);
1328 /* info->size.x = 32; *//* ??? */
1329
1330 info->size.y = (RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 6) << 4;
1331 control = (control & ~6) | ((info->size.y >> 4) & 6);
1332 vgaw (ba, SEQ_ID_CURSOR_CONTROL, control);
1333
1334 /* sick intel bull-addressing.. */
1335 WSeq (ba, SEQ_ID_CURSOR_STORE_LO, SPRITE_ADDR & 0x0f);
1336 WSeq (ba, SEQ_ID_CURSOR_STORE_HI, 0);
1337 WSeq (ba, SEQ_ID_CURSOR_ST_OFF_LO, (SPRITE_ADDR >> 4) & 0xff);
1338 WSeq (ba, SEQ_ID_CURSOR_ST_OFF_HI, ((SPRITE_ADDR >> 4) >> 8) & 0xff);
1339 }
1340
1341 return 0;
1342 }
1343
1344 int
1345 rt_getspritemax (gp, pos)
1346 struct grf_softc *gp;
1347 struct grf_position *pos;
1348 {
1349 pos->x = 32;
1350 pos->y = 128;
1351
1352 return 0;
1353 }
1354
1355
1356 /*
1357 * !!! THIS AREA UNDER CONSTRUCTION !!!
1358 */
1359
1360 int
1361 rt_bitblt (gp, bb)
1362 struct grf_softc *gp;
1363 struct grf_bitblt *bb;
1364 {
1365 return EINVAL;
1366
1367
1368 #if 0
1369 volatile unsigned char *ba, *fb;
1370 u_char control;
1371 u_char saved_bank_lo;
1372 u_char saved_bank_hi;
1373 u_char src_bank_lo, src_bank_hi;
1374 u_char dst_bank_lo, dst_bank_hi;
1375 u_long src_offset, dst_offset;
1376 u_short src_bank, dst_bank;
1377 u_char *srcp, *dstp;
1378 short x, y;
1379 u_long tot;
1380
1381 ba = gp->g_regkva;
1382 fb = gp->g_fbkva;
1383
1384 saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
1385 saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
1386
1387 /* for now, only GRFBBcopy is supported, and only for depth 8. No
1388 clipping is performed, either... */
1389
1390 if (bb->op != GRFBBcopy && gp->g_display.gd_planes != 8)
1391 return EINVAL;
1392
1393 src_offset = op->src_x + op->src_y * gp->g_display.gd_fbwidth;
1394 dst_offset = op->dst_x + op->dst_y * gp->g_display.gd_fbwidth;
1395 tot = op->w * op->h;
1396
1397 /* set write mode 1, "[...] data in the read latches is written
1398 to memory during CPU memory write cycles. [...]" */
1399 WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 1);
1400 /* write to primary, read from secondary */
1401 WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, (RSeq(ba, SEQ_ID_EXTENDED_MEM_ENA) & 0x1f) | 0 );
1402
1403 if (src_offset < dst_offset)
1404 {
1405 /* start at end */
1406 src_offset += tot;
1407 dst_offset += tot;
1408 }
1409
1410 src_bank_lo = (src_offset >> 6) & 0xff;
1411 src_bank_hi = (src_offset >> 14) & 0xff;
1412 dst_bank_lo = (dst_offset >> 6) & 0xff;
1413 dst_bank_hi = (dst_offset >> 14) & 0xff;
1414
1415 while (tot)
1416 {
1417 WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, src_bank_lo);
1418 WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, src_bank_hi);
1419 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, dst_bank_lo);
1420 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, dst_bank_hi);
1421
1422 if (src_offset < dst_offset)
1423 {
1424
1425
1426 }
1427 else
1428 {
1429
1430 }
1431 }
1432
1433
1434 #endif
1435 }
1436
1437
1438 #endif /* NGRF */
1439