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