1 /* $NetBSD: grf_rt.c,v 1.53 2009/03/18 17:06:42 cegger Exp $ */
4 * Copyright (c) 1993 Markus Wild
5 * Copyright (c) 1993 Lutz Vieweg
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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
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.
33 #include "opt_amigacons.h"
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: grf_rt.c,v 1.53 2009/03/18 17:06:42 cegger Exp $");
41 /* Graphics routines for the Retina board,
42 using the NCR 77C22E+ VGA controller. */
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/errno.h>
47 #include <sys/ioctl.h>
48 #include <sys/device.h>
49 #include <machine/cpu.h>
50 #include <amiga/amiga/device.h>
51 #include <amiga/dev/zbusvar.h>
52 #include <amiga/dev/grfioctl.h>
53 #include <amiga/dev/grfvar.h>
54 #include <amiga/dev/grf_rtreg.h>
56 int rt_ioctl(struct grf_softc
*gp
, u_long
, void *);
59 * marked true early so that retina_cnprobe() can tell if we are alive.
65 * This driver for the MacroSystem Retina board was only possible,
66 * because MacroSystem provided information about the pecularities
67 * of the board. THANKS! Competition in Europe among gfx board
68 * manufacturers is rather tough, so Lutz Vieweg, who wrote the
69 * initial driver, has made an agreement with MS not to document
70 * the driver source (see also his comment below).
71 * -> ALL comments after
72 * -> " -------------- START OF CODE -------------- "
73 * -> have been added by myself (mw) from studying the publically
74 * -> available "NCR 77C22E+" Data Manual
77 * This code offers low-level routines to access the Retina graphics-board
78 * manufactured by MS MacroSystem GmbH from within NetBSD for the Amiga.
80 * Thanks to MacroSystem for providing me with the necessary information
81 * to create theese routines. The sparse documentation of this code
82 * results from the agreements between MS and me.
85 extern unsigned char kernel_font_8x8_width
, kernel_font_8x8_height
;
86 extern unsigned char kernel_font_8x8_lo
, kernel_font_8x8_hi
;
87 extern unsigned char kernel_font_8x8
[];
95 /* standard-palette definition */
97 unsigned char NCRStdPalette
[16*3] = {
107 64, 64, 64, /* the higher 8 colors have more intensity for */
108 255,255,255, /* compatibility with standard attributes */
118 /* The following structures are examples for monitor-definitions. To make one
119 of your own, first use "DefineMonitor" and create the 8-bit monitor-mode of
120 your dreams. Then save it, and make a structure from the values provided in
121 the file DefineMonitor stored - the labels in the comment above the
122 structure definition show where to put what value.
124 Then you'll need to adapt your monitor-definition to the font you want to
125 use. Be FX the width of the font, then the following modifications have to
126 be applied to your values:
134 Make sure your maximum width (MW) and height (MH) are even multiples of
135 the fonts' width and height.
139 /* horizontal 31.5 kHz */
141 /* FQ FLG MW MH HBS HSS HSE HBE HT VBS VSS VSE VBE VT */
142 struct MonDef MON_640_512_60
= { 50000000, 28, 640, 512, 81, 86, 93, 98, 95, 513, 513, 521, 535, 535,
143 /* Depth, PAL, TX, TY, XY,FontX, FontY, FontData, FLo, Fhi */
144 4, NCRStdPalette
, 80, 64, 5120, 8, 8, kernel_font_8x8
, 32, 255};
146 struct MonDef MON_640_480_62_G
= { 50000000, 4, 640, 480, 161,171,184,196,195, 481, 484, 492, 502, 502,
147 8, NCRStdPalette
,640,480, 5120, 8, 8, kernel_font_8x8
, 32, 255};
148 /* Enter higher values here ^ ^ for panning! */
150 /* horizontal 38kHz */
152 struct MonDef MON_768_600_60
= { 75000000, 28, 768, 600, 97, 99,107,120,117, 601, 615, 625, 638, 638,
153 4, NCRStdPalette
, 96, 75, 7200, 8, 8, kernel_font_8x8
, 32, 255};
155 /* horizontal 64kHz */
157 struct MonDef MON_768_600_80
= { 50000000, 24, 768, 600, 97,104,112,122,119, 601, 606, 616, 628, 628,
158 4, NCRStdPalette
, 96, 75, 7200, 8, 8, kernel_font_8x8
, 32, 255};
160 struct MonDef MON_1024_768_80
= { 90000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804,
161 4, NCRStdPalette
,128, 96, 12288, 8, 8, kernel_font_8x8
, 32, 255};
163 /* FQ FLG MW MH HBS HSS HSE HBE HT VBS VSS VSE VBE VT */
164 struct MonDef MON_1024_768_80_G
= { 90000000, 0, 1024, 768, 257,258,280,344,343, 769, 770, 783, 804, 804,
165 8, NCRStdPalette
, 1024, 768, 12288, 8, 8, kernel_font_8x8
, 32, 255};
167 struct MonDef MON_1024_1024_59
= { 90000000, 24, 1024,1024, 129,130,141,173,170,1025,1059,1076,1087,1087,
168 4, NCRStdPalette
,128, 128, 16384, 8, 8, kernel_font_8x8
, 32, 255};
170 /* WARNING: THE FOLLOWING MONITOR MODES EXCEED THE 90-MHz LIMIT THE PROCESSOR
171 HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
172 MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)! */
174 struct MonDef MON_1280_1024_60
= {110000000, 24, 1280,1024, 161,162,176,211,208,1025,1026,1043,1073,1073,
175 4, NCRStdPalette
,160, 128, 20480, 8, 8, kernel_font_8x8
, 32, 255};
177 struct MonDef MON_1280_1024_60_G
= {110000000, 0, 1280,1024, 321,322,349,422,421,1025,1026,1043,1073,1073,
178 8, NCRStdPalette
,1280,1024, 20480, 8, 8, kernel_font_8x8
, 32, 255};
180 /* horizontal 75kHz */
182 struct MonDef MON_1280_1024_69
= {120000000, 24, 1280,1024, 161,162,175,200,197,1025,1026,1043,1073,1073,
183 4, NCRStdPalette
,160, 128, 20480, 8, 8, kernel_font_8x8
, 32, 255};
187 struct MonDef monitor_defs
[] = {
188 /* horizontal 31.5 kHz */
190 { 50000000, 28, 640, 512, 81, 86, 93, 98, 95, 513, 513, 521, 535, 535,
191 4, NCRStdPalette
, 80, 64, 5120, 8, 8, kernel_font_8x8
, 32, 255},
193 /* horizontal 38kHz */
195 { 75000000, 28, 768, 600, 97, 99,107,120,117, 601, 615, 625, 638, 638,
196 4, NCRStdPalette
, 96, 75, 7200, 8, 8, kernel_font_8x8
, 32, 255},
198 /* horizontal 64kHz */
200 { 50000000, 24, 768, 600, 97,104,112,122,119, 601, 606, 616, 628, 628,
201 4, NCRStdPalette
, 96, 75, 7200, 8, 8, kernel_font_8x8
, 32, 255},
203 { 90000000, 24, 1024, 768, 129,130,141,172,169, 769, 770, 783, 804, 804,
204 4, NCRStdPalette
,128, 96, 12288, 8, 8, kernel_font_8x8
, 32, 255},
208 /* horizontal 31.5 kHz */
210 { 50000000, 4, 640, 480, 161,171,184,196,195, 481, 484, 492, 502, 502,
211 8, NCRStdPalette
,640, 480, 5120, 8, 8, kernel_font_8x8
, 32, 255},
213 /* horizontal 64kHz */
215 { 90000000, 0, 1024, 768, 257,258,280,344,343, 769, 770, 783, 804, 804,
216 8, NCRStdPalette
, 1024, 768, 12288, 8, 8, kernel_font_8x8
, 32, 255},
218 /* WARNING: THE FOLLOWING MONITOR MODES EXCEED THE 90-MHz LIMIT THE PROCESSOR
219 HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
220 MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)! */
222 {110000000, 0, 1280,1024, 321,322,349,422,421,1025,1026,1043,1073,1073,
223 8, NCRStdPalette
,1280,1024, 20480, 8, 8, kernel_font_8x8
, 32, 255},
226 static const char *monitor_descr
[] = {
227 "80x64 (640x512) 31.5kHz",
228 "96x75 (768x600) 38kHz",
229 "96x75 (768x600) 64kHz",
230 "128x96 (1024x768) 64kHz",
232 "GFX (640x480) 31.5kHz",
233 "GFX (1024x768) 64kHz",
234 "GFX (1280x1024) 64kHz ***EXCEEDS CHIP LIMIT!!!***",
237 int retina_mon_max
= sizeof (monitor_defs
)/sizeof (monitor_defs
[0]);
240 int retina_default_mon
= 0;
241 int retina_default_gfx
= 4;
246 static struct MonDef
*current_mon
;
248 /* -------------- START OF CODE -------------- */
251 static const long FQTab
[16] =
252 { 25175000, 28322000, 36000000, 65000000,
253 44900000, 50000000, 80000000, 75000000,
254 56644000, 63000000, 72000000, 130000000,
255 90000000, 100000000, 110000000, 120000000 };
258 /*--------------------------------------------------*/
259 /*--------------------------------------------------*/
262 static struct MonDef
*default_monitor
= &DEFAULT_MONDEF
;
265 int retina_alive(struct MonDef
*);
266 static int rt_load_mon(struct grf_softc
*, struct MonDef
*);
270 * used to query the retina to see if its alive (?)
273 retina_alive(struct MonDef
*mdp
)
277 for (clksel
= 15; clksel
; clksel
--) {
278 if (FQTab
[clksel
] == mdp
->FQ
)
285 if (mdp
->FX
== 4 || (mdp
->FX
>= 7 && mdp
->FX
<= 16))
291 rt_load_mon(struct grf_softc
*gp
, struct MonDef
*md
)
293 struct grfinfo
*gi
= &gp
->g_display
;
296 short FW
, clksel
, HDE
, VDE
;
298 for (clksel
= 15; clksel
; clksel
--) {
299 if (FQTab
[clksel
] == md
->FQ
) break;
305 fb
= (volatile char*)gp
->g_fbkva
;
349 if (md
->DEP
== 4) HDE
= (md
->MW
+md
->FX
-1)/md
->FX
;
350 else HDE
= (md
->MW
+3)/4;
356 /* enable extension registers */
357 WSeq (ba
, SEQ_ID_EXTENDED_ENABLE
, 0x05);
360 /* program the clock oscillator */
361 vgaw (ba
, GREG_MISC_OUTPUT_W
, 0xe3 | ((clksel
& 3) * 0x04));
362 vgaw (ba
, GREG_FEATURE_CONTROL_W
, 0x00);
364 /* XXXX according to the NCR specs, this register should be set to 1
365 XXXX before doing the MISC_OUTPUT setting and CLOCKING_MODE
367 WSeq (ba
, SEQ_ID_RESET
, 0x03);
369 WSeq (ba
, SEQ_ID_CLOCKING_MODE
, 0x01 | ((md
->FLG
& MDF_CLKDIV2
)/ MDF_CLKDIV2
* 8));
370 WSeq (ba
, SEQ_ID_MAP_MASK
, 0x0f);
371 WSeq (ba
, SEQ_ID_CHAR_MAP_SELECT
, 0x00);
372 /* odd/even write select + extended memory */
373 WSeq (ba
, SEQ_ID_MEMORY_MODE
, 0x06);
374 /* XXXX I think this order of setting RESET is wrong... */
375 WSeq (ba
, SEQ_ID_RESET
, 0x01);
376 WSeq (ba
, SEQ_ID_RESET
, 0x03);
378 WSeq (ba
, SEQ_ID_RESET
, 0x01);
380 /* set font width + rest of clocks */
381 WSeq (ba
, SEQ_ID_EXT_CLOCK_MODE
, 0x30 | (FW
& 0x0f) | ((clksel
& 4) / 4 * 0x40) );
382 /* another clock bit, plus hw stuff */
383 WSeq (ba
, SEQ_ID_MISC_FEATURE_SEL
, 0xf4 | (clksel
& 8) );
385 /* program the clock oscillator */
386 vgaw (ba
, GREG_MISC_OUTPUT_W
, 0xe3 | ((clksel
& 3) * 0x04));
387 vgaw (ba
, GREG_FEATURE_CONTROL_W
, 0x00);
389 WSeq (ba
, SEQ_ID_CLOCKING_MODE
, 0x01 | ((md
->FLG
& MDF_CLKDIV2
)/ MDF_CLKDIV2
* 8));
390 WSeq (ba
, SEQ_ID_MAP_MASK
, 0x0f);
391 WSeq (ba
, SEQ_ID_CHAR_MAP_SELECT
, 0x00);
392 /* odd/even write select + extended memory */
393 WSeq (ba
, SEQ_ID_MEMORY_MODE
, 0x06);
394 WSeq (ba
, SEQ_ID_RESET
, 0x03);
397 /* monochrome cursor */
398 WSeq (ba
, SEQ_ID_CURSOR_CONTROL
, 0x00);
400 WSeq (ba
, SEQ_ID_PRIM_HOST_OFF_HI
, 0x00);
401 WSeq (ba
, SEQ_ID_PRIM_HOST_OFF_LO
, 0x00);
402 WSeq (ba
, SEQ_ID_DISP_OFF_HI
, 0x00);
403 WSeq (ba
, SEQ_ID_DISP_OFF_LO
, 0x00);
405 WSeq (ba
, SEQ_ID_SEC_HOST_OFF_HI
, 0x00);
406 WSeq (ba
, SEQ_ID_SEC_HOST_OFF_LO
, 0x00);
407 /* 1M-chips + ena SEC + ena EMem + rw PrimA0/rw Sec/B0 */
408 WSeq (ba
, SEQ_ID_EXTENDED_MEM_ENA
, 0x3 | 0x4 | 0x10 | 0x40);
410 /* set font width + rest of clocks */
411 WSeq (ba
, SEQ_ID_EXT_CLOCK_MODE
, 0x30 | (FW
& 0x0f) | ((clksel
& 4) / 4 * 0x40) );
414 /* no ext-chain4 + no host-addr-bit-16 */
415 WSeq (ba
, SEQ_ID_EXT_VIDEO_ADDR
, 0x00);
416 /* no packed/nibble + no 256bit gfx format */
417 WSeq (ba
, SEQ_ID_EXT_PIXEL_CNTL
, 0x00);
420 WSeq (ba
, SEQ_ID_EXT_VIDEO_ADDR
, 0x02);
421 /* 256bit gfx format */
422 WSeq (ba
, SEQ_ID_EXT_PIXEL_CNTL
, 0x01);
425 WSeq (ba
, SEQ_ID_BUS_WIDTH_FEEDB
, 0x06);
426 /* see fg/bg color expansion */
427 WSeq (ba
, SEQ_ID_COLOR_EXP_WFG
, 0x01);
428 WSeq (ba
, SEQ_ID_COLOR_EXP_WBG
, 0x00);
429 WSeq (ba
, SEQ_ID_EXT_RW_CONTROL
, 0x00);
431 /* another clock bit, plus hw stuff */
432 WSeq (ba
, SEQ_ID_MISC_FEATURE_SEL
, 0xf4 | (clksel
& 8) );
434 /* don't tristate PCLK and PIX */
435 WSeq (ba
, SEQ_ID_COLOR_KEY_CNTL
, 0x40 );
436 /* reset CRC circuit */
437 WSeq (ba
, SEQ_ID_CRC_CONTROL
, 0x00 );
438 /* set RAS/CAS swap */
439 WSeq (ba
, SEQ_ID_PERF_SELECT
, 0x20);
441 WCrt (ba
, CRT_ID_END_VER_RETR
, (md
->VSE
& 0xf ) | 0x20);
442 WCrt (ba
, CRT_ID_HOR_TOTAL
, md
->HT
& 0xff);
443 WCrt (ba
, CRT_ID_HOR_DISP_ENA_END
, (HDE
-1) & 0xff);
444 WCrt (ba
, CRT_ID_START_HOR_BLANK
, md
->HBS
& 0xff);
445 WCrt (ba
, CRT_ID_END_HOR_BLANK
, (md
->HBE
& 0x1f) | 0x80);
447 WCrt (ba
, CRT_ID_START_HOR_RETR
, md
->HSS
& 0xff);
448 WCrt (ba
, CRT_ID_END_HOR_RETR
, (md
->HSE
& 0x1f) | ((md
->HBE
& 0x20)/ 0x20 * 0x80));
449 WCrt (ba
, CRT_ID_VER_TOTAL
, (md
->VT
& 0xff));
450 WCrt (ba
, CRT_ID_OVERFLOW
, (( (md
->VSS
& 0x200) / 0x200 * 0x80)
451 | ((VDE
& 0x200) / 0x200 * 0x40)
452 | ((md
->VT
& 0x200) / 0x200 * 0x20)
454 | ((md
->VBS
& 0x100) / 0x100 * 8 )
455 | ((md
->VSS
& 0x100) / 0x100 * 4 )
456 | ((VDE
& 0x100) / 0x100 * 2 )
457 | ((md
->VT
& 0x100) / 0x100 )));
458 WCrt (ba
, CRT_ID_PRESET_ROW_SCAN
, 0x00);
461 WCrt (ba
, CRT_ID_MAX_SCAN_LINE
, (( (md
->FLG
& MDF_DBL
)/ MDF_DBL
* 0x80)
463 | ((md
->VBS
& 0x200)/0x200 * 0x20)
464 | ((md
->FY
-1) & 0x1f)));
467 WCrt (ba
, CRT_ID_MAX_SCAN_LINE
, (( (md
->FLG
& MDF_DBL
)/ MDF_DBL
* 0x80)
469 | ((md
->VBS
& 0x200)/0x200 * 0x20)
473 WCrt (ba
, CRT_ID_CURSOR_START
, (md
->FY
& 0x1f) - 2);
474 WCrt (ba
, CRT_ID_CURSOR_END
, (md
->FY
& 0x1f) - 1);
476 WCrt (ba
, CRT_ID_START_ADDR_HIGH
, 0x00);
477 WCrt (ba
, CRT_ID_START_ADDR_LOW
, 0x00);
479 WCrt (ba
, CRT_ID_CURSOR_LOC_HIGH
, 0x00);
480 WCrt (ba
, CRT_ID_CURSOR_LOC_LOW
, 0x00);
482 WCrt (ba
, CRT_ID_START_VER_RETR
, md
->VSS
& 0xff);
483 WCrt (ba
, CRT_ID_END_VER_RETR
, (md
->VSE
& 0x0f) | 0x80 | 0x20);
484 WCrt (ba
, CRT_ID_VER_DISP_ENA_END
, VDE
& 0xff);
486 WCrt (ba
, CRT_ID_OFFSET
, (HDE
/ 2) & 0xff);
488 WCrt (ba
, CRT_ID_OFFSET
, (md
->TX
/ 8) & 0xff);
490 WCrt (ba
, CRT_ID_UNDERLINE_LOC
, (md
->FY
-1) & 0x1f);
491 WCrt (ba
, CRT_ID_START_VER_BLANK
, md
->VBS
& 0xff);
492 WCrt (ba
, CRT_ID_END_VER_BLANK
, md
->VBE
& 0xff);
493 /* byte mode + wrap + select row scan counter + cms */
494 WCrt (ba
, CRT_ID_MODE_CONTROL
, 0xe3);
495 WCrt (ba
, CRT_ID_LINE_COMPARE
, 0xff);
497 /* enable extended end bits + those bits */
498 WCrt (ba
, CRT_ID_EXT_HOR_TIMING1
, ( 0x20
499 | ((md
->FLG
& MDF_LACE
) / MDF_LACE
* 0x10)
500 | ((md
->HT
& 0x100) / 0x100 * 0x01)
501 | (((HDE
-1) & 0x100) / 0x100 * 0x02)
502 | ((md
->HBS
& 0x100) / 0x100 * 0x04)
503 | ((md
->HSS
& 0x100) / 0x100 * 0x08)));
506 WCrt (ba
, CRT_ID_EXT_START_ADDR
, (((HDE
/ 2) & 0x100)/0x100 * 16));
508 WCrt (ba
, CRT_ID_EXT_START_ADDR
, (((md
->TX
/ 8) & 0x100)/0x100 * 16));
510 WCrt (ba
, CRT_ID_EXT_HOR_TIMING2
, ( ((md
->HT
& 0x200)/ 0x200 * 0x01)
511 | (((HDE
-1) & 0x200)/ 0x200 * 0x02)
512 | ((md
->HBS
& 0x200)/ 0x200 * 0x04)
513 | ((md
->HSS
& 0x200)/ 0x200 * 0x08)
514 | ((md
->HBE
& 0xc0) / 0x40 * 0x10)
515 | ((md
->HSE
& 0x60) / 0x20 * 0x40)));
517 WCrt (ba
, CRT_ID_EXT_VER_TIMING
, ( ((md
->VSE
& 0x10) / 0x10 * 0x80)
518 | ((md
->VBE
& 0x300)/ 0x100 * 0x20)
520 | ((md
->VSS
& 0x400)/ 0x400 * 0x08)
521 | ((md
->VBS
& 0x400)/ 0x400 * 0x04)
522 | ((VDE
& 0x400)/ 0x400 * 0x02)
523 | ((md
->VT
& 0x400)/ 0x400 * 0x01)));
525 WGfx (ba
, GCT_ID_SET_RESET
, 0x00);
526 WGfx (ba
, GCT_ID_ENABLE_SET_RESET
, 0x00);
527 WGfx (ba
, GCT_ID_COLOR_COMPARE
, 0x00);
528 WGfx (ba
, GCT_ID_DATA_ROTATE
, 0x00);
529 WGfx (ba
, GCT_ID_READ_MAP_SELECT
, 0x00);
530 WGfx (ba
, GCT_ID_GRAPHICS_MODE
, 0x00);
532 WGfx (ba
, GCT_ID_MISC
, 0x04);
534 WGfx (ba
, GCT_ID_MISC
, 0x05);
535 WGfx (ba
, GCT_ID_COLOR_XCARE
, 0xff);
536 WGfx (ba
, GCT_ID_BITMASK
, 0xff);
538 /* reset the Attribute Controller flipflop */
539 vgar (ba
, GREG_STATUS1_R
);
540 WAttr (ba
, ACT_ID_PALETTE0
, 0x00);
541 WAttr (ba
, ACT_ID_PALETTE1
, 0x01);
542 WAttr (ba
, ACT_ID_PALETTE2
, 0x02);
543 WAttr (ba
, ACT_ID_PALETTE3
, 0x03);
544 WAttr (ba
, ACT_ID_PALETTE4
, 0x04);
545 WAttr (ba
, ACT_ID_PALETTE5
, 0x05);
546 WAttr (ba
, ACT_ID_PALETTE6
, 0x06);
547 WAttr (ba
, ACT_ID_PALETTE7
, 0x07);
548 WAttr (ba
, ACT_ID_PALETTE8
, 0x08);
549 WAttr (ba
, ACT_ID_PALETTE9
, 0x09);
550 WAttr (ba
, ACT_ID_PALETTE10
, 0x0a);
551 WAttr (ba
, ACT_ID_PALETTE11
, 0x0b);
552 WAttr (ba
, ACT_ID_PALETTE12
, 0x0c);
553 WAttr (ba
, ACT_ID_PALETTE13
, 0x0d);
554 WAttr (ba
, ACT_ID_PALETTE14
, 0x0e);
555 WAttr (ba
, ACT_ID_PALETTE15
, 0x0f);
557 vgar (ba
, GREG_STATUS1_R
);
559 WAttr (ba
, ACT_ID_ATTR_MODE_CNTL
, 0x08);
561 WAttr (ba
, ACT_ID_ATTR_MODE_CNTL
, 0x09);
563 WAttr (ba
, ACT_ID_OVERSCAN_COLOR
, 0x00);
564 WAttr (ba
, ACT_ID_COLOR_PLANE_ENA
, 0x0f);
565 WAttr (ba
, ACT_ID_HOR_PEL_PANNING
, 0x00);
566 WAttr (ba
, ACT_ID_COLOR_SELECT
, 0x00);
568 vgar (ba
, GREG_STATUS1_R
);
569 /* I have *NO* idea what strobing reg-0x20 might do... */
570 vgaw (ba
, ACT_ADDRESS_W
, 0x20);
573 WCrt (ba
, CRT_ID_MAX_SCAN_LINE
, ( ((md
->FLG
& MDF_DBL
)/ MDF_DBL
* 0x80)
575 | ((md
->VBS
& 0x200)/0x200 * 0x20)
576 | ((md
->FY
-1) & 0x1f)));
578 WCrt (ba
, CRT_ID_MAX_SCAN_LINE
, ( ((md
->FLG
& MDF_DBL
)/ MDF_DBL
* 0x80)
580 | ((md
->VBS
& 0x200)/0x200 * 0x20)
584 /* not it's time for guessing... */
586 vgaw (ba
, VDAC_REG_D
, 0x02);
588 /* if this does what I think it does, it selects DAC
589 register 0, and writes the palette in subsequent
590 registers, thus it works similar to the WD33C93
591 select/data mechanism */
592 vgaw (ba
, VDAC_REG_SELECT
, 0x00);
597 const unsigned char * col
= md
->PAL
;
600 vgaw (ba
, VDAC_REG_DATA
, *col
++);
601 vgaw (ba
, VDAC_REG_DATA
, *col
++);
602 vgaw (ba
, VDAC_REG_DATA
, *col
++);
609 unsigned char cols
= 16;
612 vgaw(ba
, VDAC_REG_DATA
, cols
);
613 vgaw(ba
, VDAC_REG_DATA
, cols
);
614 vgaw(ba
, VDAC_REG_DATA
, cols
);
622 /* now load the font into maps 2 (and 3 for fonts wider than 8 pixels) */
625 /* first set the whole font memory to a test-pattern, so we
626 can see if something that shouldn't be drawn IS drawn.. */
628 volatile char *c
= fb
;
632 for (x
= 0; x
< 65536; x
++) {
633 *c
++ = (x
& 1)? 0xaa : 0x55;
638 volatile char *c
= fb
;
642 for (x
= 0; x
< 65536; x
++) {
643 *c
++ = (x
& 1)? 0xaa : 0x55;
648 /* ok, now position at first defined character, and
649 copy over the images */
650 volatile char *c
= fb
+ md
->FLo
* 32;
651 const unsigned char * f
= md
->FData
;
655 for (z
= md
->FLo
; z
<= md
->FHi
; z
++) {
680 for (zz
= md
->FLo
; z
<= md
->FHi
; zz
++) {
697 WGfx (ba
, GCT_ID_READ_MAP_SELECT
, 0);
699 /* allow writes into maps 0 and 1 */
700 WSeq (ba
, SEQ_ID_MAP_MASK
, 3);
702 /* allow writes into all maps */
703 WSeq (ba
, SEQ_ID_MAP_MASK
, 0x0f);
705 /* select extended chain4 addressing:
706 !A0/!A1 map 0 character to be displayed
707 !A1/ A1 map 1 attribute of that character
708 A0/!A1 map 2 not used (masked out, ignored)
709 A0/ A1 map 3 not used (masked out, ignored) */
710 WSeq (ba
, SEQ_ID_EXT_VIDEO_ADDR
, RSeq(ba
, SEQ_ID_EXT_VIDEO_ADDR
) | 0x02);
713 /* position in display memory */
714 volatile unsigned short * c
= (volatile unsigned short *) fb
;
716 /* fill with blank, white on black */
717 const unsigned short fill_val
= 0x2010;
721 c
+= 2; } while (x
--);
723 /* I won't comment this :-)) */
724 c
= (volatile unsigned short *) fb
;
727 unsigned short init_msg
[6] = {0x520a, 0x450b, 0x540c, 0x490d, 0x4e0e, 0x410f};
728 unsigned short * f
= init_msg
;
736 else if (md
->DEP
== 8) {
737 /* could clear the gfx screen here, but that's what the X server does anyway */
741 gp
->g_data
= (void *)md
;
742 gi
->gd_regaddr
= (void *)ztwopa(ba
);
743 gi
->gd_regsize
= 64*1024;
745 gi
->gd_fbaddr
= (void *)ztwopa(fb
);
746 gi
->gd_fbsize
= 64*1024; /* larger, but that's whats mappable */
748 gi
->gd_colors
= 1 << md
->DEP
;
749 gi
->gd_planes
= md
->DEP
;
751 gi
->gd_fbwidth
= md
->MW
;
752 gi
->gd_fbheight
= md
->MH
;
755 gi
->gd_dwidth
= md
->TX
* md
->FX
;
756 gi
->gd_dheight
= md
->TY
* md
->FY
;
760 /* initialized, works, return 1 */
764 void grfrtattach(struct device
*, struct device
*, void *);
765 int grfrtprint(void *, const char *);
766 int grfrtmatch(struct device
*, struct cfdata
*, void *);
768 int rt_mode(struct grf_softc
*, u_long
, void *, u_long
, int);
769 static int rt_getvmode(struct grf_softc
*, struct grfvideo_mode
*);
770 static int rt_setvmode(struct grf_softc
*, unsigned, int);
771 int rt_getspritepos(struct grf_softc
*, struct grf_position
*);
772 int rt_setspritepos(struct grf_softc
*, struct grf_position
*);
773 int rt_getspriteinfo(struct grf_softc
*, struct grf_spriteinfo
*);
774 int rt_setspriteinfo(struct grf_softc
*, struct grf_spriteinfo
*);
775 int rt_getspritemax(struct grf_softc
*, struct grf_position
*);
776 int rt_getcmap(struct grf_softc
*, struct grf_colormap
*);
777 int rt_putcmap(struct grf_softc
*, struct grf_colormap
*);
778 int rt_bitblt(struct grf_softc
*, struct grf_bitblt
*);
779 int rt_blank(struct grf_softc
*, int *);
781 CFATTACH_DECL(grfrt
, sizeof(struct grf_softc
),
782 grfrtmatch
, grfrtattach
, NULL
, NULL
);
785 * only used in console init
787 static struct cfdata
*cfdata
;
790 * we make sure to only init things once. this is somewhat
791 * tricky regarding the console.
794 grfrtmatch(struct device
*pdp
, struct cfdata
*cfp
, void *auxp
)
797 static int rtconunit
= -1;
799 struct zbus_args
*zap
;
804 * allow only one retina console
806 if (amiga_realconfig
== 0)
812 * check that this is a retina board.
814 if (zap
->manid
!= 18260 || zap
->prodid
!= 6)
818 if (amiga_realconfig
== 0 || rtconunit
!= cfp
->cf_unit
) {
820 if ((unsigned)retina_default_mon
>= retina_mon_max
||
821 monitor_defs
[retina_default_mon
].DEP
== 8)
822 retina_default_mon
= 0;
824 current_mon
= monitor_defs
+ retina_default_mon
;
825 if (retina_alive(current_mon
) == 0)
828 if (amiga_realconfig
== 0) {
829 rtconunit
= cfp
->cf_unit
;
838 * attach to the grfbus (zbus)
841 grfrtattach(struct device
*pdp
, struct device
*dp
, void *auxp
)
843 static struct grf_softc congrf
;
844 struct zbus_args
*zap
;
845 struct grf_softc
*gp
;
852 gp
= (struct grf_softc
*)dp
;
854 if (dp
!= NULL
&& congrf
.g_regkva
!= 0) {
856 * we inited earlier just copy the info
857 * take care not to copy the device struct though.
859 memcpy(&gp
->g_display
, &congrf
.g_display
,
860 (char *)&gp
[1] - (char *)&gp
->g_display
);
862 gp
->g_regkva
= (volatile void *)zap
->va
;
863 gp
->g_fbkva
= (volatile char *)zap
->va
+ 64 * 1024;
864 gp
->g_unit
= GRF_RETINAII_UNIT
;
865 gp
->g_flags
= GF_ALIVE
;
866 gp
->g_mode
= rt_mode
;
867 gp
->g_conpri
= grfrt_cnprobe();
869 (void)rt_load_mon(gp
, current_mon
);
876 amiga_config_found(cfdata
, &gp
->g_device
, gp
, grfrtprint
);
880 grfrtprint(void *auxp
, const char *pnp
)
883 aprint_normal("grf%d at %s", ((struct grf_softc
*)auxp
)->g_unit
,
889 rt_getvmode(struct grf_softc
*gp
, struct grfvideo_mode
*vm
)
894 if (vm
->mode_num
&& vm
->mode_num
> retina_mon_max
)
898 vm
->mode_num
= (current_mon
- monitor_defs
) + 1;
900 md
= monitor_defs
+ (vm
->mode_num
- 1);
901 strncpy (vm
->mode_descr
, monitor_descr
[vm
->mode_num
- 1],
902 sizeof (vm
->mode_descr
));
903 vm
->pixel_clock
= md
->FQ
;
904 vm
->disp_width
= md
->MW
;
905 vm
->disp_height
= md
->MH
;
909 * From observation of the monitor definition table above, I guess that
910 * the horizontal timings are in units of longwords. Hence, I get the
911 * pixels by multiplication with 32 and division by the depth.
912 * The text modes, apparently marked by depth == 4, are even more weird.
913 * According to a comment above, they are computed from a depth==8 mode
914 * (thats for us: * 32 / 8) by applying another factor of 4 / font width.
915 * Reverse applying the latter formula most of the constants cancel
916 * themselves and we are left with a nice (* font width).
917 * That is, internal timings are in units of longwords for graphics
918 * modes, or in units of characters widths for text modes.
919 * We better don't WRITE modes until this has been real live checked.
920 * - Ignatios Souvatzis
924 vm
->hblank_start
= md
->HBS
* 32 / md
->DEP
;
925 vm
->hsync_start
= md
->HSS
* 32 / md
->DEP
;
926 vm
->hsync_stop
= md
->HSE
* 32 / md
->DEP
;
927 vm
->htotal
= md
->HT
* 32 / md
->DEP
;
929 vm
->hblank_start
= md
->HBS
* md
->FX
;
930 vm
->hsync_start
= md
->HSS
* md
->FX
;
931 vm
->hsync_stop
= md
->HSE
* md
->FX
;
932 vm
->htotal
= md
->HT
* md
->FX
;
936 /* XXX move vm->disp_flags and vmul to rt_load_mon
937 * if rt_setvmode can add new modes with grfconfig */
940 if (md
->FLG
& MDF_DBL
) {
941 vm
->disp_flags
|= GRF_FLAGS_DBLSCAN
;
944 if (md
->FLG
& MDF_LACE
) {
945 vm
->disp_flags
|= GRF_FLAGS_LACE
;
948 vm
->vblank_start
= md
->VBS
* vmul
/ 2;
949 vm
->vsync_start
= md
->VSS
* vmul
/ 2;
950 vm
->vsync_stop
= md
->VSE
* vmul
/ 2;
951 vm
->vtotal
= md
->VT
* vmul
/ 2;
958 rt_setvmode(struct grf_softc
*gp
, unsigned mode
, int txtonly
)
962 if (!mode
|| mode
> retina_mon_max
)
965 if (txtonly
&& monitor_defs
[mode
-1].DEP
== 8)
968 current_mon
= monitor_defs
+ (mode
- 1);
970 error
= rt_load_mon (gp
, current_mon
) ? 0 : EINVAL
;
977 * Change the mode of the display.
978 * Return a UNIX error number or 0 for success.
981 rt_mode(struct grf_softc
*gp
, u_long cmd
, void *arg
, u_long a2
, int a3
)
983 /* implement these later... */
987 rt_setvmode (gp
, retina_default_gfx
+ 1, 0);
991 rt_setvmode (gp
, retina_default_mon
+ 1, 0);
998 return (rt_getvmode (gp
, (struct grfvideo_mode
*) arg
));
1000 case GM_GRFSETVMODE
:
1001 return (rt_setvmode (gp
, *(unsigned *) arg
, 1));
1003 case GM_GRFGETNUMVM
:
1004 *(int *)arg
= retina_mon_max
;
1008 return (rt_ioctl (gp
, a2
, arg
));
1014 return (EPASSTHROUGH
);
1018 rt_ioctl(register struct grf_softc
*gp
, u_long cmd
, void *data
)
1021 case GRFIOCGSPRITEPOS
:
1022 return (rt_getspritepos (gp
, (struct grf_position
*) data
));
1024 case GRFIOCSSPRITEPOS
:
1025 return (rt_setspritepos (gp
, (struct grf_position
*) data
));
1027 case GRFIOCSSPRITEINF
:
1028 return (rt_setspriteinfo (gp
, (struct grf_spriteinfo
*) data
));
1030 case GRFIOCGSPRITEINF
:
1031 return (rt_getspriteinfo (gp
, (struct grf_spriteinfo
*) data
));
1033 case GRFIOCGSPRITEMAX
:
1034 return (rt_getspritemax (gp
, (struct grf_position
*) data
));
1037 return (rt_getcmap (gp
, (struct grf_colormap
*) data
));
1040 return (rt_putcmap (gp
, (struct grf_colormap
*) data
));
1043 return (rt_bitblt (gp
, (struct grf_bitblt
*) data
));
1046 return (rt_blank(gp
, (int *)data
));
1049 return (EPASSTHROUGH
);
1053 rt_getcmap(struct grf_softc
*gfp
, struct grf_colormap
*cmap
)
1055 volatile unsigned char *ba
;
1056 u_char red
[256], green
[256], blue
[256], *rp
, *gp
, *bp
;
1060 if (cmap
->count
== 0 || cmap
->index
>= 256)
1063 if (cmap
->count
> 256 - cmap
->index
)
1064 cmap
->count
= 256 - cmap
->index
;
1067 /* first read colors out of the chip, then copyout to userspace */
1068 vgaw (ba
, VDAC_REG_SELECT
, cmap
->index
);
1069 x
= cmap
->count
- 1;
1070 rp
= red
+ cmap
->index
;
1071 gp
= green
+ cmap
->index
;
1072 bp
= blue
+ cmap
->index
;
1074 *rp
++ = vgar (ba
, VDAC_REG_DATA
);
1075 *gp
++ = vgar (ba
, VDAC_REG_DATA
);
1076 *bp
++ = vgar (ba
, VDAC_REG_DATA
);
1080 if (!(error
= copyout (red
+ cmap
->index
, cmap
->red
, cmap
->count
))
1081 && !(error
= copyout (green
+ cmap
->index
, cmap
->green
, cmap
->count
))
1082 && !(error
= copyout (blue
+ cmap
->index
, cmap
->blue
, cmap
->count
)))
1089 rt_putcmap(struct grf_softc
*gfp
, struct grf_colormap
*cmap
)
1091 volatile unsigned char *ba
;
1092 u_char red
[256], green
[256], blue
[256], *rp
, *gp
, *bp
;
1096 if (cmap
->count
== 0 || cmap
->index
>= 256)
1099 if (cmap
->count
> 256 - cmap
->index
)
1100 cmap
->count
= 256 - cmap
->index
;
1102 /* first copy the colors into kernelspace */
1103 if (!(error
= copyin (cmap
->red
, red
+ cmap
->index
, cmap
->count
))
1104 && !(error
= copyin (cmap
->green
, green
+ cmap
->index
, cmap
->count
))
1105 && !(error
= copyin (cmap
->blue
, blue
+ cmap
->index
, cmap
->count
)))
1108 vgaw (ba
, VDAC_REG_SELECT
, cmap
->index
);
1109 x
= cmap
->count
- 1;
1110 rp
= red
+ cmap
->index
;
1111 gp
= green
+ cmap
->index
;
1112 bp
= blue
+ cmap
->index
;
1114 vgaw (ba
, VDAC_REG_DATA
, *rp
++);
1115 vgaw (ba
, VDAC_REG_DATA
, *gp
++);
1116 vgaw (ba
, VDAC_REG_DATA
, *bp
++);
1126 rt_getspritepos(struct grf_softc
*gp
, struct grf_position
*pos
)
1128 volatile unsigned char *ba
;
1131 pos
->x
= vgar (ba
, SEQ_ID_CURSOR_X_LOC_LO
) |
1132 (vgar (ba
, SEQ_ID_CURSOR_X_LOC_HI
) << 8);
1133 pos
->y
= vgar (ba
, SEQ_ID_CURSOR_Y_LOC_LO
) |
1134 (vgar (ba
, SEQ_ID_CURSOR_Y_LOC_HI
) << 8);
1139 rt_setspritepos(struct grf_softc
*gp
, struct grf_position
*pos
)
1141 volatile unsigned char *ba
;
1144 vgaw (ba
, SEQ_ID_CURSOR_X_LOC_LO
, pos
->x
& 0xff);
1145 vgaw (ba
, SEQ_ID_CURSOR_X_LOC_HI
, (pos
->x
>> 8) & 0x07);
1146 vgaw (ba
, SEQ_ID_CURSOR_Y_LOC_LO
, pos
->y
& 0xff);
1147 vgaw (ba
, SEQ_ID_CURSOR_Y_LOC_HI
, (pos
->y
>> 8) & 0x07);
1151 /* assume an at least 2M retina (XXX), sprite is last in memory.
1152 * According to the bogus docs, the cursor can be at most 128 lines
1153 * in height, and the x-hostspot can be placed at most at pos 31,
1154 * this gives width of a long
1156 #define SPRITE_ADDR (2*1024*1024 - 128*4)
1159 rt_getspriteinfo(struct grf_softc
*gp
, struct grf_spriteinfo
*info
)
1161 volatile void *ba
, *fb
;
1165 if (info
->set
& GRFSPRSET_ENABLE
)
1166 info
->enable
= vgar (ba
, SEQ_ID_CURSOR_CONTROL
) & 0x01;
1167 if (info
->set
& GRFSPRSET_POS
)
1168 rt_getspritepos (gp
, &info
->pos
);
1169 if (info
->set
& GRFSPRSET_HOT
) {
1170 info
->hot
.x
= vgar (ba
, SEQ_ID_CURSOR_X_INDEX
) & 0x1f;
1171 info
->hot
.y
= vgar (ba
, SEQ_ID_CURSOR_Y_INDEX
) & 0x7f;
1173 if (info
->set
& GRFSPRSET_CMAP
) {
1174 struct grf_colormap cmap
;
1178 rt_getcmap (gp
, &cmap
);
1179 index
= vgar (ba
, SEQ_ID_CURSOR_COLOR0
);
1180 info
->cmap
.red
[0] = cmap
.red
[index
];
1181 info
->cmap
.green
[0] = cmap
.green
[index
];
1182 info
->cmap
.blue
[0] = cmap
.blue
[index
];
1183 index
= vgar (ba
, SEQ_ID_CURSOR_COLOR1
);
1184 info
->cmap
.red
[1] = cmap
.red
[index
];
1185 info
->cmap
.green
[1] = cmap
.green
[index
];
1186 info
->cmap
.blue
[1] = cmap
.blue
[index
];
1188 if (info
->set
& GRFSPRSET_SHAPE
) {
1189 int saved_bank_lo
= RSeq (ba
, SEQ_ID_PRIM_HOST_OFF_LO
);
1190 int saved_bank_hi
= RSeq (ba
, SEQ_ID_PRIM_HOST_OFF_HI
);
1191 int last_bank
= SPRITE_ADDR
>> 6;
1192 int last_bank_lo
= last_bank
& 0xff;
1193 int last_bank_hi
= last_bank
>> 8;
1195 WSeq (ba
, SEQ_ID_PRIM_HOST_OFF_LO
, last_bank_lo
);
1196 WSeq (ba
, SEQ_ID_PRIM_HOST_OFF_HI
, last_bank_hi
);
1197 copyout (__UNVOLATILE(fb
), info
->image
, 128*4);
1198 mask
= RSeq (ba
, SEQ_ID_CURSOR_PIXELMASK
);
1199 WSeq (ba
, SEQ_ID_PRIM_HOST_OFF_LO
, saved_bank_lo
);
1200 WSeq (ba
, SEQ_ID_PRIM_HOST_OFF_HI
, saved_bank_hi
);
1201 copyout (&mask
, info
->mask
, 1);
1202 info
->size
.x
= 32; /* ??? */
1203 info
->size
.y
= (RSeq (ba
, SEQ_ID_CURSOR_CONTROL
) & 6) << 4;
1211 rt_setspriteinfo(struct grf_softc
*gp
, struct grf_spriteinfo
*info
)
1213 volatile void *ba
, *fb
;
1218 control
= vgar (ba
, SEQ_ID_CURSOR_CONTROL
);
1219 if (info
->set
& GRFSPRSET_ENABLE
) {
1224 vgaw (ba
, SEQ_ID_CURSOR_CONTROL
, control
);
1226 if (info
->set
& GRFSPRSET_POS
)
1227 rt_setspritepos (gp
, &info
->pos
);
1228 if (info
->set
& GRFSPRSET_HOT
) {
1229 vgaw (ba
, SEQ_ID_CURSOR_X_INDEX
, info
->hot
.x
& 0x1f);
1230 vgaw (ba
, SEQ_ID_CURSOR_Y_INDEX
, info
->hot
.y
& 0x7f);
1232 if (info
->set
& GRFSPRSET_CMAP
) {
1233 /* hey cheat a bit here.. XXX */
1234 vgaw (ba
, SEQ_ID_CURSOR_COLOR0
, 0);
1235 vgaw (ba
, SEQ_ID_CURSOR_COLOR1
, 1);
1237 if (info
->set
& GRFSPRSET_SHAPE
) {
1238 int saved_bank_lo
= RSeq (ba
, SEQ_ID_PRIM_HOST_OFF_LO
);
1239 int saved_bank_hi
= RSeq (ba
, SEQ_ID_PRIM_HOST_OFF_HI
);
1240 int last_bank
= SPRITE_ADDR
>> 6;
1241 int last_bank_lo
= last_bank
& 0xff;
1242 int last_bank_hi
= last_bank
>> 8;
1244 WSeq (ba
, SEQ_ID_PRIM_HOST_OFF_LO
, last_bank_lo
);
1245 WSeq (ba
, SEQ_ID_PRIM_HOST_OFF_HI
, last_bank_hi
);
1246 copyin (info
->image
, __UNVOLATILE(fb
), 128*4);
1247 WSeq (ba
, SEQ_ID_PRIM_HOST_OFF_LO
, saved_bank_lo
);
1248 WSeq (ba
, SEQ_ID_PRIM_HOST_OFF_HI
, saved_bank_hi
);
1249 copyin (info
->mask
, &mask
, 1);
1250 WSeq (ba
, SEQ_ID_CURSOR_PIXELMASK
, mask
);
1251 /* info->size.x = 32; *//* ??? */
1253 info
->size
.y
= (RSeq (ba
, SEQ_ID_CURSOR_CONTROL
) & 6) << 4;
1254 control
= (control
& ~6) | ((info
->size
.y
>> 4) & 6);
1255 vgaw (ba
, SEQ_ID_CURSOR_CONTROL
, control
);
1257 /* sick intel bull-addressing.. */
1258 WSeq (ba
, SEQ_ID_CURSOR_STORE_LO
, SPRITE_ADDR
& 0x0f);
1259 WSeq (ba
, SEQ_ID_CURSOR_STORE_HI
, 0);
1260 WSeq (ba
, SEQ_ID_CURSOR_ST_OFF_LO
, (SPRITE_ADDR
>> 4) & 0xff);
1261 WSeq (ba
, SEQ_ID_CURSOR_ST_OFF_HI
, ((SPRITE_ADDR
>> 4) >> 8) & 0xff);
1269 rt_getspritemax(struct grf_softc
*gp
, struct grf_position
*pos
)
1279 * !!! THIS AREA UNDER CONSTRUCTION !!!
1283 rt_bitblt(struct grf_softc
*gp
, struct grf_bitblt
*bb
)
1288 volatile void *ba
, fb
;
1290 u_char saved_bank_lo
;
1291 u_char saved_bank_hi
;
1292 u_char src_bank_lo
, src_bank_hi
;
1293 u_char dst_bank_lo
, dst_bank_hi
;
1294 u_long src_offset
, dst_offset
;
1295 u_short src_bank
, dst_bank
;
1296 u_char
*srcp
, *dstp
;
1303 saved_bank_lo
= RSeq (ba
, SEQ_ID_PRIM_HOST_OFF_LO
);
1304 saved_bank_hi
= RSeq (ba
, SEQ_ID_PRIM_HOST_OFF_HI
);
1306 /* for now, only GRFBBcopy is supported, and only for depth 8. No
1307 clipping is performed, either... */
1309 if (bb
->op
!= GRFBBcopy
&& gp
->g_display
.gd_planes
!= 8)
1312 src_offset
= op
->src_x
+ op
->src_y
* gp
->g_display
.gd_fbwidth
;
1313 dst_offset
= op
->dst_x
+ op
->dst_y
* gp
->g_display
.gd_fbwidth
;
1314 tot
= op
->w
* op
->h
;
1316 /* set write mode 1, "[...] data in the read latches is written
1317 to memory during CPU memory write cycles. [...]" */
1318 WGfx (ba
, GCT_ID_GRAPHICS_MODE
, (RGfx(ba
, GCT_ID_GRAPHICS_MODE
) & 0xfc) | 1);
1319 /* write to primary, read from secondary */
1320 WSeq (ba
, SEQ_ID_EXTENDED_MEM_ENA
, (RSeq(ba
, SEQ_ID_EXTENDED_MEM_ENA
) & 0x1f) | 0 );
1322 if (src_offset
< dst_offset
)
1329 src_bank_lo
= (src_offset
>> 6) & 0xff;
1330 src_bank_hi
= (src_offset
>> 14) & 0xff;
1331 dst_bank_lo
= (dst_offset
>> 6) & 0xff;
1332 dst_bank_hi
= (dst_offset
>> 14) & 0xff;
1336 WSeq (ba
, SEQ_ID_SEC_HOST_OFF_LO
, src_bank_lo
);
1337 WSeq (ba
, SEQ_ID_SEC_HOST_OFF_HI
, src_bank_hi
);
1338 WSeq (ba
, SEQ_ID_PRIM_HOST_OFF_LO
, dst_bank_lo
);
1339 WSeq (ba
, SEQ_ID_PRIM_HOST_OFF_HI
, dst_bank_hi
);
1341 if (src_offset
< dst_offset
)
1358 rt_blank(struct grf_softc
*gp
, int *on
)
1360 struct MonDef
*md
= (struct MonDef
*)gp
->g_data
;
1363 r
= 0x01 | ((md
->FLG
& MDF_CLKDIV2
)/ MDF_CLKDIV2
* 8);
1365 WSeq(gp
->g_regkva
, SEQ_ID_CLOCKING_MODE
, *on
> 0 ? r
: 0x21);