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