grf_rt.c revision 1.3 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 "grfioctl.h"
10 #include "grfvar.h"
11 #include "grf_rtreg.h"
12 #include "../include/cpu.h"
13 #include "device.h"
14
15 extern caddr_t ZORRO2ADDR;
16
17 /* NOTE: this driver for the MacroSystem Retina board was only possible,
18 because MacroSystem provided information about the pecularities
19 of the board. THANKS! Competition in Europe among gfx board
20 manufacturers is rather tough, so Lutz Vieweg, who wrote the
21 initial driver, has made an agreement with MS not to document
22 the driver source (see also his Copyright disclaimer below).
23 -> ALL comments after
24 -> "/* -------------- START OF CODE -------------- * /"
25 -> have been added by myself (mw) from studying the publically
26 -> available "NCR 77C22E+" Data Manual
27
28 Lutz' original driver source (without any of my comments) is
29 available on request. */
30
31
32 /* This code offers low-level routines to access the Retina graphics-board
33 manufactured by MS MacroSystem GmbH from within NetBSD for the Amiga.
34 No warranties for any kind of function at all - this code may crash
35 your hardware and scratch your harddisk.
36 Use at your own risk.
37 Freely distributable.
38
39 Written by Lutz Vieweg 07/93
40
41 Thanks to MacroSystem for providing me with the neccessary information
42 to create theese routines. The sparse documentation of this code
43 results from the agreements between MS and me.
44 */
45
46 extern unsigned char kernel_font_width, kernel_font_height;
47 extern unsigned char kernel_font_lo, kernel_font_hi;
48 extern unsigned char kernel_font[];
49
50
51 #define MDF_DBL 1
52 #define MDF_LACE 2
53 #define MDF_CLKDIV2 4
54
55
56 /* standard-palette definition */
57
58 unsigned char NCRStdPalette[16*3] = {
59 /* R G B */
60 0, 0, 0,
61 192,192,192,
62 128, 0, 0,
63 0,128, 0,
64 0, 0,128,
65 128,128, 0,
66 0,128,128,
67 128, 0,128,
68 64, 64, 64, /* the higher 8 colors have more intensity for */
69 255,255,255, /* compatibility with standard attributes */
70 255, 0, 0,
71 0,255, 0,
72 0, 0,255,
73 255,255, 0,
74 0,255,255,
75 255, 0,255
76 };
77
78
79 /* The following structures are examples for monitor-definitions. To make one
80 of your own, first use "DefineMonitor" and create the 8-bit monitor-mode of
81 your dreams. Then save it, and make a structure from the values provided in
82 the file DefineMonitor stored - the labels in the comment above the
83 structure definition show where to put what value.
84
85 Then you'll need to adapt your monitor-definition to the font you want to
86 use. Be FX the width of the font, then the following modifications have to
87 be applied to your values:
88
89 HBS = (HBS * 4) / FX
90 HSS = (HSS * 4) / FX
91 HSE = (HSE * 4) / FX
92 HBE = (HBE * 4) / FX
93 HT = (HT * 4) / FX
94
95 Make sure your maximum width (MW) and height (MH) are even multiples of
96 the fonts' width and height.
97 */
98
99 #if 0
100 /* horizontal 31.5 kHz */
101
102 /* FQ FLG MW MH HBS HSS HSE HBE HT VBS VSS VSE VBE VT */
103 struct MonDef MON_640_512_60 = { 50000000, 28, 640, 512, 81, 86, 93, 98, 95, 513, 513, 521, 535, 535,
104 /* Depth, PAL, TX, TY, XY,FontX, FontY, FontData, FLo, Fhi */
105 4, NCRStdPalette, 80, 64, 5120, 8, 8, kernel_font, 32, 255};
106
107 /* horizontal 38kHz */
108
109 struct MonDef MON_768_600_60 = { 75000000, 28, 768, 600, 97, 99,107,120,117, 601, 615, 625, 638, 638,
110 4, NCRStdPalette, 96, 75, 7200, 8, 8, kernel_font, 32, 255};
111
112 /* horizontal 64kHz */
113
114 struct MonDef MON_768_600_80 = { 50000000, 24, 768, 600, 97,104,112,122,119, 601, 606, 616, 628, 628,
115 4, NCRStdPalette, 96, 75, 7200, 8, 8, kernel_font, 32, 255};
116
117 #if 0
118 struct MonDef MON_1024_768_80 = { 90000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804,
119 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255};
120 #else
121 struct MonDef MON_1024_768_80 = { 90000000, 0, 1024, 768, 257,258,278,321,320, 769, 770, 783, 804, 804,
122 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255};
123 #endif
124
125 struct MonDef MON_1024_1024_59= { 90000000, 24, 1024,1024, 129,130,141,173,170,1025,1059,1076,1087,1087,
126 4, NCRStdPalette,128, 128, 16384, 8, 8, kernel_font, 32, 255};
127
128 /* WARNING: THE FOLLOWING MONITOR MODES EXCEED THE 90-MHz LIMIT THE PROCESSOR
129 HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
130 MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)! */
131
132 struct MonDef MON_1280_1024_60= {110000000, 24, 1280,1024, 161,162,176,211,208,1025,1026,1043,1073,1073,
133 4, NCRStdPalette,160, 128, 20480, 8, 8, kernel_font, 32, 255};
134
135 /* horizontal 75kHz */
136
137 struct MonDef MON_1280_1024_69= {120000000, 24, 1280,1024, 161,162,175,200,197,1025,1026,1043,1073,1073,
138 4, NCRStdPalette,160, 128, 20480, 8, 8, kernel_font, 32, 255};
139
140 #else
141
142 struct MonDef monitor_defs[] = {
143 /* horizontal 31.5 kHz */
144
145 { 50000000, 28, 640, 512, 81, 86, 93, 98, 95, 513, 513, 521, 535, 535,
146 4, NCRStdPalette, 80, 64, 5120, 8, 8, kernel_font, 32, 255},
147
148 /* horizontal 38kHz */
149
150 { 75000000, 28, 768, 600, 97, 99,107,120,117, 601, 615, 625, 638, 638,
151 4, NCRStdPalette, 96, 75, 7200, 8, 8, kernel_font, 32, 255},
152
153 /* horizontal 64kHz */
154
155 { 50000000, 24, 768, 600, 97,104,112,122,119, 601, 606, 616, 628, 628,
156 4, NCRStdPalette, 96, 75, 7200, 8, 8, kernel_font, 32, 255},
157
158
159
160 { 90000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804,
161 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255},
162
163 { 100000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804,
164 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255},
165
166 { 110000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804,
167 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255},
168
169 { 120000000, 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 { 13000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804,
173 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255},
174
175 { 72000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804,
176 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255},
177
178 { 75000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804,
179 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255},
180
181
182
183
184 { 90000000, 24, 1024, 768, 129,130,139,161,160, 769, 770, 783, 804, 804,
185 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255},
186
187 { 90000000, 24, 1024,1024, 129,130,141,173,170,1025,1059,1076,1087,1087,
188 4, NCRStdPalette,128, 128, 16384, 8, 8, kernel_font, 32, 255},
189
190 /* WARNING: THE FOLLOWING MONITOR MODES EXCEED THE 90-MHz LIMIT THE PROCESSOR
191 HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
192 MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)! */
193
194 {110000000, 24, 1280,1024, 161,162,176,211,208,1025,1026,1043,1073,1073,
195 4, NCRStdPalette,160, 128, 20480, 8, 8, kernel_font, 32, 255},
196
197 /* horizontal 75kHz */
198
199 {120000000, 24, 1280,1024, 161,162,175,200,197,1025,1026,1043,1073,1073,
200 4, NCRStdPalette,160, 128, 20480, 8, 8, kernel_font, 32, 255},
201
202 };
203
204 static const char *monitor_descr[] = {
205 "80x64 (640x512) 31.5kHz",
206 "96x75 (768x600) 38kHz",
207 "96x75 (768x600) 64kHz",
208 "128x96 (1024x768) 64kHz",
209 "128x128 (1024x1024) 64kHz",
210 "160x128 (1280x1024) 64kHz ***EXCEEDS CHIP LIMIT!!!***",
211 "160x128 (1280x1024) 75kHz ***EXCEEDS CHIP LIMIT!!!***",
212 };
213
214 int retina_mon_max = sizeof (monitor_defs)/sizeof (monitor_defs[0]);
215
216 /* patchable */
217 int retina_default_mon = 2;
218
219 #endif
220
221
222 static struct MonDef *current_mon;
223
224 /* -------------- START OF CODE -------------- */
225
226
227 static const long FQTab[16] =
228 { 25175000, 28322000, 36000000, 65000000,
229 44900000, 50000000, 80000000, 75000000,
230 56644000, 63000000, 72000000, 130000000,
231 90000000, 100000000, 110000000, 120000000 };
232
233
234 /*--------------------------------------------------*/
235 /*--------------------------------------------------*/
236
237 #if 0
238 static struct MonDef *default_monitor = &DEFAULT_MONDEF;
239 #endif
240
241
242 static int rt_load_mon (struct grf_softc *gp, struct MonDef *md)
243 {
244 struct grfinfo *gi = &gp->g_display;
245 volatile unsigned char *ba;
246 volatile unsigned char *fb;
247 short FW, clksel, HDE, VDE;
248
249 for (clksel = 15; clksel; clksel--) {
250 if (FQTab[clksel] == md->FQ) break;
251 }
252 if (clksel < 0) return 0;
253
254 ba = gp->g_regkva;;
255 fb = gp->g_fbkva;
256
257 switch (md->FX) {
258 case 4:
259 FW = 0;
260 break;
261 case 7:
262 FW = 1;
263 break;
264 case 8:
265 FW = 2;
266 break;
267 case 9:
268 FW = 3;
269 break;
270 case 10:
271 FW = 4;
272 break;
273 case 11:
274 FW = 5;
275 break;
276 case 12:
277 FW = 6;
278 break;
279 case 13:
280 FW = 7;
281 break;
282 case 14:
283 FW = 8;
284 break;
285 case 15:
286 FW = 9;
287 break;
288 case 16:
289 FW = 11;
290 break;
291 default:
292 return 0;
293 break;
294 };
295
296 HDE = (md->MW+md->FX-1)/md->FX;
297 VDE = md->MH-1;
298
299 /* hmm... */
300 fb[0x8000] = 0;
301
302 /* enable extension registers */
303 WSeq (ba, SEQ_ID_EXTENDED_ENABLE, 0x05);
304
305 #if 0
306 /* program the clock oscillator */
307 vgaw (ba, GREG_MISC_OUTPUT_W, 0xe3 | ((clksel & 3) * 0x04));
308 vgaw (ba, GREG_FEATURE_CONTROL_W, 0x00);
309
310 /* XXXX according to the NCR specs, this register should be set to 1
311 XXXX before doing the MISC_OUTPUT setting and CLOCKING_MODE
312 XXXX setting. */
313 WSeq (ba, SEQ_ID_RESET, 0x03);
314
315 WSeq (ba, SEQ_ID_CLOCKING_MODE, 0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8));
316 WSeq (ba, SEQ_ID_MAP_MASK, 0x0f);
317 WSeq (ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
318 /* odd/even write select + extended memory */
319 WSeq (ba, SEQ_ID_MEMORY_MODE, 0x06);
320 /* XXXX I think this order of setting RESET is wrong... */
321 WSeq (ba, SEQ_ID_RESET, 0x01);
322 WSeq (ba, SEQ_ID_RESET, 0x03);
323 #else
324 WSeq (ba, SEQ_ID_RESET, 0x01);
325
326 /* set font width + rest of clocks */
327 WSeq (ba, SEQ_ID_EXT_CLOCK_MODE, 0x30 | (FW & 0x0f) | ((clksel & 4) / 4 * 0x40) );
328 /* another clock bit, plus hw stuff */
329 WSeq (ba, SEQ_ID_MISC_FEATURE_SEL, 0xf4 | (clksel & 8) );
330
331 /* program the clock oscillator */
332 vgaw (ba, GREG_MISC_OUTPUT_W, 0xe3 | ((clksel & 3) * 0x04));
333 vgaw (ba, GREG_FEATURE_CONTROL_W, 0x00);
334
335 WSeq (ba, SEQ_ID_CLOCKING_MODE, 0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8));
336 WSeq (ba, SEQ_ID_MAP_MASK, 0x0f);
337 WSeq (ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
338 /* odd/even write select + extended memory */
339 WSeq (ba, SEQ_ID_MEMORY_MODE, 0x06);
340 WSeq (ba, SEQ_ID_RESET, 0x03);
341 #endif
342
343 /* monochrome cursor */
344 WSeq (ba, SEQ_ID_CURSOR_CONTROL, 0x00);
345 /* bank0 */
346 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, 0x00);
347 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, 0x00);
348 WSeq (ba, 0x1a , 0x00); /* these are reserved, really set them to 0 ??? */
349 WSeq (ba, 0x1b , 0x00); /* these are reserved, really set them to 0 ??? */
350 /* bank0 */
351 WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, 0x00);
352 WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, 0x00);
353 /* 1M-chips + ena SEC + ena EMem + rw PrimA0/rw Sec/B0 */
354 WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, 0x3 | 0x4 | 0x10 | 0x40);
355 #if 0
356 /* set font width + rest of clocks */
357 WSeq (ba, SEQ_ID_EXT_CLOCK_MODE, 0x30 | (FW & 0x0f) | ((clksel & 4) / 4 * 0x40) );
358 #endif
359 /* no ext-chain4 + no host-addr-bit-16 */
360 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, 0x00);
361 /* no packed/nibble + no 256bit gfx format */
362 WSeq (ba, SEQ_ID_EXT_PIXEL_CNTL, 0x00);
363 /* AT-interface */
364 WSeq (ba, SEQ_ID_BUS_WIDTH_FEEDB, 0x06);
365 /* see fg/bg color expansion */
366 WSeq (ba, SEQ_ID_COLOR_EXP_WFG, 0x01);
367 WSeq (ba, SEQ_ID_COLOR_EXP_WBG, 0x00);
368 WSeq (ba, SEQ_ID_EXT_RW_CONTROL, 0x00);
369 #if 0
370 /* another clock bit, plus hw stuff */
371 WSeq (ba, SEQ_ID_MISC_FEATURE_SEL, 0xf4 | (clksel & 8) );
372 #endif
373 /* don't tristate PCLK and PIX */
374 WSeq (ba, SEQ_ID_COLOR_KEY_CNTL, 0x40 );
375 /* reset CRC circuit */
376 WSeq (ba, SEQ_ID_CRC_CONTROL, 0x00 );
377 /* set RAS/CAS swap */
378 WSeq (ba, SEQ_ID_PERF_SELECT, 0x20);
379
380 WCrt (ba, CRT_ID_END_VER_RETR, (md->VSE & 0xf ) | 0x20);
381 WCrt (ba, CRT_ID_HOR_TOTAL, md->HT & 0xff);
382 WCrt (ba, CRT_ID_HOR_DISP_ENA_END, (HDE-1) & 0xff);
383 WCrt (ba, CRT_ID_START_HOR_BLANK, md->HBS & 0xff);
384 WCrt (ba, CRT_ID_END_HOR_BLANK, (md->HBE & 0x1f) | 0x80);
385
386 WCrt (ba, CRT_ID_START_HOR_RETR, md->HSS & 0xff);
387 WCrt (ba, CRT_ID_END_HOR_RETR, (md->HSE & 0x1f) | ((md->HBE & 0x20)/ 0x20 * 0x80));
388 WCrt (ba, CRT_ID_VER_TOTAL, (md->VT & 0xff));
389 WCrt (ba, CRT_ID_OVERFLOW, (( (md->VSS & 0x200) / 0x200 * 0x80)
390 | ((VDE & 0x200) / 0x200 * 0x40)
391 | ((md->VT & 0x200) / 0x200 * 0x20)
392 | 0x10
393 | ((md->VBS & 0x100) / 0x100 * 8 )
394 | ((md->VSS & 0x100) / 0x100 * 4 )
395 | ((VDE & 0x100) / 0x100 * 2 )
396 | ((md->VT & 0x100) / 0x100 )));
397 WCrt (ba, CRT_ID_PRESET_ROW_SCAN, 0x00);
398
399 WCrt (ba, CRT_ID_MAX_SCAN_LINE, (( (md->FLG & MDF_DBL)/ MDF_DBL * 0x80)
400 | 0x40
401 | ((md->VBS & 0x200)/0x200 * 0x20)
402 | ((md->FY-1) & 0x1f)));
403
404 WCrt (ba, CRT_ID_CURSOR_START, (md->FY & 0x1f) - 2);
405 WCrt (ba, CRT_ID_CURSOR_END, (md->FY & 0x1f) - 1);
406
407 WCrt (ba, CRT_ID_START_ADDR_HIGH, 0x00);
408 WCrt (ba, CRT_ID_START_ADDR_LOW, 0x00);
409
410 WCrt (ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
411 WCrt (ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
412
413 WCrt (ba, CRT_ID_START_VER_RETR, md->VSS & 0xff);
414 WCrt (ba, CRT_ID_END_VER_RETR, (md->VSE & 0x0f) | 0x80 | 0x20);
415 WCrt (ba, CRT_ID_VER_DISP_ENA_END, VDE & 0xff);
416 WCrt (ba, CRT_ID_OFFSET, (HDE / 2) & 0xff);
417 WCrt (ba, CRT_ID_UNDERLINE_LOC, (md->FY-1) & 0x1f);
418 WCrt (ba, CRT_ID_START_VER_BLANK, md->VBS & 0xff);
419 WCrt (ba, CRT_ID_END_VER_BLANK, md->VBE & 0xff);
420 /* byte mode + wrap + select row scan counter + cms */
421 WCrt (ba, CRT_ID_MODE_CONTROL, 0xe3);
422 WCrt (ba, CRT_ID_LINE_COMPARE, 0xff);
423
424 /* enable extended end bits + those bits */
425 WCrt (ba, CRT_ID_EXT_HOR_TIMING1, ( 0x20
426 | ((md->FLG & MDF_LACE) / MDF_LACE * 0x10)
427 | ((md->HT & 0x100) / 0x100 * 0x01)
428 | (((HDE-1) & 0x100) / 0x100 * 0x02)
429 | ((md->HBS & 0x100) / 0x100 * 0x04)
430 | ((md->HSS & 0x100) / 0x100 * 0x08)));
431
432 WCrt (ba, CRT_ID_EXT_START_ADDR, (((HDE / 2) & 0x100)/0x100 * 16));
433
434 WCrt (ba, CRT_ID_EXT_HOR_TIMING2, ( ((md->HT & 0x200)/ 0x200 * 0x01)
435 | (((HDE-1) & 0x200)/ 0x200 * 0x02)
436 | ((md->HBS & 0x200)/ 0x200 * 0x04)
437 | ((md->HSS & 0x200)/ 0x200 * 0x08)
438 | ((md->HBE & 0xc0) / 0x40 * 0x10)
439 | ((md->HSE & 0x60) / 0x20 * 0x40)));
440
441 WCrt (ba, CRT_ID_EXT_VER_TIMING, ( ((md->VSE & 0x10) / 0x10 * 0x80)
442 | ((md->VBE & 0x300)/ 0x100 * 0x20)
443 | 0x10
444 | ((md->VSS & 0x400)/ 0x400 * 0x08)
445 | ((md->VBS & 0x400)/ 0x400 * 0x04)
446 | ((VDE & 0x400)/ 0x400 * 0x02)
447 | ((md->VT & 0x400)/ 0x400 * 0x01)));
448
449 WGfx (ba, GCT_ID_SET_RESET, 0x00);
450 WGfx (ba, GCT_ID_ENABLE_SET_RESET, 0x00);
451 WGfx (ba, GCT_ID_COLOR_COMPARE, 0x00);
452 WGfx (ba, GCT_ID_DATA_ROTATE, 0x00);
453 WGfx (ba, GCT_ID_READ_MAP_SELECT, 0x00);
454 WGfx (ba, GCT_ID_GRAPHICS_MODE, 0x00);
455 WGfx (ba, GCT_ID_MISC, 0x04);
456 WGfx (ba, GCT_ID_COLOR_XCARE, 0xff);
457 WGfx (ba, GCT_ID_BITMASK, 0xff);
458
459 /* reset the Attribute Controller flipflop */
460 vgar (ba, GREG_STATUS1_R);
461 WAttr (ba, ACT_ID_PALETTE0, 0x00);
462 WAttr (ba, ACT_ID_PALETTE1, 0x01);
463 WAttr (ba, ACT_ID_PALETTE2, 0x02);
464 WAttr (ba, ACT_ID_PALETTE3, 0x03);
465 WAttr (ba, ACT_ID_PALETTE4, 0x04);
466 WAttr (ba, ACT_ID_PALETTE5, 0x05);
467 WAttr (ba, ACT_ID_PALETTE6, 0x06);
468 WAttr (ba, ACT_ID_PALETTE7, 0x07);
469 WAttr (ba, ACT_ID_PALETTE8, 0x08);
470 WAttr (ba, ACT_ID_PALETTE9, 0x09);
471 WAttr (ba, ACT_ID_PALETTE10, 0x0a);
472 WAttr (ba, ACT_ID_PALETTE11, 0x0b);
473 WAttr (ba, ACT_ID_PALETTE12, 0x0c);
474 WAttr (ba, ACT_ID_PALETTE13, 0x0d);
475 WAttr (ba, ACT_ID_PALETTE14, 0x0e);
476 WAttr (ba, ACT_ID_PALETTE15, 0x0f);
477
478 vgar (ba, GREG_STATUS1_R);
479 WAttr (ba, ACT_ID_ATTR_MODE_CNTL, 0x08);
480
481 WAttr (ba, ACT_ID_OVERSCAN_COLOR, 0x00);
482 WAttr (ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
483 WAttr (ba, ACT_ID_HOR_PEL_PANNING, 0x00);
484 WAttr (ba, ACT_ID_COLOR_SELECT, 0x00);
485
486 vgar (ba, GREG_STATUS1_R);
487 /* I have *NO* idea what strobing reg-0x20 might do... */
488 vgaw (ba, ACT_ADDRESS_W, 0x20);
489
490 WCrt (ba, CRT_ID_MAX_SCAN_LINE, ( ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80)
491 | 0x40
492 | ((md->VBS & 0x200)/0x200 * 0x20)
493 | ((md->FY-1) & 0x1f)));
494
495
496 /* not it's time for guessing... */
497
498 vgaw (ba, VDAC_REG_D, 0x02);
499
500 /* if this does what I think it does, it selects DAC
501 register 0, and writes the palette in subsequent
502 registers, thus it works similar to the WD33C93
503 select/data mechanism */
504 vgaw (ba, VDAC_REG_SELECT, 0x00);
505
506 {
507
508 short x = 15;
509 const unsigned char * col = md->PAL;
510 do {
511
512 vgaw (ba, VDAC_REG_DATA, *col++);
513 vgaw (ba, VDAC_REG_DATA, *col++);
514 vgaw (ba, VDAC_REG_DATA, *col++);
515
516
517 } while (x--);
518
519 }
520
521
522 /* now load the font into maps 2 (and 3 for fonts wider than 8 pixels) */
523 {
524
525 /* first set the whole font memory to a test-pattern, so we
526 can see if something that shouldn't be drawn IS drawn.. */
527 {
528 unsigned char * c = fb;
529 long x;
530 Map(2);
531
532 for (x = 0; x < 65536; x++) {
533 *c++ = (x & 1)? 0xaa : 0x55;
534 }
535 }
536
537 {
538 unsigned char * c = fb;
539 long x;
540 Map(3);
541
542 for (x = 0; x < 65536; x++) {
543 *c++ = (x & 1)? 0xaa : 0x55;
544 }
545 }
546
547 {
548 /* ok, now position at first defined character, and
549 copy over the images */
550 unsigned char * c = fb + md->FLo * 32;
551 const unsigned char * f = md->FData;
552 unsigned short z;
553
554 Map(2);
555 for (z = md->FLo; z <= md->FHi; z++) {
556
557 short y = md->FY-1;
558 if (md->FX > 8){
559 do {
560 *c++ = *f;
561 f += 2;
562 } while (y--);
563 }
564 else {
565 do {
566 *c++ = *f++;
567 } while (y--);
568 }
569
570 c += 32-md->FY;
571
572 }
573
574 if (md->FX > 8) {
575 unsigned short z;
576
577 Map(3);
578 c = fb + md->FLo*32;
579 f = md->FData+1;
580 for (z = md->FLo; z <= md->FHi; z++) {
581
582 short y = md->FY-1;
583 do {
584 *c++ = *f;
585 f += 2;
586 } while (y--);
587
588 c += 32-md->FY;
589
590 }
591 }
592 }
593
594 }
595
596 /* select map 0 */
597 WGfx (ba, GCT_ID_READ_MAP_SELECT, 0);
598 /* allow writes into maps 0 and 1 */
599 WSeq (ba, SEQ_ID_MAP_MASK, 3);
600 /* select extended chain4 addressing:
601 !A0/!A1 map 0 character to be displayed
602 !A1/ A1 map 1 attribute of that character
603 A0/!A1 map 2 not used (masked out, ignored)
604 A0/ A1 map 3 not used (masked out, ignored) */
605 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) | 0x02);
606
607 {
608 /* position in display memory */
609 unsigned short * c = (unsigned short *) fb;
610
611 /* fill with blank, white on black */
612 const unsigned short fill_val = 0x2010;
613 short x = md->XY;
614 do {
615 *c = fill_val;
616 c += 2;
617 } while (x--);
618
619 /* I won't comment this :-)) */
620 c = (unsigned short *) fb;
621 c += (md->TX-6)*2;
622 {
623 unsigned short init_msg[6] = {0x520a, 0x450b, 0x540c, 0x490d, 0x4e0e, 0x410f};
624 unsigned short * f = init_msg;
625 x = 5;
626 do {
627 *c = *f++;
628 c += 2;
629 } while (x--);
630 }
631
632
633 }
634
635
636 gp->g_data = (caddr_t) md;
637 gi->gd_regaddr = (long)ba - (long)ZORRO2ADDR + (long)ZORRO2BASE;;
638 gi->gd_regsize = 64*1024;
639
640 gi->gd_fbaddr = (long)fb - (long)ZORRO2ADDR + (long)ZORRO2BASE;
641 gi->gd_fbsize = 64*1024; /* larger, but that's whats mappable */
642
643 gi->gd_colors = 1 << md->DEP;
644 gi->gd_planes = md->DEP;
645
646 gi->gd_fbwidth = md->MW;
647 gi->gd_fbheight = md->MH;
648 gi->gd_fbx = 0;
649 gi->gd_fby = 0;
650 gi->gd_dwidth = md->TX * md->FX;
651 gi->gd_dheight = md->TY * md->FY;
652 gi->gd_dx = 0;
653 gi->gd_dy = 0;
654
655 /* initialized, works, return 1 */
656 return 1;
657 }
658
659 int rt_init (struct grf_softc *gp, struct amiga_device *ad, struct amiga_hw *ahw)
660 {
661 /* if already initialized, fail */
662 if (gp->g_regkva)
663 return 0;
664
665 gp->g_regkva = ahw->hw_kva;
666 gp->g_fbkva = ahw->hw_kva + 64*1024;
667
668 /* don't let them patch it out of bounds */
669 if ((unsigned)retina_default_mon >= retina_mon_max)
670 retina_default_mon = 0;
671
672 current_mon = monitor_defs + retina_default_mon;
673
674 return rt_load_mon (gp, current_mon);
675 }
676
677 static int
678 rt_getvmode (gp, vm)
679 struct grf_softc *gp;
680 struct grfvideo_mode *vm;
681 {
682 struct MonDef *md;
683
684 if (vm->mode_num && vm->mode_num > retina_mon_max)
685 return EINVAL;
686
687 if (! vm->mode_num)
688 vm->mode_num = (current_mon - monitor_defs) + 1;
689
690 md = monitor_defs + (vm->mode_num - 1);
691 strncpy (vm->mode_descr, monitor_descr + (vm->mode_num - 1),
692 sizeof (vm->mode_descr));
693 vm->pixel_clock = md->FQ;
694 vm->disp_width = md->MW;
695 vm->disp_height = md->MH;
696 vm->depth = md->DEP;
697 vm->hblank_start = md->HBS;
698 vm->hblank_stop = md->HBE;
699 vm->hsync_start = md->HSS;
700 vm->hsync_stop = md->HSE;
701 vm->htotal = md->HT;
702 vm->vblank_start = md->VBS;
703 vm->vblank_stop = md->VBE;
704 vm->vsync_start = md->VSS;
705 vm->vsync_stop = md->VSE;
706 vm->vtotal = md->VT;
707
708 return 0;
709 }
710
711
712 static int
713 rt_setvmode (gp, mode)
714 struct grf_softc *gp;
715 unsigned mode;
716 {
717 struct MonDef *md;
718
719 if (!mode || mode > retina_mon_max)
720 return EINVAL;
721
722 current_mon = monitor_defs + (mode - 1);
723 return rt_load_mon (gp, current_mon) ? 0 : EINVAL;
724 }
725
726
727 /*
728 * Change the mode of the display.
729 * Right now all we can do is grfon/grfoff.
730 * Return a UNIX error number or 0 for success.
731 */
732 rt_mode(gp, cmd, arg)
733 register struct grf_softc *gp;
734 int cmd;
735 void *arg;
736 {
737 /* implement these later... */
738
739 switch (cmd)
740 {
741 case GM_GRFON:
742 return 0;
743
744 case GM_GRFOFF:
745 return 0;
746
747 case GM_GRFCONFIG:
748 return 0;
749
750 case GM_GRFGETVMODE:
751 return rt_getvmode (gp, (struct grfvideo_mode *) arg);
752
753 case GM_GRFSETVMODE:
754 return rt_setvmode (gp, *(unsigned *) arg);
755
756 case GM_GRFGETNUMVM:
757 *(int *)arg = retina_mon_max;
758 return 0;
759
760 default:
761 break;
762 }
763
764 return EINVAL;
765 }
766
767 #endif /* NGRF */
768