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