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