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