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