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