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