grf_rt.c revision 1.10 1 /*
2 * $Id: grf_rt.c,v 1.10 1994/04/26 03:48:08 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 retina_inited = rt_load_mon(gp, current_mon);
731 return(retina_inited); /* XXX Markus maybe you */
732 /* XXX can make this cleaner. */
733 }
734
735 static int
736 rt_getvmode (gp, vm)
737 struct grf_softc *gp;
738 struct grfvideo_mode *vm;
739 {
740 struct MonDef *md;
741
742 if (vm->mode_num && vm->mode_num > retina_mon_max)
743 return EINVAL;
744
745 if (! vm->mode_num)
746 vm->mode_num = (current_mon - monitor_defs) + 1;
747
748 md = monitor_defs + (vm->mode_num - 1);
749 strncpy (vm->mode_descr, monitor_descr + (vm->mode_num - 1),
750 sizeof (vm->mode_descr));
751 vm->pixel_clock = md->FQ;
752 vm->disp_width = md->MW;
753 vm->disp_height = md->MH;
754 vm->depth = md->DEP;
755 vm->hblank_start = md->HBS;
756 vm->hblank_stop = md->HBE;
757 vm->hsync_start = md->HSS;
758 vm->hsync_stop = md->HSE;
759 vm->htotal = md->HT;
760 vm->vblank_start = md->VBS;
761 vm->vblank_stop = md->VBE;
762 vm->vsync_start = md->VSS;
763 vm->vsync_stop = md->VSE;
764 vm->vtotal = md->VT;
765
766 return 0;
767 }
768
769
770 static int
771 rt_setvmode (gp, mode, txtonly)
772 struct grf_softc *gp;
773 unsigned mode;
774 int txtonly;
775 {
776 struct MonDef *md;
777 int error;
778
779 if (!mode || mode > retina_mon_max)
780 return EINVAL;
781
782 if (txtonly && monitor_defs[mode-1].DEP == 8)
783 return EINVAL;
784
785 current_mon = monitor_defs + (mode - 1);
786
787 error = rt_load_mon (gp, current_mon) ? 0 : EINVAL;
788
789 return error;
790 }
791
792
793 /*
794 * Change the mode of the display.
795 * Return a UNIX error number or 0 for success.
796 */
797 rt_mode(gp, cmd, arg, a2, a3)
798 register struct grf_softc *gp;
799 int cmd;
800 void *arg;
801 int a2, a3;
802 {
803 /* implement these later... */
804
805 switch (cmd)
806 {
807 case GM_GRFON:
808 rt_setvmode (gp, retina_default_gfx + 1, 0);
809 return 0;
810
811 case GM_GRFOFF:
812 rt_setvmode (gp, retina_default_mon + 1, 0);
813 return 0;
814
815 case GM_GRFCONFIG:
816 return 0;
817
818 case GM_GRFGETVMODE:
819 return rt_getvmode (gp, (struct grfvideo_mode *) arg);
820
821 case GM_GRFSETVMODE:
822 return rt_setvmode (gp, *(unsigned *) arg, 1);
823
824 case GM_GRFGETNUMVM:
825 *(int *)arg = retina_mon_max;
826 return 0;
827
828 #ifdef BANKEDDEVPAGER
829 case GM_GRFGETBANK:
830 *(int *)arg = rt_getbank (gp, a2, a3);
831 return 0;
832
833 case GM_GRFGETCURBANK:
834 *(int *)arg = rt_getcurbank (gp);
835 return 0;
836
837 case GM_GRFSETBANK:
838 return rt_setbank (gp, arg);
839 #endif
840 case GM_GRFIOCTL:
841 return rt_ioctl (gp, arg, a2);
842
843 default:
844 break;
845 }
846
847 return EINVAL;
848 }
849
850 int
851 rt_ioctl (gp, cmd, data)
852 register struct grf_softc *gp;
853 int cmd;
854 void *data;
855 {
856 switch (cmd)
857 {
858 case GRFIOCGSPRITEPOS:
859 return rt_getspritepos (gp, (struct grf_position *) data);
860
861 case GRFIOCSSPRITEPOS:
862 return rt_setspritepos (gp, (struct grf_position *) data);
863
864 case GRFIOCSSPRITEINF:
865 return rt_setspriteinfo (gp, (struct grf_spriteinfo *) data);
866
867 case GRFIOCGSPRITEINF:
868 return rt_getspriteinfo (gp, (struct grf_spriteinfo *) data);
869
870 case GRFIOCGSPRITEMAX:
871 return rt_getspritemax (gp, (struct grf_position *) data);
872
873 case GRFIOCGETCMAP:
874 return rt_getcmap (gp, (struct grf_colormap *) data);
875
876 case GRFIOCPUTCMAP:
877 return rt_putcmap (gp, (struct grf_colormap *) data);
878
879 case GRFIOCBITBLT:
880 return rt_bitblt (gp, (struct grf_bitblt *) data);
881 }
882
883 return EINVAL;
884 }
885
886 #ifdef BANKEDDEVPAGER
887
888 /* Retina banks can overlap. Don't use this information (yet?), and
889 only switch 64k sized banks. */
890
891 int
892 rt_getbank (gp, offs, prot)
893 struct grf_softc *gp;
894 off_t offs;
895 int prot;
896 {
897 /* XXX */
898 if (offs < 0 || offs >= 4*1024*1024)
899 return -1;
900 else
901 return offs >> 16;
902 }
903
904 int
905 rt_getcurbank (gp)
906 struct grf_softc *gp;
907 {
908 struct grfinfo *gi = &gp->g_display;
909 volatile unsigned char *ba;
910 int bank;
911
912 ba = gp->g_regkva;
913 bank = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO) | (RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI) << 8);
914
915 /* bank register is multiple of 64 byte, make this multiple of 64k */
916 bank >>= 10;
917 return bank;
918 }
919
920 int
921 rt_setbank (gp, bank)
922 struct grf_softc *gp;
923 int bank;
924 {
925 volatile unsigned char *ba;
926
927 ba = gp->g_regkva;
928 /* bank register is multiple of 64 byte, make this multiple of 64k */
929 bank <<= 10;
930 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, (unsigned char) bank);
931 bank >>= 8;
932 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, (unsigned char) bank);
933
934 return 0;
935 }
936
937 #endif
938
939 int
940 rt_getcmap (gfp, cmap)
941 struct grf_softc *gfp;
942 struct grf_colormap *cmap;
943 {
944 volatile unsigned char *ba;
945 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
946 short x;
947 int error;
948
949 if (cmap->count == 0 || cmap->index >= 256)
950 return 0;
951
952 if (cmap->index + cmap->count > 256)
953 cmap->count = 256 - cmap->index;
954
955 ba = gfp->g_regkva;
956 /* first read colors out of the chip, then copyout to userspace */
957 vgaw (ba, VDAC_REG_SELECT, cmap->index);
958 x = cmap->count - 1;
959 rp = red + cmap->index;
960 gp = green + cmap->index;
961 bp = blue + cmap->index;
962 do
963 {
964 *rp++ = vgar (ba, VDAC_REG_DATA);
965 *gp++ = vgar (ba, VDAC_REG_DATA);
966 *bp++ = vgar (ba, VDAC_REG_DATA);
967 }
968 while (x--);
969
970 if (!(error = copyout (red + cmap->index, cmap->red, cmap->count))
971 && !(error = copyout (green + cmap->index, cmap->green, cmap->count))
972 && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count)))
973 return 0;
974
975 return error;
976 }
977
978 int
979 rt_putcmap (gfp, cmap)
980 struct grf_softc *gfp;
981 struct grf_colormap *cmap;
982 {
983 volatile unsigned char *ba;
984 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
985 short x;
986 int error;
987
988 if (cmap->count == 0 || cmap->index >= 256)
989 return 0;
990
991 if (cmap->index + cmap->count > 256)
992 cmap->count = 256 - cmap->index;
993
994 /* first copy the colors into kernelspace */
995 if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
996 && !(error = copyin (cmap->green, green + cmap->index, cmap->count))
997 && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count)))
998 {
999 ba = gfp->g_regkva;
1000 vgaw (ba, VDAC_REG_SELECT, cmap->index);
1001 x = cmap->count - 1;
1002 rp = red + cmap->index;
1003 gp = green + cmap->index;
1004 bp = blue + cmap->index;
1005 do
1006 {
1007 vgaw (ba, VDAC_REG_DATA, *rp++);
1008 vgaw (ba, VDAC_REG_DATA, *gp++);
1009 vgaw (ba, VDAC_REG_DATA, *bp++);
1010 }
1011 while (x--);
1012 return 0;
1013 }
1014 else
1015 return error;
1016 }
1017
1018 int
1019 rt_getspritepos (gp, pos)
1020 struct grf_softc *gp;
1021 struct grf_position *pos;
1022 {
1023 volatile unsigned char *ba;
1024
1025 ba = gp->g_regkva;
1026 pos->x = vgar (ba, SEQ_ID_CURSOR_X_LOC_LO) | (vgar (ba, SEQ_ID_CURSOR_X_LOC_HI) << 8);
1027 pos->y = vgar (ba, SEQ_ID_CURSOR_Y_LOC_LO) | (vgar (ba, SEQ_ID_CURSOR_Y_LOC_HI) << 8);
1028 return 0;
1029 }
1030
1031 int
1032 rt_setspritepos (gp, pos)
1033 struct grf_softc *gp;
1034 struct grf_position *pos;
1035 {
1036 volatile unsigned char *ba;
1037
1038 ba = gp->g_regkva;
1039 vgaw (ba, SEQ_ID_CURSOR_X_LOC_LO, pos->x & 0xff);
1040 vgaw (ba, SEQ_ID_CURSOR_X_LOC_HI, (pos->x >> 8) & 0x07);
1041 vgaw (ba, SEQ_ID_CURSOR_Y_LOC_LO, pos->y & 0xff);
1042 vgaw (ba, SEQ_ID_CURSOR_Y_LOC_HI, (pos->y >> 8) & 0x07);
1043 return 0;
1044 }
1045
1046 /* assume an at least 2M retina (XXX), sprite is last in memory.
1047 According to the bogus docs, the cursor can be at most 128 lines
1048 in height, and the x-hostspot can be placed at most at pos 31,
1049 this gives width of a long */
1050 #define SPRITE_ADDR (2*1024*1024 - 128*4)
1051
1052 int
1053 rt_getspriteinfo (gp, info)
1054 struct grf_softc *gp;
1055 struct grf_spriteinfo *info;
1056 {
1057 volatile unsigned char *ba, *fb;
1058
1059 ba = gp->g_regkva;
1060 fb = gp->g_fbkva;
1061 if (info->set & GRFSPRSET_ENABLE)
1062 info->enable = vgar (ba, SEQ_ID_CURSOR_CONTROL) & 0x01;
1063 if (info->set & GRFSPRSET_POS)
1064 rt_getspritepos (gp, &info->pos);
1065 if (info->set & GRFSPRSET_HOT)
1066 {
1067 info->hot.x = vgar (ba, SEQ_ID_CURSOR_X_INDEX) & 0x1f;
1068 info->hot.y = vgar (ba, SEQ_ID_CURSOR_Y_INDEX) & 0x7f;
1069 }
1070 if (info->set & GRFSPRSET_CMAP)
1071 {
1072 struct grf_colormap cmap;
1073 int index;
1074 cmap.index = 0;
1075 cmap.count = 256;
1076 rt_getcmap (gp, &cmap);
1077 index = vgar (ba, SEQ_ID_CURSOR_COLOR0);
1078 info->cmap.red[0] = cmap.red[index];
1079 info->cmap.green[0] = cmap.green[index];
1080 info->cmap.blue[0] = cmap.blue[index];
1081 index = vgar (ba, SEQ_ID_CURSOR_COLOR1);
1082 info->cmap.red[1] = cmap.red[index];
1083 info->cmap.green[1] = cmap.green[index];
1084 info->cmap.blue[1] = cmap.blue[index];
1085 }
1086 if (info->set & GRFSPRSET_SHAPE)
1087 {
1088 int saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
1089 int saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
1090 int last_bank = SPRITE_ADDR >> 6;
1091 int last_bank_lo = last_bank & 0xff;
1092 int last_bank_hi = last_bank >> 8;
1093 u_char mask;
1094 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, last_bank_lo);
1095 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, last_bank_hi);
1096 copyout (fb, info->image, 128*4);
1097 mask = RSeq (ba, SEQ_ID_CURSOR_PIXELMASK);
1098 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, saved_bank_lo);
1099 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, saved_bank_hi);
1100 copyout (&mask, info->mask, 1);
1101 info->size.x = 32; /* ??? */
1102 info->size.y = (RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 6) << 4;
1103 }
1104
1105 }
1106
1107 int
1108 rt_setspriteinfo (gp, info)
1109 struct grf_softc *gp;
1110 struct grf_spriteinfo *info;
1111 {
1112 volatile unsigned char *ba, *fb;
1113 u_char control;
1114
1115 ba = gp->g_regkva;
1116 fb = gp->g_fbkva;
1117 control = vgar (ba, SEQ_ID_CURSOR_CONTROL);
1118 if (info->set & GRFSPRSET_ENABLE)
1119 {
1120 if (info->enable)
1121 control |= 1;
1122 else
1123 control &= ~1;
1124 vgaw (ba, SEQ_ID_CURSOR_CONTROL, control);
1125 }
1126 if (info->set & GRFSPRSET_POS)
1127 rt_setspritepos (gp, &info->pos);
1128 if (info->set & GRFSPRSET_HOT)
1129 {
1130 vgaw (ba, SEQ_ID_CURSOR_X_INDEX, info->hot.x & 0x1f);
1131 vgaw (ba, SEQ_ID_CURSOR_Y_INDEX, info->hot.y & 0x7f);
1132 }
1133 if (info->set & GRFSPRSET_CMAP)
1134 {
1135 /* hey cheat a bit here.. XXX */
1136 vgaw (ba, SEQ_ID_CURSOR_COLOR0, 0);
1137 vgaw (ba, SEQ_ID_CURSOR_COLOR1, 1);
1138 }
1139 if (info->set & GRFSPRSET_SHAPE)
1140 {
1141 int saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
1142 int saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
1143 int last_bank = SPRITE_ADDR >> 6;
1144 int last_bank_lo = last_bank & 0xff;
1145 int last_bank_hi = last_bank >> 8;
1146 u_char mask;
1147 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, last_bank_lo);
1148 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, last_bank_hi);
1149 copyin (info->image, fb, 128*4);
1150 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, saved_bank_lo);
1151 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, saved_bank_hi);
1152 copyin (info->mask, &mask, 1);
1153 WSeq (ba, SEQ_ID_CURSOR_PIXELMASK, mask);
1154 /* info->size.x = 32; *//* ??? */
1155
1156 info->size.y = (RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 6) << 4;
1157 control = (control & ~6) | ((info->size.y >> 4) & 6);
1158 vgaw (ba, SEQ_ID_CURSOR_CONTROL, control);
1159
1160 /* sick intel bull-addressing.. */
1161 WSeq (ba, SEQ_ID_CURSOR_STORE_LO, SPRITE_ADDR & 0x0f);
1162 WSeq (ba, SEQ_ID_CURSOR_STORE_HI, 0);
1163 WSeq (ba, SEQ_ID_CURSOR_ST_OFF_LO, (SPRITE_ADDR >> 4) & 0xff);
1164 WSeq (ba, SEQ_ID_CURSOR_ST_OFF_HI, ((SPRITE_ADDR >> 4) >> 8) & 0xff);
1165 }
1166
1167 return 0;
1168 }
1169
1170 int
1171 rt_getspritemax (gp, pos)
1172 struct grf_softc *gp;
1173 struct grf_position *pos;
1174 {
1175 pos->x = 32;
1176 pos->y = 128;
1177
1178 return 0;
1179 }
1180
1181
1182 /*
1183 * !!! THIS AREA UNDER CONSTRUCTION !!!
1184 */
1185
1186 int
1187 rt_bitblt (gp, bb)
1188 struct grf_softc *gp;
1189 struct grf_bitblt *bb;
1190 {
1191 return EINVAL;
1192
1193
1194 #if 0
1195 volatile unsigned char *ba, *fb;
1196 u_char control;
1197 u_char saved_bank_lo;
1198 u_char saved_bank_hi;
1199 u_char src_bank_lo, src_bank_hi;
1200 u_char dst_bank_lo, dst_bank_hi;
1201 u_long src_offset, dst_offset;
1202 u_short src_bank, dst_bank;
1203 u_char *srcp, *dstp;
1204 short x, y;
1205 u_long tot;
1206
1207 ba = gp->g_regkva;
1208 fb = gp->g_fbkva;
1209
1210 saved_bank_lo = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO);
1211 saved_bank_hi = RSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI);
1212
1213 /* for now, only GRFBBcopy is supported, and only for depth 8. No
1214 clipping is performed, either... */
1215
1216 if (bb->op != GRFBBcopy && gp->g_display.gd_planes != 8)
1217 return EINVAL;
1218
1219 src_offset = op->src_x + op->src_y * gp->g_display.gd_fbwidth;
1220 dst_offset = op->dst_x + op->dst_y * gp->g_display.gd_fbwidth;
1221 tot = op->w * op->h;
1222
1223 /* set write mode 1, "[...] data in the read latches is written
1224 to memory during CPU memory write cycles. [...]" */
1225 WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 1);
1226 /* write to primary, read from secondary */
1227 WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, (RSeq(ba, SEQ_ID_EXTENDED_MEM_ENA) & 0x1f) | 0 );
1228
1229 if (src_offset < dst_offset)
1230 {
1231 /* start at end */
1232 src_offset += tot;
1233 dst_offset += tot;
1234 }
1235
1236 src_bank_lo = (src_offset >> 6) & 0xff;
1237 src_bank_hi = (src_offset >> 14) & 0xff;
1238 dst_bank_lo = (dst_offset >> 6) & 0xff;
1239 dst_bank_hi = (dst_offset >> 14) & 0xff;
1240
1241 while (tot)
1242 {
1243 WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, src_bank_lo);
1244 WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, src_bank_hi);
1245 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, dst_bank_lo);
1246 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, dst_bank_hi);
1247
1248 if (src_offset < dst_offset)
1249 {
1250
1251
1252 }
1253 else
1254 {
1255
1256 }
1257 }
1258
1259
1260 #endif
1261 }
1262
1263
1264 #endif /* NGRF */
1265