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