grf_rt.c revision 1.1.1.1 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 struct MonDef MON_1024_768_80 = { 90000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804,
118 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255};
119
120 struct MonDef MON_1024_1024_59= { 90000000, 24, 1024,1024, 129,130,141,173,170,1025,1059,1076,1087,1087,
121 4, NCRStdPalette,128, 128, 16384, 8, 8, kernel_font, 32, 255};
122
123 /* WARNING: THE FOLLOWING MONITOR MODES EXCEED THE 90-MHz LIMIT THE PROCESSOR
124 HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
125 MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)! */
126
127 struct MonDef MON_1280_1024_60= {110000000, 24, 1280,1024, 161,162,176,211,208,1025,1026,1043,1073,1073,
128 4, NCRStdPalette,160, 128, 20480, 8, 8, kernel_font, 32, 255};
129
130 /* horizontal 75kHz */
131
132 struct MonDef MON_1280_1024_69= {120000000, 24, 1280,1024, 161,162,175,200,197,1025,1026,1043,1073,1073,
133 4, NCRStdPalette,160, 128, 20480, 8, 8, kernel_font, 32, 255};
134
135 #else
136
137 struct MonDef monitor_defs[] = {
138 /* horizontal 31.5 kHz */
139
140 { 50000000, 28, 640, 512, 81, 86, 93, 98, 95, 513, 513, 521, 535, 535,
141 4, NCRStdPalette, 80, 64, 5120, 8, 8, kernel_font, 32, 255},
142
143 /* horizontal 38kHz */
144
145 { 75000000, 28, 768, 600, 97, 99,107,120,117, 601, 615, 625, 638, 638,
146 4, NCRStdPalette, 96, 75, 7200, 8, 8, kernel_font, 32, 255},
147
148 /* horizontal 64kHz */
149
150 { 50000000, 24, 768, 600, 97,104,112,122,119, 601, 606, 616, 628, 628,
151 4, NCRStdPalette, 96, 75, 7200, 8, 8, kernel_font, 32, 255},
152
153 { 90000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804,
154 4, NCRStdPalette,128, 96, 12288, 8, 8, kernel_font, 32, 255},
155
156 { 90000000, 24, 1024,1024, 129,130,141,173,170,1025,1059,1076,1087,1087,
157 4, NCRStdPalette,128, 128, 16384, 8, 8, kernel_font, 32, 255},
158
159 /* WARNING: THE FOLLOWING MONITOR MODES EXCEED THE 90-MHz LIMIT THE PROCESSOR
160 HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
161 MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)! */
162
163 {110000000, 24, 1280,1024, 161,162,176,211,208,1025,1026,1043,1073,1073,
164 4, NCRStdPalette,160, 128, 20480, 8, 8, kernel_font, 32, 255},
165
166 /* horizontal 75kHz */
167
168 {120000000, 24, 1280,1024, 161,162,175,200,197,1025,1026,1043,1073,1073,
169 4, NCRStdPalette,160, 128, 20480, 8, 8, kernel_font, 32, 255},
170
171 };
172
173 static const char *monitor_descr[] = {
174 "80x64 (640x512) 31.5kHz",
175 "96x75 (768x600) 38kHz",
176 "96x75 (768x600) 64kHz",
177 "128x96 (1024x768) 64kHz",
178 "128x128 (1024x1024) 64kHz",
179 "160x128 (1280x1024) 64kHz ***EXCEEDS CHIP LIMIT!!!***",
180 "160x128 (1280x1024) 75kHz ***EXCEEDS CHIP LIMIT!!!***",
181 };
182
183 int retina_mon_max = sizeof (monitor_defs)/sizeof (monitor_defs[0]);
184
185 /* patchable */
186 int retina_default_mon = 2;
187
188 #endif
189
190
191 static struct MonDef *current_mon;
192
193 /* -------------- START OF CODE -------------- */
194
195
196 static const long FQTab[16] =
197 { 25175000, 28322000, 36000000, 65000000,
198 44900000, 50000000, 80000000, 75000000,
199 56644000, 63000000, 72000000, 130000000,
200 90000000, 100000000, 110000000, 120000000 };
201
202
203 /*--------------------------------------------------*/
204 /*--------------------------------------------------*/
205
206 #if 0
207 static struct MonDef *default_monitor = &DEFAULT_MONDEF;
208 #endif
209
210
211 static int rt_load_mon (struct grf_softc *gp, struct MonDef *md)
212 {
213 struct grfinfo *gi = &gp->g_display;
214 volatile unsigned char *ba;
215 volatile unsigned char *fb;
216 short FW, clksel, HDE, VDE;
217
218 for (clksel = 15; clksel; clksel--) {
219 if (FQTab[clksel] == md->FQ) break;
220 }
221 if (clksel < 0) return 0;
222
223 ba = gp->g_regkva;;
224 fb = gp->g_fbkva;
225
226 switch (md->FX) {
227 case 4:
228 FW = 0;
229 break;
230 case 7:
231 FW = 1;
232 break;
233 case 8:
234 FW = 2;
235 break;
236 case 9:
237 FW = 3;
238 break;
239 case 10:
240 FW = 4;
241 break;
242 case 11:
243 FW = 5;
244 break;
245 case 12:
246 FW = 6;
247 break;
248 case 13:
249 FW = 7;
250 break;
251 case 14:
252 FW = 8;
253 break;
254 case 15:
255 FW = 9;
256 break;
257 case 16:
258 FW = 11;
259 break;
260 default:
261 return 0;
262 break;
263 };
264
265 HDE = (md->MW+md->FX-1)/md->FX;
266 VDE = md->MH-1;
267
268 /* hmm... */
269 fb[0x8000] = 0;
270
271 /* program the clock oscillator */
272 vgaw (ba, GREG_MISC_OUTPUT_W, 0xe3 | ((clksel & 3) * 0x04));
273 vgaw (ba, GREG_FEATURE_CONTROL_W, 0x00);
274
275 /* XXXX according to the NCR specs, this register should be set to 1
276 XXXX before doing the MISC_OUTPUT setting and CLOCKING_MODE
277 XXXX setting. */
278 WSeq (ba, SEQ_ID_RESET, 0x03);
279
280 WSeq (ba, SEQ_ID_CLOCKING_MODE, 0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8));
281 WSeq (ba, SEQ_ID_MAP_MASK, 0x0f);
282 WSeq (ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
283 /* odd/even write select + extended memory */
284 WSeq (ba, SEQ_ID_MEMORY_MODE, 0x06);
285 /* XXXX I think this order of setting RESET is wrong... */
286 WSeq (ba, SEQ_ID_RESET, 0x01);
287 WSeq (ba, SEQ_ID_RESET, 0x03);
288
289 /* enable extension registers *
290 WSeq (ba, SEQ_ID_EXTENDED_ENABLE, 0x05);
291 /* monochrome cursor */
292 WSeq (ba, SEQ_ID_CURSOR_CONTROL, 0x00);
293 /* bank0 */
294 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, 0x00);
295 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, 0x00);
296 WSeq (ba, 0x1a , 0x00); /* these are reserved, really set them to 0 ??? */
297 WSeq (ba, 0x1b , 0x00); /* these are reserved, really set them to 0 ??? */
298 /* bank0 */
299 WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, 0x00);
300 WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, 0x00);
301 /* 1M-chips + ena SEC + ena EMem + rw PrimA0/rw Sec/B0 */
302 WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, 0x3 | 0x4 | 0x10 | 0x40);
303 /* set font width + rest of clocks */
304 WSeq (ba, SEQ_ID_EXT_CLOCK_MODE, 0x30 | (FW & 0x0f) | ((clksel & 4) / 4 * 0x40) );
305 /* no ext-chain4 + no host-addr-bit-16 */
306 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, 0x00);
307 /* no packed/nibble + no 256bit gfx format */
308 WSeq (ba, SEQ_ID_EXT_PIXEL_CNTL, 0x00);
309 /* AT-interface */
310 WSeq (ba, SEQ_ID_BUS_WIDTH_FEEDB, 0x06);
311 /* see fg/bg color expansion */
312 WSeq (ba, SEQ_ID_COLOR_EXP_WFG, 0x01);
313 WSeq (ba, SEQ_ID_COLOR_EXP_WBG, 0x00);
314 WSeq (ba, SEQ_ID_EXT_RW_CONTROL, 0x00);
315 /* another clock bit, plus hw stuff */
316 WSeq (ba, SEQ_ID_MISC_FEATURE_SEL, 0xf4 | (clksel & 8) );
317 /* don't tristate PCLK and PIX */
318 WSeq (ba, SEQ_ID_COLOR_KEY_CNTL, 0x40 );
319 /* reset CRC circuit */
320 WSeq (ba, SEQ_ID_CRC_CONTROL, 0x00 );
321 /* set RAS/CAS swap */
322 WSeq (ba, SEQ_ID_PERF_SELECT, 0x20);
323
324 WCrt (ba, CRT_ID_END_VER_RETR, (md->VSE & 0xf ) | 0x20);
325 WCrt (ba, CRT_ID_HOR_TOTAL, md->HT & 0xff);
326 WCrt (ba, CRT_ID_HOR_DISP_ENA_END, (HDE-1) & 0xff);
327 WCrt (ba, CRT_ID_START_HOR_BLANK, md->HBS & 0xff);
328 WCrt (ba, CRT_ID_END_HOR_BLANK, (md->HBE & 0x1f) | 0x80);
329
330 WCrt (ba, CRT_ID_START_HOR_RETR, md->HSS & 0xff);
331 WCrt (ba, CRT_ID_END_HOR_RETR, (md->HSE & 0x1f) | ((md->HBE & 0x20)/ 0x20 * 0x80));
332 WCrt (ba, CRT_ID_VER_TOTAL, (md->VT & 0xff));
333 WCrt (ba, CRT_ID_OVERFLOW, (( (md->VSS & 0x200) / 0x200 * 0x80)
334 | ((VDE & 0x200) / 0x200 * 0x40)
335 | ((md->VT & 0x200) / 0x200 * 0x20)
336 | 0x10
337 | ((md->VBS & 0x100) / 0x100 * 8 )
338 | ((md->VSS & 0x100) / 0x100 * 4 )
339 | ((VDE & 0x100) / 0x100 * 2 )
340 | ((md->VT & 0x100) / 0x100 )));
341 WCrt (ba, CRT_ID_PRESET_ROW_SCAN, 0x00);
342
343 WCrt (ba, CRT_ID_MAX_SCAN_LINE, (( (md->FLG & MDF_DBL)/ MDF_DBL * 0x80)
344 | 0x40
345 | ((md->VBS & 0x200)/0x200 * 0x20)
346 | ((md->FY-1) & 0x1f)));
347
348 WCrt (ba, CRT_ID_CURSOR_START, (md->FY & 0x1f) - 2);
349 WCrt (ba, CRT_ID_CURSOR_END, (md->FY & 0x1f) - 1);
350
351 WCrt (ba, CRT_ID_START_ADDR_HIGH, 0x00);
352 WCrt (ba, CRT_ID_START_ADDR_LOW, 0x00);
353
354 WCrt (ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
355 WCrt (ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
356
357 WCrt (ba, CRT_ID_START_VER_RETR, md->VSS & 0xff);
358 WCrt (ba, CRT_ID_END_VER_RETR, (md->VSE & 0x0f) | 0x80 | 0x20);
359 WCrt (ba, CRT_ID_VER_DISP_ENA_END, VDE & 0xff);
360 WCrt (ba, CRT_ID_OFFSET, (HDE / 2) & 0xff);
361 WCrt (ba, CRT_ID_UNDERLINE_LOC, (md->FY-1) & 0x1f);
362 WCrt (ba, CRT_ID_START_VER_BLANK, md->VBS & 0xff);
363 WCrt (ba, CRT_ID_END_VER_BLANK, md->VBE & 0xff);
364 /* byte mode + wrap + select row scan counter + cms */
365 WCrt (ba, CRT_ID_MODE_CONTROL, 0xe3);
366 WCrt (ba, CRT_ID_LINE_COMPARE, 0xff);
367
368 /* enable extended end bits + those bits */
369 WCrt (ba, CRT_ID_EXT_HOR_TIMING1, ( 0x20
370 | ((md->FLG & MDF_LACE) / MDF_LACE * 0x10)
371 | ((md->HT & 0x100) / 0x100 * 0x01)
372 | (((HDE-1) & 0x100) / 0x100 * 0x02)
373 | ((md->HBS & 0x100) / 0x100 * 0x04)
374 | ((md->HSS & 0x100) / 0x100 * 0x08)));
375
376 WCrt (ba, CRT_ID_EXT_START_ADDR, (((HDE / 2) & 0x100)/0x100 * 16));
377
378 WCrt (ba, CRT_ID_EXT_HOR_TIMING2, ( ((md->HT & 0x200)/ 0x200 * 0x01)
379 | (((HDE-1) & 0x200)/ 0x200 * 0x02)
380 | ((md->HBS & 0x200)/ 0x200 * 0x04)
381 | ((md->HSS & 0x200)/ 0x200 * 0x08)
382 | ((md->HBE & 0xc0) / 0x40 * 0x10)
383 | ((md->HSE & 0x60) / 0x20 * 0x40)));
384
385 WCrt (ba, CRT_ID_EXT_VER_TIMING, ( ((md->VSE & 0x10) / 0x10 * 0x80)
386 | ((md->VBE & 0x300)/ 0x100 * 0x20)
387 | 0x10
388 | ((md->VSS & 0x400)/ 0x400 * 0x08)
389 | ((md->VBS & 0x400)/ 0x400 * 0x04)
390 | ((VDE & 0x400)/ 0x400 * 0x02)
391 | ((md->VT & 0x400)/ 0x400 * 0x01)));
392
393 WGfx (ba, GCT_ID_SET_RESET, 0x00);
394 WGfx (ba, GCT_ID_ENABLE_SET_RESET, 0x00);
395 WGfx (ba, GCT_ID_COLOR_COMPARE, 0x00);
396 WGfx (ba, GCT_ID_DATA_ROTATE, 0x00);
397 WGfx (ba, GCT_ID_READ_MAP_SELECT, 0x00);
398 WGfx (ba, GCT_ID_GRAPHICS_MODE, 0x00);
399 WGfx (ba, GCT_ID_MISC, 0x04);
400 WGfx (ba, GCT_ID_COLOR_XCARE, 0xff);
401 WGfx (ba, GCT_ID_BITMASK, 0xff);
402
403 /* reset the Attribute Controller flipflop */
404 vgar (ba, GREG_STATUS1_R);
405 WAttr (ba, ACT_ID_PALETTE0, 0x00);
406 WAttr (ba, ACT_ID_PALETTE1, 0x01);
407 WAttr (ba, ACT_ID_PALETTE2, 0x02);
408 WAttr (ba, ACT_ID_PALETTE3, 0x03);
409 WAttr (ba, ACT_ID_PALETTE4, 0x04);
410 WAttr (ba, ACT_ID_PALETTE5, 0x05);
411 WAttr (ba, ACT_ID_PALETTE6, 0x06);
412 WAttr (ba, ACT_ID_PALETTE7, 0x07);
413 WAttr (ba, ACT_ID_PALETTE8, 0x08);
414 WAttr (ba, ACT_ID_PALETTE9, 0x09);
415 WAttr (ba, ACT_ID_PALETTE10, 0x0a);
416 WAttr (ba, ACT_ID_PALETTE11, 0x0b);
417 WAttr (ba, ACT_ID_PALETTE12, 0x0c);
418 WAttr (ba, ACT_ID_PALETTE13, 0x0d);
419 WAttr (ba, ACT_ID_PALETTE14, 0x0e);
420 WAttr (ba, ACT_ID_PALETTE15, 0x0f);
421
422 vgar (ba, GREG_STATUS1_R);
423 WAttr (ba, ACT_ID_ATTR_MODE_CNTL, 0x08);
424
425 WAttr (ba, ACT_ID_OVERSCAN_COLOR, 0x00);
426 WAttr (ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
427 WAttr (ba, ACT_ID_HOR_PEL_PANNING, 0x00);
428 WAttr (ba, ACT_ID_COLOR_SELECT, 0x00);
429
430 vgar (ba, GREG_STATUS1_R);
431 /* I have *NO* idea what strobing reg-0x20 might do... */
432 vgaw (ba, ACT_ADDRESS_W, 0x20);
433
434 WCrt (ba, CRT_ID_MAX_SCAN_LINE, ( ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80)
435 | 0x40
436 | ((md->VBS & 0x200)/0x200 * 0x20)
437 | ((md->FY-1) & 0x1f)));
438
439
440 /* not it's time for guessing... */
441
442 vgaw (ba, VDAC_REG_D, 0x02);
443
444 /* if this does what I think it does, it selects DAC
445 register 0, and writes the palette in subsequent
446 registers, thus it works similar to the WD33C93
447 select/data mechanism */
448 vgaw (ba, VDAC_REG_SELECT, 0x00);
449
450 {
451
452 short x = 15;
453 const unsigned char * col = md->PAL;
454 do {
455
456 vgaw (ba, VDAC_REG_DATA, *col++);
457 vgaw (ba, VDAC_REG_DATA, *col++);
458 vgaw (ba, VDAC_REG_DATA, *col++);
459
460
461 } while (x--);
462
463 }
464
465
466 /* now load the font into maps 2 (and 3 for fonts wider than 8 pixels) */
467 {
468
469 /* first set the whole font memory to a test-pattern, so we
470 can see if something that shouldn't be drawn IS drawn.. */
471 {
472 unsigned char * c = fb;
473 long x;
474 Map(2);
475
476 for (x = 0; x < 65536; x++) {
477 *c++ = (x & 1)? 0xaa : 0x55;
478 }
479 }
480
481 {
482 unsigned char * c = fb;
483 long x;
484 Map(3);
485
486 for (x = 0; x < 65536; x++) {
487 *c++ = (x & 1)? 0xaa : 0x55;
488 }
489 }
490
491 {
492 /* ok, now position at first defined character, and
493 copy over the images */
494 unsigned char * c = fb + md->FLo * 32;
495 const unsigned char * f = md->FData;
496 unsigned short z;
497
498 Map(2);
499 for (z = md->FLo; z <= md->FHi; z++) {
500
501 short y = md->FY-1;
502 if (md->FX > 8){
503 do {
504 *c++ = *f;
505 f += 2;
506 } while (y--);
507 }
508 else {
509 do {
510 *c++ = *f++;
511 } while (y--);
512 }
513
514 c += 32-md->FY;
515
516 }
517
518 if (md->FX > 8) {
519 unsigned short z;
520
521 Map(3);
522 c = fb + md->FLo*32;
523 f = md->FData+1;
524 for (z = md->FLo; z <= md->FHi; z++) {
525
526 short y = md->FY-1;
527 do {
528 *c++ = *f;
529 f += 2;
530 } while (y--);
531
532 c += 32-md->FY;
533
534 }
535 }
536 }
537
538 }
539
540 /* select map 0 */
541 WGfx (ba, GCT_ID_READ_MAP_SELECT, 0);
542 /* allow writes into maps 0 and 1 */
543 WSeq (ba, SEQ_ID_MAP_MASK, 3);
544 /* select extended chain4 addressing:
545 !A0/!A1 map 0 character to be displayed
546 !A1/ A1 map 1 attribute of that character
547 A0/!A1 map 2 not used (masked out, ignored)
548 A0/ A1 map 3 not used (masked out, ignored) */
549 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) | 0x02);
550
551 {
552 /* position in display memory */
553 unsigned short * c = (unsigned short *) fb;
554
555 /* fill with blank, white on black */
556 const unsigned short fill_val = 0x2010;
557 short x = md->XY;
558 do {
559 *c = fill_val;
560 c += 2;
561 } while (x--);
562
563 /* I won't comment this :-)) */
564 c = (unsigned short *) fb;
565 c += (md->TX-6)*2;
566 {
567 unsigned short init_msg[6] = {0x520a, 0x450b, 0x540c, 0x490d, 0x4e0e, 0x410f};
568 unsigned short * f = init_msg;
569 x = 5;
570 do {
571 *c = *f++;
572 c += 2;
573 } while (x--);
574 }
575
576
577 }
578
579
580 gi->gd_regaddr = (caddr_t) md; /* XXX */
581 gi->gd_regsize = 0;
582
583 gi->gd_fbaddr = (long)fb - (long)ZORRO2ADDR + (long)ZORRO2BASE;
584 gi->gd_fbsize = 64*1024; /* larger, but that's whats mappable */
585
586 gi->gd_colors = 1 << md->DEP;
587 gi->gd_planes = md->DEP;
588
589 gi->gd_fbwidth = md->MW;
590 gi->gd_fbheight = md->MH;
591 gi->gd_fbx = 0;
592 gi->gd_fby = 0;
593 gi->gd_dwidth = md->TX * md->FX;
594 gi->gd_dheight = md->TY * md->FY;
595 gi->gd_dx = 0;
596 gi->gd_dy = 0;
597
598 /* initialized, works, return 1 */
599 return 1;
600 }
601
602 int rt_init (struct grf_softc *gp, struct amiga_device *ad, struct amiga_hw *ahw)
603 {
604 /* if already initialized, fail */
605 if (gp->g_regkva)
606 return 0;
607
608 gp->g_regkva = ahw->hw_kva;
609 gp->g_fbkva = ahw->hw_kva + 64*1024;
610
611 /* don't let them patch it out of bounds */
612 if ((unsigned)retina_default_mon >= retina_mon_max)
613 retina_default_mon = 0;
614
615 current_mon = monitor_defs + retina_default_mon;
616
617 return rt_load_mon (gp, current_mon);
618 }
619
620 static int
621 rt_getvmode (gp, vm)
622 struct grf_softc *gp;
623 struct grfvideo_mode *vm;
624 {
625 struct MonDef *md;
626
627 if (vm->mode_num && vm->mode_num > retina_mon_max)
628 return EINVAL;
629
630 if (! vm->mode_num)
631 vm->mode_num = (current_mon - monitor_defs) + 1;
632
633 md = monitor_defs + (vm->mode_num - 1);
634 strncpy (vm->mode_descr, monitor_descr + (vm->mode_num - 1),
635 sizeof (vm->mode_descr));
636 vm->pixel_clock = md->FQ;
637 vm->disp_width = md->MW;
638 vm->disp_height = md->MH;
639 vm->depth = md->DEP;
640 vm->hblank_start = md->HBS;
641 vm->hblank_stop = md->HBE;
642 vm->hsync_start = md->HSS;
643 vm->hsync_stop = md->HSE;
644 vm->htotal = md->HT;
645 vm->vblank_start = md->VBS;
646 vm->vblank_stop = md->VBE;
647 vm->vsync_start = md->VSS;
648 vm->vsync_stop = md->VSE;
649 vm->vtotal = md->VT;
650
651 return 0;
652 }
653
654
655 static int
656 rt_setvmode (gp, mode)
657 struct grf_softc *gp;
658 unsigned mode;
659 {
660 struct MonDef *md;
661
662 if (!mode || mode > retina_mon_max)
663 return EINVAL;
664
665 current_mon = monitor_defs + (mode - 1);
666 return rt_load_mon (gp, current_mon) ? 0 : EINVAL;
667 }
668
669
670 /*
671 * Change the mode of the display.
672 * Right now all we can do is grfon/grfoff.
673 * Return a UNIX error number or 0 for success.
674 */
675 rt_mode(gp, cmd, arg)
676 register struct grf_softc *gp;
677 int cmd;
678 void *arg;
679 {
680 /* implement these later... */
681
682 switch (cmd)
683 {
684 case GM_GRFON:
685 return 0;
686
687 case GM_GRFOFF:
688 return 0;
689
690 case GM_GRFCONFIG:
691 return 0;
692
693 case GM_GRFGETVMODE:
694 return rt_getvmode (gp, (struct grfvideo_mode *) arg);
695
696 case GM_GRFSETVMODE:
697 return rt_setvmode (gp, *(unsigned *) arg);
698
699 case GM_GRFGETNUMVM:
700 *(int *)arg = retina_mon_max;
701 return 0;
702
703 default:
704 break;
705 }
706
707 return EINVAL;
708 }
709
710 #endif /* NGRF */
711