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