1 /* $NetBSD: grf_cv.c,v 1.47 2009/03/18 17:06:42 cegger Exp $ */
4 * Copyright (c) 1995 Michael Teske
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Ezra Story, by Kari
18 * Mettinen, Michael Teske and by Bernd Ernesti.
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_cv.c,v 1.47 2009/03/18 17:06:42 cegger Exp $");
42 * Graphics routines for the CyberVision 64 board, using the S3 Trio64.
44 * Modified for CV64 from
45 * Kari Mettinen's Cirrus driver by Michael Teske 10/95
47 * Thanks to Tekelec Airtronic for providing me with a S3 Trio64 documentation.
48 * Thanks to Bernd 'the fabulous bug-finder' Ernesti for bringing my messy
49 * source to NetBSD style :)
50 * Thanks to Harald Koenig for providing information about undocumented
54 #include <sys/param.h>
55 #include <sys/errno.h>
56 #include <sys/ioctl.h>
57 #include <sys/device.h>
58 #include <sys/malloc.h>
59 #include <sys/systm.h>
60 #include <sys/syslog.h>
61 #include <machine/cpu.h>
63 #include <amiga/dev/itevar.h>
64 #include <amiga/amiga/device.h>
65 #include <amiga/amiga/isr.h>
66 #include <amiga/dev/grfioctl.h>
67 #include <amiga/dev/grfvar.h>
68 #include <amiga/dev/grf_cvreg.h>
69 #include <amiga/dev/zbusvar.h>
72 * finish all bus operations, flush pipelines
73 * XXX is this really needed?
76 #define cpu_sync() __asm volatile ("nop")
77 #elif defined(__powerpc__)
78 #define cpu_sync() __asm volatile ("sync; isync")
81 int grfcvmatch(struct device
*, struct cfdata
*, void *);
82 void grfcvattach(struct device
*, struct device
*, void *);
83 int grfcvprint(void *, const char *);
86 static int cv_has_4mb(volatile void *);
87 static unsigned short cv_compute_clock(unsigned long);
88 void cv_boardinit(struct grf_softc
*);
89 int cv_getvmode(struct grf_softc
*, struct grfvideo_mode
*);
90 int cv_setvmode(struct grf_softc
*, unsigned int);
91 int cv_blank(struct grf_softc
*, int *);
92 int cv_mode(register struct grf_softc
*, u_long
, void *, u_long
, int);
93 int cv_ioctl(register struct grf_softc
*gp
, u_long cmd
, void *data
);
94 int cv_setmonitor(struct grf_softc
*, struct grfvideo_mode
*);
95 int cv_getcmap(struct grf_softc
*, struct grf_colormap
*);
96 int cv_putcmap(struct grf_softc
*, struct grf_colormap
*);
97 int cv_toggle(struct grf_softc
*);
98 int cv_mondefok(struct grfvideo_mode
*);
99 int cv_load_mon(struct grf_softc
*, struct grfcvtext_mode
*);
100 void cv_inittextmode(struct grf_softc
*);
101 static inline void cv_write_port(unsigned short, volatile void *);
102 static inline void cvscreen(int, volatile void *);
103 static inline void gfx_on_off(int, volatile void *);
105 #ifndef CV_NO_HARDWARE_CURSOR
106 int cv_getspritepos(struct grf_softc
*, struct grf_position
*);
107 int cv_setspritepos(struct grf_softc
*, struct grf_position
*);
108 int cv_getspriteinfo(struct grf_softc
*,struct grf_spriteinfo
*);
109 void cv_setup_hwc(struct grf_softc
*);
110 int cv_setspriteinfo(struct grf_softc
*,struct grf_spriteinfo
*);
111 int cv_getspritemax(struct grf_softc
*,struct grf_position
*);
112 #endif /* !CV_NO_HARDWARE_CURSOR */
115 * Extension to grf_softc for interrupt support
118 struct grf_cv_softc
{
119 struct grf_softc gcs_sc
;
123 /* Graphics display definitions.
124 * These are filled by 'grfconfig' using GRFIOCSETMON.
126 #define monitor_def_max 24
127 static struct grfvideo_mode monitor_def
[24] = {
128 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
129 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
130 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}
132 static struct grfvideo_mode
*monitor_current
= &monitor_def
[0];
133 #define MAXPIXELCLOCK 135000000 /* safety */
135 unsigned char cv_pass_toggle
; /* passthru status tracker */
137 /* Console display definition.
138 * Default hardcoded text mode. This grf_cv is set up to
139 * use one text mode only, and this is it. You may use
140 * grfconfig to change the mode after boot.
145 #define S3FONT kernel_font_8x11
148 #define S3FONT kernel_font_8x8
151 extern unsigned char S3FONT
[];
154 * Define default console mode
155 * (Internally, we still have to use hvalues/8!)
157 struct grfcvtext_mode cvconsole_mode
= {
158 {255, "", 25000000, 640, 480, 4, 640/8, 680/8, 768/8, 800/8,
159 481, 491, 493, 525, 0},
160 8, S3FONTY
, 80, 480 / S3FONTY
, S3FONT
, 32, 255
164 unsigned char cvconscolors
[16][3] = { /* background, foreground, hilite */
184 static unsigned char clocks
[]={
185 0x13, 0x61, 0x6b, 0x6d, 0x51, 0x69, 0x54, 0x69,
186 0x4f, 0x68, 0x6b, 0x6b, 0x18, 0x61, 0x7b, 0x6c,
187 0x51, 0x67, 0x24, 0x62, 0x56, 0x67, 0x77, 0x6a,
188 0x1d, 0x61, 0x53, 0x66, 0x6b, 0x68, 0x79, 0x69,
189 0x7c, 0x69, 0x7f, 0x69, 0x22, 0x61, 0x54, 0x65,
190 0x56, 0x65, 0x58, 0x65, 0x67, 0x66, 0x41, 0x63,
191 0x27, 0x61, 0x13, 0x41, 0x37, 0x62, 0x6b, 0x4d,
192 0x23, 0x43, 0x51, 0x49, 0x79, 0x66, 0x54, 0x49,
193 0x7d, 0x66, 0x34, 0x56, 0x4f, 0x63, 0x1f, 0x42,
194 0x6b, 0x4b, 0x7e, 0x4d, 0x18, 0x41, 0x2a, 0x43,
195 0x7b, 0x4c, 0x74, 0x4b, 0x51, 0x47, 0x65, 0x49,
196 0x24, 0x42, 0x68, 0x49, 0x56, 0x47, 0x75, 0x4a,
197 0x77, 0x4a, 0x31, 0x43, 0x1d, 0x41, 0x71, 0x49,
198 0x53, 0x46, 0x29, 0x42, 0x6b, 0x48, 0x1f, 0x41,
199 0x79, 0x49, 0x6f, 0x48, 0x7c, 0x49, 0x38, 0x43,
200 0x7f, 0x49, 0x5d, 0x46, 0x22, 0x41, 0x53, 0x45,
201 0x54, 0x45, 0x55, 0x45, 0x56, 0x45, 0x57, 0x45,
202 0x58, 0x45, 0x25, 0x41, 0x67, 0x46, 0x5b, 0x45,
203 0x41, 0x43, 0x78, 0x47, 0x27, 0x41, 0x51, 0x44,
204 0x13, 0x21, 0x7d, 0x47, 0x37, 0x42, 0x71, 0x46,
205 0x6b, 0x2d, 0x14, 0x21, 0x23, 0x23, 0x7d, 0x2f,
206 0x51, 0x29, 0x61, 0x2b, 0x79, 0x46, 0x1d, 0x22,
207 0x54, 0x29, 0x45, 0x27, 0x7d, 0x46, 0x7f, 0x46,
208 0x4f, 0x43, 0x2f, 0x41, 0x1f, 0x22, 0x6a, 0x2b,
209 0x6b, 0x2b, 0x5b, 0x29, 0x7e, 0x2d, 0x65, 0x44,
210 0x18, 0x21, 0x5e, 0x29, 0x2a, 0x23, 0x45, 0x26,
211 0x7b, 0x2c, 0x19, 0x21, 0x74, 0x2b, 0x75, 0x2b,
212 0x51, 0x27, 0x3f, 0x25, 0x65, 0x29, 0x40, 0x25,
213 0x24, 0x22, 0x41, 0x25, 0x68, 0x29, 0x42, 0x25,
214 0x56, 0x27, 0x7e, 0x2b, 0x75, 0x2a, 0x1c, 0x21,
215 0x77, 0x2a, 0x4f, 0x26, 0x31, 0x23, 0x6f, 0x29,
216 0x1d, 0x21, 0x32, 0x23, 0x71, 0x29, 0x72, 0x29,
217 0x53, 0x26, 0x69, 0x28, 0x29, 0x22, 0x75, 0x29,
218 0x6b, 0x28, 0x1f, 0x21, 0x1f, 0x21, 0x6d, 0x28,
219 0x79, 0x29, 0x2b, 0x22, 0x6f, 0x28, 0x59, 0x26,
220 0x7c, 0x29, 0x7d, 0x29, 0x38, 0x23, 0x21, 0x21,
221 0x7f, 0x29, 0x39, 0x23, 0x5d, 0x26, 0x75, 0x28,
222 0x22, 0x21, 0x77, 0x28, 0x53, 0x25, 0x6c, 0x27,
223 0x54, 0x25, 0x61, 0x26, 0x55, 0x25, 0x30, 0x22,
224 0x56, 0x25, 0x63, 0x26, 0x57, 0x25, 0x71, 0x27,
225 0x58, 0x25, 0x7f, 0x28, 0x25, 0x21, 0x74, 0x27,
226 0x67, 0x26, 0x40, 0x23, 0x5b, 0x25, 0x26, 0x21,
227 0x41, 0x23, 0x34, 0x22, 0x78, 0x27, 0x6b, 0x26,
228 0x27, 0x21, 0x35, 0x22, 0x51, 0x24, 0x7b, 0x27,
229 0x13, 0x1, 0x13, 0x1, 0x7d, 0x27, 0x4c, 0x9,
230 0x37, 0x22, 0x5b, 0xb, 0x71, 0x26, 0x5c, 0xb,
231 0x6b, 0xd, 0x47, 0x23, 0x14, 0x1, 0x4f, 0x9,
232 0x23, 0x3, 0x75, 0x26, 0x7d, 0xf, 0x1c, 0x2,
233 0x51, 0x9, 0x59, 0x24, 0x61, 0xb, 0x69, 0x25,
234 0x79, 0x26, 0x34, 0x5, 0x1d, 0x2, 0x6b, 0x25,
235 0x54, 0x9, 0x35, 0x5, 0x45, 0x7, 0x6d, 0x25,
236 0x7d, 0x26, 0x16, 0x1, 0x7f, 0x26, 0x77, 0xd,
237 0x4f, 0x23, 0x78, 0xd, 0x2f, 0x21, 0x27, 0x3,
238 0x1f, 0x2, 0x59, 0x9, 0x6a, 0xb, 0x73, 0x25,
239 0x6b, 0xb, 0x63, 0x24, 0x5b, 0x9, 0x20, 0x2,
240 0x7e, 0xd, 0x4b, 0x7, 0x65, 0x24, 0x43, 0x22,
241 0x18, 0x1, 0x6f, 0xb, 0x5e, 0x9, 0x70, 0xb,
242 0x2a, 0x3, 0x33, 0x4, 0x45, 0x6, 0x60, 0x9,
243 0x7b, 0xc, 0x19, 0x1, 0x19, 0x1, 0x7d, 0xc,
244 0x74, 0xb, 0x50, 0x7, 0x75, 0xb, 0x63, 0x9,
245 0x51, 0x7, 0x23, 0x2, 0x3f, 0x5, 0x1a, 0x1,
246 0x65, 0x9, 0x2d, 0x3, 0x40, 0x5, 0x0, 0x0,
250 /* Board Address of CV64 */
251 static volatile void *cv_boardaddr
;
252 static int cv_fbsize
;
255 * Memory clock (binpatchable).
256 * Let's be defensive: 50 MHz runs on all boards I know of.
257 * 55 MHz runs on most boards. But you should know what you're doing
258 * if you set this flag. Again: This flag may destroy your CV Board.
259 * Use it at your own risk!!!
260 * Anyway, this doesn't imply that I'm responsible if your board breaks
261 * without setting this flag :-).
263 #ifdef CV_AGGRESSIVE_TIMING
264 long cv_memclk
= 55000000;
266 long cv_memclk
= 50000000;
269 /* standard driver stuff */
270 CFATTACH_DECL(grfcv
, sizeof(struct grf_cv_softc
),
271 grfcvmatch
, grfcvattach
, NULL
, NULL
);
273 static struct cfdata
*cfdata
;
275 #define CV_INT_NUM 6 /* CV interrupt Level: #2 or #6 */
276 #define CV_ULCURSOR 1 /* Underlined Cursor in textmode */
278 #ifndef CV_NO_HARDWARE_CURSOR
280 #define HWC_OFF (cv_fbsize - 1024*2)
281 #define HWC_SIZE 1024
283 static unsigned short cv_cursor_storage
[HWC_SIZE
/2];
284 static short curs_update_flag
= 0;
286 #endif /* !CV_NO_HARDWARE_CURSOR */
290 * This is used for updating the cursor shape (because it _must not_
291 * be changed while cursor is displayed)
292 * and maybe later to avoid busy waiting
293 * for Vertical Blank and/or gfx engine busy
299 #ifndef CV_NO_HARDWARE_CURSOR
300 volatile unsigned long *csrc
, *cdest
;
303 struct grf_softc
*gp
= arg
;
304 volatile void *ba
= gp
->g_regkva
;
306 unsigned char cridx
; /* Save the cr Register index */
311 test
= vgar(ba
, GREG_INPUT_STATUS0_R
);
313 if (test
& 0x80) { /* VR int pending */
314 /* Save old CR index */
315 cridx
= vgar (ba
, CRT_ADDRESS
);
317 #if !defined(__m68k__)
318 test
= RCrt(ba
, CRT_ID_END_VER_RETR
);
319 /* Clear int (bit 4) */
321 WCrt(ba
, CRT_ID_END_VER_RETR
, test
);
323 vgaw(ba
, CRT_ADDRESS
, CRT_ID_END_VER_RETR
);
324 __asm
volatile("bclr #4,%0@(0x3d5);nop" : : "a" (ba
));
327 #ifndef CV_NO_HARDWARE_CURSOR
328 /* update the hardware cursor, if necessary */
329 if (curs_update_flag
) {
330 csrc
= (unsigned long *)cv_cursor_storage
;
331 cdest
= (volatile unsigned long *)
332 ((volatile char*)gp
->g_fbkva
+ HWC_OFF
);
333 for (i
= 0; i
< HWC_SIZE
/ sizeof(long); i
++)
335 curs_update_flag
= 0;
338 #if !defined(__m68k__)
340 WCrt(ba
, CRT_ID_END_VER_RETR
, test
);
342 /* I don't trust the optimizer here... */
343 __asm
volatile("bset #4,%0@(0x3d5);nop" : : "a" (ba
));
345 cv_setspritepos (gp
, NULL
);
347 /* Restore the old CR index */
348 vgaw(ba
, CRT_ADDRESS
, cridx
);
350 #endif /* !CV_NO_HARDWARE_CURSOR */
357 * Get frambuffer memory size.
358 * phase5 didn't provide the bit in CR36,
359 * so we have to do it this way.
360 * Return 0 for 2MB, 1 for 4MB
363 cv_has_4mb(volatile void *fb
)
365 volatile unsigned long *testfbw
, *testfbr
;
367 /* write patterns in memory and test if they can be read */
368 testfbw
= (volatile unsigned long *)fb
;
369 testfbr
= (volatile unsigned long *)((volatile char*)fb
+ 0x02000000);
370 *testfbw
= 0x87654321;
372 if (*testfbr
!= 0x87654321)
375 /* upper memory region */
376 testfbw
= (volatile unsigned long *)((volatile char*)fb
+ 0x00200000);
377 testfbr
= (volatile unsigned long *)((volatile char*)fb
+ 0x02200000);
378 *testfbw
= 0x87654321;
380 if (*testfbr
!= 0x87654321)
382 *testfbw
= 0xAAAAAAAA;
384 if (*testfbr
!= 0xAAAAAAAA)
386 *testfbw
= 0x55555555;
388 if (*testfbr
!= 0x55555555)
394 grfcvmatch(struct device
*pdp
, struct cfdata
*cfp
, void *auxp
)
397 static int cvcons_unit
= -1;
399 struct zbus_args
*zap
;
403 if (amiga_realconfig
== 0)
405 if (cvcons_unit
!= -1)
409 /* Lets be Paranoid: Test man and prod id */
410 if (zap
->manid
!= 8512 || zap
->prodid
!= 34)
413 cv_boardaddr
= zap
->va
;
416 if (amiga_realconfig
== 0) {
417 cvcons_unit
= cfp
->cf_unit
;
426 grfcvattach(struct device
*pdp
, struct device
*dp
, void *auxp
)
428 static struct grf_cv_softc congrf
;
429 struct zbus_args
*zap
;
430 struct grf_softc
*gp
;
431 struct grf_cv_softc
*gcp
;
432 static char attachflag
= 0;
437 * This function is called twice, once on console init (dp == NULL)
438 * and once on "normal" grf5 init.
441 if (dp
== NULL
) /* console init */
444 gcp
= (struct grf_cv_softc
*)dp
;
448 if (dp
!= NULL
&& congrf
.gcs_sc
.g_regkva
!= 0) {
450 * inited earlier, just copy (not device struct)
454 memcpy(&gp
->g_display
, &congrf
.gcs_sc
.g_display
,
455 (char *) &gcp
->gcs_isr
- (char *) &gp
->g_display
);
457 /* ... and transfer the isr */
458 gcp
->gcs_isr
.isr_ipl
= CV_INT_NUM
;
459 gcp
->gcs_isr
.isr_intr
= cvintr
;
460 gcp
->gcs_isr
.isr_arg
= (void *)gp
;
462 /* First add new isr */
463 add_isr(&gcp
->gcs_isr
);
464 remove_isr(&congrf
.gcs_isr
);
466 gp
->g_regkva
= (volatile char *)cv_boardaddr
+ 0x02000000;
467 gp
->g_fbkva
= (volatile char *)cv_boardaddr
+ 0x01400000;
469 gp
->g_unit
= GRF_CV64_UNIT
;
470 gp
->g_mode
= cv_mode
;
471 gp
->g_conpri
= grfcv_cnprobe();
472 gp
->g_flags
= GF_ALIVE
;
474 /* add Interrupt Handler */
475 gcp
->gcs_isr
.isr_ipl
= CV_INT_NUM
;
476 gcp
->gcs_isr
.isr_intr
= cvintr
;
477 gcp
->gcs_isr
.isr_arg
= (void *)gp
;
478 add_isr(&gcp
->gcs_isr
);
480 /* wakeup the board */
485 (void)cv_load_mon(gp
, &cvconsole_mode
);
492 if (amiga_config_found(cfdata
, &gp
->g_device
, gp
, grfcvprint
)) {
494 printf("grfcv: CyberVision64 with %dMB being used\n",
499 /*printf("grfcv unattached!!\n")*/;
504 grfcvprint(void *auxp
, const char *pnp
)
507 aprint_normal("ite at %s: ", pnp
);
513 * Computes M, N, and R values from
514 * given input frequency. It uses a table of
515 * precomputed values, to keep CPU time low.
517 * The return value consist of:
518 * lower byte: Bits 4-0: N Divider Value
519 * Bits 5-6: R Value for e.g. SR10 or SR12
520 * higher byte: Bits 0-6: M divider value for e.g. SR11 or SR13
523 static unsigned short
524 cv_compute_clock(unsigned long freq
)
526 static unsigned char *mnr
, *save
; /* M, N + R vals */
527 unsigned long work_freq
, r
;
531 if (freq
< 12500000 || freq
> MAXPIXELCLOCK
) {
532 printf("grfcv: Illegal clock frequency: %ldMHz\n", freq
/1000000);
533 printf("grfcv: Using default frequency: 25MHz\n");
534 printf("grfcv: See the manpage of grfconfig for more informations.\n");
538 mnr
= clocks
; /* there the vals are stored */
541 while (*mnr
) { /* mnr vals are 0-terminated */
542 work_freq
= (0x37EE * (mnr
[0] + 2)) / ((mnr
[1] & 0x1F) + 2);
544 r
= (mnr
[1] >> 5) & 0x03;
546 work_freq
=work_freq
>> r
; /* r is the freq divider */
548 work_freq
*= 0x3E8; /* 2nd part of OSC */
550 diff
= abs(freq
- work_freq
);
554 /* In save are the vals for minimal diff */
559 erg
= *((unsigned short *)save
);
566 cv_boardinit(struct grf_softc
*gp
)
570 unsigned int clockpar
;
576 for (i
= 0; i
< 6; i
++)
578 cv_write_port (0xff, (volatile char*)ba
- 0x02000000);
580 /* Return to operational Mode */
581 cv_write_port(0x8004, (volatile char*)ba
- 0x02000000);
584 vgaw(ba
, SREG_VIDEO_SUBS_ENABLE
, 0x10);
585 vgaw(ba
, SREG_OPTION_SELECT
, 0x01);
586 vgaw(ba
, SREG_VIDEO_SUBS_ENABLE
, 0x08);
588 vgaw(ba
, GREG_MISC_OUTPUT_W
, 0x03);
590 WCrt(ba
, CRT_ID_REGISTER_LOCK_1
, 0x48); /* unlock S3 VGA regs */
591 WCrt(ba
, CRT_ID_REGISTER_LOCK_2
, 0xA5); /* unlock syscontrol */
594 * The default board interrupt is #6.
595 * Set the roxxler register to use interrupt #2, not #6.
598 cv_write_port(0x8080, ba
- 0x02000000);
601 /* Enable board interrupts */
602 cv_write_port(0x8008, (volatile char*)ba
- 0x02000000);
604 test
= RCrt(ba
, CRT_ID_SYSTEM_CONFIG
);
605 test
= test
| 0x01; /* enable enhaced register access */
606 test
= test
& 0xEF; /* clear bit 4, 0 wait state */
607 WCrt(ba
, CRT_ID_SYSTEM_CONFIG
, test
);
610 * bit 1=1: enable enhanced mode functions
611 * bit 4=1: enable linear addressing
612 * bit 5=1: enable MMIO
614 vgaw(ba
, ECR_ADV_FUNC_CNTL
, 0x31);
616 /* enable color mode (bit0), CPU access (bit1), high 64k page (bit5) */
617 vgaw(ba
, GREG_MISC_OUTPUT_W
, 0xe3);
620 WCrt(ba
, CRT_ID_EXT_SYS_CNTL_4
, 0x00);
622 /* Reset. This does nothing, but everyone does it:) */
623 WSeq(ba
, SEQ_ID_RESET
, 0x03);
625 WSeq(ba
, SEQ_ID_CLOCKING_MODE
, 0x01); /* 8 Dot Clock */
626 WSeq(ba
, SEQ_ID_MAP_MASK
, 0x0f); /* Enable write planes */
627 WSeq(ba
, SEQ_ID_CHAR_MAP_SELECT
, 0x00); /* Character Font */
629 WSeq(ba
, SEQ_ID_MEMORY_MODE
, 0x02); /* Complete mem access */
631 WSeq(ba
, SEQ_ID_UNLOCK_EXT
, 0x06); /* Unlock extensions */
632 test
= RSeq(ba
, SEQ_ID_BUS_REQ_CNTL
); /* Bus Request */
634 /* enable 4MB fast Page Mode */
635 test
= test
| 1 << 6;
636 WSeq(ba
, SEQ_ID_BUS_REQ_CNTL
, test
);
637 /* faster LUT write */
638 WSeq(ba
, SEQ_ID_RAMDAC_CNTL
, 0xC0);
640 test
= RSeq(ba
, SEQ_ID_CLKSYN_CNTL_2
); /* Clksyn2 read */
642 /* immediately Clkload bit clear */
645 /* 2 MCLK Memory Write.... */
646 if (cv_memclk
>= 55000000)
649 WSeq(ba
, SEQ_ID_CLKSYN_CNTL_2
, test
);
652 clockpar
= cv_compute_clock(cv_memclk
);
653 test
= (clockpar
& 0xFF00) >> 8;
654 WSeq(ba
, SEQ_ID_MCLK_HI
, test
); /* PLL N-Divider Value */
656 test
= clockpar
& 0xFF;
657 WSeq(ba
, SEQ_ID_MCLK_LO
, test
); /* PLL M-Divider Value */
659 if (RCrt(ba
, CRT_ID_REVISION
) == 0x10) /* bugfix for new S3 chips */
660 WSeq(ba
, SEQ_ID_MORE_MAGIC
, test
);
662 /* We now load an 25 MHz, 31 kHz, 640x480 standard VGA Mode. */
664 WSeq(ba
, SEQ_ID_DCLK_HI
, 0x13);
665 WSeq(ba
, SEQ_ID_DCLK_LO
, 0x41);
667 test
= RSeq (ba
, SEQ_ID_CLKSYN_CNTL_2
);
670 /* DCLK + MCLK Clock immediate load! */
671 WSeq(ba
,SEQ_ID_CLKSYN_CNTL_2
, test
);
674 test
= vgar(ba
, 0x3cc);
676 vgaw(ba
, 0x3c2, test
);
678 /* Clear bit 5 again, prevent further loading. */
679 WSeq(ba
, SEQ_ID_CLKSYN_CNTL_2
, 0x02);
681 WCrt(ba
, CRT_ID_HOR_TOTAL
, 0x5F);
682 WCrt(ba
, CRT_ID_HOR_DISP_ENA_END
, 0x4F);
683 WCrt(ba
, CRT_ID_START_HOR_BLANK
, 0x50);
684 WCrt(ba
, CRT_ID_END_HOR_BLANK
, 0x82);
685 WCrt(ba
, CRT_ID_START_HOR_RETR
, 0x54);
686 WCrt(ba
, CRT_ID_END_HOR_RETR
, 0x80);
687 WCrt(ba
, CRT_ID_VER_TOTAL
, 0xBF);
689 WCrt(ba
, CRT_ID_OVERFLOW
, 0x1F); /* overflow reg */
691 WCrt(ba
, CRT_ID_PRESET_ROW_SCAN
, 0x00); /* no panning */
693 WCrt(ba
, CRT_ID_MAX_SCAN_LINE
, 0x40); /* vscan */
695 WCrt(ba
, CRT_ID_CURSOR_START
, 0x00);
696 WCrt(ba
, CRT_ID_CURSOR_END
, 0x00);
698 /* Display start address */
699 WCrt(ba
, CRT_ID_START_ADDR_HIGH
, 0x00);
700 WCrt(ba
, CRT_ID_START_ADDR_LOW
, 0x00);
702 /* Cursor location */
703 WCrt(ba
, CRT_ID_CURSOR_LOC_HIGH
, 0x00);
704 WCrt(ba
, CRT_ID_CURSOR_LOC_LOW
, 0x00);
706 /* Vertical retrace */
707 WCrt(ba
, CRT_ID_START_VER_RETR
, 0x9C);
708 WCrt(ba
, CRT_ID_END_VER_RETR
, 0x0E);
710 WCrt(ba
, CRT_ID_VER_DISP_ENA_END
, 0x8F);
711 WCrt(ba
, CRT_ID_SCREEN_OFFSET
, 0x50);
713 WCrt(ba
, CRT_ID_UNDERLINE_LOC
, 0x00);
715 WCrt(ba
, CRT_ID_START_VER_BLANK
, 0x96);
716 WCrt(ba
, CRT_ID_END_VER_BLANK
, 0xB9);
718 WCrt(ba
, CRT_ID_MODE_CONTROL
, 0xE3);
720 WCrt(ba
, CRT_ID_LINE_COMPARE
, 0xFF);
722 WCrt(ba
, CRT_ID_BACKWAD_COMP_3
, 0x10); /* FIFO enabled */
724 /* Refresh count 1, High speed text font, enhanced color mode */
725 WCrt(ba
, CRT_ID_MISC_1
, 0x35);
727 /* start fifo position */
728 WCrt(ba
, CRT_ID_DISPLAY_FIFO
, 0x5a);
730 WCrt(ba
, CRT_ID_EXT_MEM_CNTL_2
, 0x70);
732 /* address window position */
733 WCrt(ba
, CRT_ID_LAW_POS_LO
, 0x40);
735 /* N Parameter for Display FIFO */
736 WCrt(ba
, CRT_ID_EXT_MEM_CNTL_3
, 0xFF);
738 WGfx(ba
, GCT_ID_SET_RESET
, 0x00);
739 WGfx(ba
, GCT_ID_ENABLE_SET_RESET
, 0x00);
740 WGfx(ba
, GCT_ID_COLOR_COMPARE
, 0x00);
741 WGfx(ba
, GCT_ID_DATA_ROTATE
, 0x00);
742 WGfx(ba
, GCT_ID_READ_MAP_SELECT
, 0x00);
743 WGfx(ba
, GCT_ID_GRAPHICS_MODE
, 0x40);
744 WGfx(ba
, GCT_ID_MISC
, 0x01);
745 WGfx(ba
, GCT_ID_COLOR_XCARE
, 0x0F);
746 WGfx(ba
, GCT_ID_BITMASK
, 0xFF);
748 /* colors for text mode */
749 for (i
= 0; i
<= 0xf; i
++)
752 WAttr(ba
, ACT_ID_ATTR_MODE_CNTL
, 0x41);
753 WAttr(ba
, ACT_ID_OVERSCAN_COLOR
, 0x01);
754 WAttr(ba
, ACT_ID_COLOR_PLANE_ENA
, 0x0F);
755 WAttr(ba
, ACT_ID_HOR_PEL_PANNING
, 0x00);
756 WAttr(ba
, ACT_ID_COLOR_SELECT
, 0x00);
758 vgaw(ba
, VDAC_MASK
, 0xFF); /* DAC Mask */
760 *((volatile unsigned long *)((volatile char*)ba
+ ECR_FRGD_COLOR
)) = 0xFF;
761 *((volatile unsigned long *)((volatile char*)ba
+ ECR_BKGD_COLOR
)) = 0;
763 /* colors initially set to greyscale */
765 vgaw(ba
, VDAC_ADDRESS_W
, 0);
766 for (i
= 255; i
>= 0 ; i
--) {
767 vgaw(ba
, VDAC_DATA
, i
);
768 vgaw(ba
, VDAC_DATA
, i
);
769 vgaw(ba
, VDAC_DATA
, i
);
772 /* GFx hardware cursor off */
773 WCrt(ba
, CRT_ID_HWGC_MODE
, 0x00);
775 /* Set first to 4 MB, so test will work */
776 WCrt(ba
, CRT_ID_LAW_CNTL
, 0x13);
778 /* find *correct* fbsize of z3 board */
779 if (cv_has_4mb((volatile char *)cv_boardaddr
+ 0x01400000)) {
780 cv_fbsize
= 1024 * 1024 * 4;
781 WCrt(ba
, CRT_ID_LAW_CNTL
, 0x13); /* 4 MB */
783 cv_fbsize
= 1024 * 1024 * 2;
784 WCrt(ba
, CRT_ID_LAW_CNTL
, 0x12); /* 2 MB */
787 /* Initialize graphics engine */
789 vgaw16(ba
, ECR_FRGD_MIX
, 0x27);
790 vgaw16(ba
, ECR_BKGD_MIX
, 0x07);
792 vgaw16(ba
, ECR_READ_REG_DATA
, 0x1000);
794 vgaw16(ba
, ECR_READ_REG_DATA
, 0x2000);
796 vgaw16(ba
, ECR_READ_REG_DATA
, 0x3fff);
799 vgaw16(ba
, ECR_READ_REG_DATA
, 0x4fff);
802 vgaw16(ba
, ECR_BITPLANE_WRITE_MASK
, ~0);
805 vgaw16(ba
, ECR_READ_REG_DATA
, 0xe000);
806 vgaw16(ba
, ECR_CURRENT_Y_POS2
, 0x00);
807 vgaw16(ba
, ECR_CURRENT_X_POS2
, 0x00);
808 vgaw16(ba
, ECR_READ_REG_DATA
, 0xa000);
809 vgaw16(ba
, ECR_DEST_Y__AX_STEP
, 0x00);
810 vgaw16(ba
, ECR_DEST_Y2__AX_STEP2
, 0x00);
811 vgaw16(ba
, ECR_DEST_X__DIA_STEP
, 0x00);
812 vgaw16(ba
, ECR_DEST_X2__DIA_STEP2
, 0x00);
813 vgaw16(ba
, ECR_SHORT_STROKE
, 0x00);
814 vgaw16(ba
, ECR_DRAW_CMD
, 0x01);
817 /* It ain't easy to write here, so let's do it again */
818 vgaw16(ba
, ECR_READ_REG_DATA
, 0x4fff);
820 vgaw16(ba
, ECR_BKGD_COLOR
, 0x01);
821 vgaw16(ba
, ECR_FRGD_COLOR
, 0x00);
823 /* Enable Video Display (Set Bit 5) */
827 gi
->gd_regaddr
= (void *) kvtop (__UNVOLATILE(ba
));
828 gi
->gd_regsize
= 64 * 1024;
829 gi
->gd_fbaddr
= (void *) kvtop (__UNVOLATILE(gp
->g_fbkva
));
830 gi
->gd_fbsize
= cv_fbsize
;
835 cv_getvmode(struct grf_softc
*gp
, struct grfvideo_mode
*vm
)
837 struct grfvideo_mode
*gv
;
840 /* Handle grabbing console mode */
841 if (vm
->mode_num
== 255) {
842 memcpy(vm
, &cvconsole_mode
, sizeof(struct grfvideo_mode
));
843 /* XXX so grfconfig can tell us the correct text dimensions. */
844 vm
->depth
= cvconsole_mode
.fy
;
848 if (vm
->mode_num
== 0)
849 vm
->mode_num
= (monitor_current
- monitor_def
) + 1;
850 if (vm
->mode_num
< 1 || vm
->mode_num
> monitor_def_max
)
852 gv
= monitor_def
+ (vm
->mode_num
- 1);
853 if (gv
->mode_num
== 0)
856 memcpy(vm
, gv
, sizeof(struct grfvideo_mode
));
859 /* adjust internal values to pixel values */
861 vm
->hblank_start
*= 8;
862 vm
->hsync_start
*= 8;
871 cv_setvmode(struct grf_softc
*gp
, unsigned mode
)
874 if (!mode
|| (mode
> monitor_def_max
) ||
875 monitor_def
[mode
- 1].mode_num
== 0)
878 monitor_current
= monitor_def
+ (mode
- 1);
885 cv_blank(struct grf_softc
*gp
, int *on
)
890 gfx_on_off(*on
> 0 ? 0 : 1, ba
);
896 * Change the mode of the display.
897 * Return a UNIX error number or 0 for success.
900 cv_mode(register struct grf_softc
*gp
, u_long cmd
, void *arg
, u_long a2
,
907 error
= cv_load_mon (gp
,
908 (struct grfcvtext_mode
*) monitor_current
) ? 0 : EINVAL
;
913 cvscreen(1, gp
->g_regkva
- 0x02000000);
915 cv_load_mon(gp
, &cvconsole_mode
);
916 ite_reinit(gp
->g_itedev
);
924 return (cv_getvmode (gp
, (struct grfvideo_mode
*) arg
));
927 error
= cv_setvmode (gp
, *(unsigned *) arg
);
928 if (!error
&& (gp
->g_flags
& GF_GRFON
))
930 (struct grfcvtext_mode
*) monitor_current
);
934 *(int *)arg
= monitor_def_max
;
938 return (cv_ioctl (gp
, a2
, arg
));
944 return (EPASSTHROUGH
);
949 cv_ioctl(register struct grf_softc
*gp
, u_long cmd
, void *data
)
952 #ifndef CV_NO_HARDWARE_CURSOR
953 case GRFIOCGSPRITEPOS
:
954 return(cv_getspritepos (gp
, (struct grf_position
*) data
));
956 case GRFIOCSSPRITEPOS
:
957 return(cv_setspritepos (gp
, (struct grf_position
*) data
));
959 case GRFIOCSSPRITEINF
:
960 return(cv_setspriteinfo (gp
, (struct grf_spriteinfo
*) data
));
962 case GRFIOCGSPRITEINF
:
963 return(cv_getspriteinfo (gp
, (struct grf_spriteinfo
*) data
));
965 case GRFIOCGSPRITEMAX
:
966 return(cv_getspritemax (gp
, (struct grf_position
*) data
));
967 #else /* !CV_NO_HARDWARE_CURSOR */
968 case GRFIOCGSPRITEPOS
:
969 case GRFIOCSSPRITEPOS
:
970 case GRFIOCSSPRITEINF
:
971 case GRFIOCGSPRITEINF
:
972 case GRFIOCGSPRITEMAX
:
974 #endif /* !CV_NO_HARDWARE_CURSOR */
977 return (cv_getcmap (gp
, (struct grf_colormap
*) data
));
980 return (cv_putcmap (gp
, (struct grf_colormap
*) data
));
986 return (cv_toggle (gp
));
989 return (cv_setmonitor (gp
, (struct grfvideo_mode
*)data
));
992 return (cv_blank (gp
, (int *)data
));
994 return (EPASSTHROUGH
);
999 cv_setmonitor(struct grf_softc
*gp
, struct grfvideo_mode
*gv
)
1001 struct grfvideo_mode
*md
;
1003 if (!cv_mondefok(gv
))
1007 /* handle interactive setting of console mode */
1008 if (gv
->mode_num
== 255) {
1009 memcpy(&cvconsole_mode
.gv
, gv
, sizeof(struct grfvideo_mode
));
1010 cvconsole_mode
.gv
.hblank_start
/= 8;
1011 cvconsole_mode
.gv
.hsync_start
/= 8;
1012 cvconsole_mode
.gv
.hsync_stop
/= 8;
1013 cvconsole_mode
.gv
.htotal
/= 8;
1014 cvconsole_mode
.rows
= gv
->disp_height
/ cvconsole_mode
.fy
;
1015 cvconsole_mode
.cols
= gv
->disp_width
/ cvconsole_mode
.fx
;
1016 if (!(gp
->g_flags
& GF_GRFON
))
1017 cv_load_mon(gp
, &cvconsole_mode
);
1018 ite_reinit(gp
->g_itedev
);
1023 md
= monitor_def
+ (gv
->mode_num
- 1);
1026 * Prevent user from crashing the system by using
1027 * grfconfig while in X
1029 if (gp
->g_flags
& GF_GRFON
)
1030 if (md
== monitor_current
) {
1031 printf("grfcv: Changing the used mode not allowed!\n");
1035 memcpy(md
, gv
, sizeof(struct grfvideo_mode
));
1037 /* adjust pixel oriented values to internal rep. */
1039 md
->hblank_start
/= 8;
1040 md
->hsync_start
/= 8;
1041 md
->hsync_stop
/= 8;
1049 cv_getcmap(struct grf_softc
*gfp
, struct grf_colormap
*cmap
)
1052 u_char red
[256], green
[256], blue
[256], *rp
, *gp
, *bp
;
1057 if (cmap
->count
== 0 || cmap
->index
>= 256)
1060 if (cmap
->count
> 256 - cmap
->index
)
1061 cmap
->count
= 256 - cmap
->index
;
1063 /* first read colors out of the chip, then copyout to userspace */
1064 vgaw (ba
, VDAC_ADDRESS_W
, cmap
->index
);
1065 x
= cmap
->count
- 1;
1067 rp
= red
+ cmap
->index
;
1068 gp
= green
+ cmap
->index
;
1069 bp
= blue
+ cmap
->index
;
1072 *rp
++ = vgar (ba
, VDAC_DATA
) << 2;
1073 *gp
++ = vgar (ba
, VDAC_DATA
) << 2;
1074 *bp
++ = vgar (ba
, VDAC_DATA
) << 2;
1077 if (!(error
= copyout (red
+ cmap
->index
, cmap
->red
, cmap
->count
))
1078 && !(error
= copyout (green
+ cmap
->index
, cmap
->green
, cmap
->count
))
1079 && !(error
= copyout (blue
+ cmap
->index
, cmap
->blue
, cmap
->count
)))
1087 cv_putcmap(struct grf_softc
*gfp
, struct grf_colormap
*cmap
)
1090 u_char red
[256], green
[256], blue
[256], *rp
, *gp
, *bp
;
1095 if (cmap
->count
== 0 || cmap
->index
>= 256)
1098 if (cmap
->count
> 256 - cmap
->index
)
1099 cmap
->count
= 256 - cmap
->index
;
1101 /* first copy the colors into kernelspace */
1102 if (!(error
= copyin (cmap
->red
, red
+ cmap
->index
, cmap
->count
))
1103 && !(error
= copyin (cmap
->green
, green
+ cmap
->index
, cmap
->count
))
1104 && !(error
= copyin (cmap
->blue
, blue
+ cmap
->index
, cmap
->count
))) {
1105 vgaw (ba
, VDAC_ADDRESS_W
, cmap
->index
);
1106 x
= cmap
->count
- 1;
1108 rp
= red
+ cmap
->index
;
1109 gp
= green
+ cmap
->index
;
1110 bp
= blue
+ cmap
->index
;
1113 vgaw (ba
, VDAC_DATA
, *rp
++ >> 2);
1114 vgaw (ba
, VDAC_DATA
, *gp
++ >> 2);
1115 vgaw (ba
, VDAC_DATA
, *bp
++ >> 2);
1124 cv_toggle(struct grf_softc
*gp
)
1131 #endif /* !CV64CONSOLE */
1133 if (cv_pass_toggle
) {
1134 cvscreen(0, (volatile char*)ba
- 0x02000000);
1137 cvscreen(1, (volatile char*)ba
- 0x02000000);
1146 cv_mondefok(struct grfvideo_mode
*gv
)
1148 unsigned long maxpix
;
1150 if (gv
->mode_num
< 1 || gv
->mode_num
> monitor_def_max
) {
1151 if (gv
->mode_num
!= 255 || gv
->depth
!= 4)
1157 maxpix
= MAXPIXELCLOCK
- 55000000;
1160 maxpix
= MAXPIXELCLOCK
;
1164 #ifdef CV_AGGRESSIVE_TIMING
1165 maxpix
= MAXPIXELCLOCK
- 35000000;
1167 maxpix
= MAXPIXELCLOCK
- 55000000;
1172 #ifdef CV_AGGRESSIVE_TIMING
1173 maxpix
= MAXPIXELCLOCK
- 75000000;
1175 maxpix
= MAXPIXELCLOCK
- 85000000;
1179 printf("grfcv: Illegal depth in mode %d\n",
1180 (int) gv
->mode_num
);
1184 if (gv
->pixel_clock
> maxpix
) {
1185 printf("grfcv: Pixelclock too high in mode %d\n",
1186 (int) gv
->mode_num
);
1190 if (gv
->mode_num
== 255) { /* console mode */
1191 if ((gv
->disp_width
/ 8) > MAXCOLS
) {
1192 printf ("grfcv: Too many columns for console\n");
1194 } else if ((gv
->disp_height
/ S3FONTY
) > MAXROWS
) {
1195 printf ("grfcv: Too many rows for console\n");
1200 if (gv
->disp_flags
& GRF_FLAGS_SYNC_ON_GREEN
) {
1201 printf("grfcv: sync-on-green is not supported\n");
1210 cv_load_mon(struct grf_softc
*gp
, struct grfcvtext_mode
*md
)
1212 struct grfvideo_mode
*gv
;
1214 volatile void *ba
, *fb
;
1216 unsigned short HT
, HDE
, HBS
, HBE
, HSS
, HSE
, VDE
, VBS
, VBE
, VSS
,
1218 int cr50
, sr15
, sr18
, clock_mode
, test
;
1219 int m
, n
; /* For calc'ing display FIFO */
1220 int tfillm
, temptym
; /* FIFO fill and empty mclk's */
1221 int hmul
; /* Multiplier for hor. Values */
1222 unsigned char hvsync_pulse
;
1228 TEXT
= (gv
->depth
== 4);
1229 CONSOLE
= (gv
->mode_num
== 255);
1231 if (!cv_mondefok(gv
)) {
1232 printf("grfcv: Monitor definition not ok\n");
1239 /* Disable Interrupts */
1240 test
= RCrt(ba
, CRT_ID_BACKWAD_COMP_1
);
1242 WCrt(ba
, CRT_ID_BACKWAD_COMP_1
, test
);
1244 /* turn gfx off, don't mess up the display */
1247 /* provide all needed information in grf device-independent locations */
1248 gp
->g_data
= (void *) gv
;
1249 gi
= &gp
->g_display
;
1250 gi
->gd_colors
= 1 << gv
->depth
;
1251 gi
->gd_planes
= gv
->depth
;
1252 gi
->gd_fbwidth
= gv
->disp_width
;
1253 gi
->gd_fbheight
= gv
->disp_height
;
1257 gi
->gd_dwidth
= md
->fx
* md
->cols
;
1258 gi
->gd_dheight
= md
->fy
* md
->rows
;
1260 gi
->gd_dwidth
= gv
->disp_width
;
1261 gi
->gd_dheight
= gv
->disp_height
;
1266 /* get display mode parameters */
1267 switch (gv
->depth
) {
1277 HBS
= gv
->hblank_start
* hmul
;
1278 HSS
= gv
->hsync_start
* hmul
;
1279 HSE
= gv
->hsync_stop
* hmul
;
1280 HBE
= gv
->htotal
* hmul
- 6;
1281 HT
= gv
->htotal
* hmul
- 5;
1282 VBS
= gv
->vblank_start
- 1;
1283 VSS
= gv
->vsync_start
;
1284 VSE
= gv
->vsync_stop
;
1285 VBE
= gv
->vtotal
- 3;
1286 VT
= gv
->vtotal
- 2;
1288 /* Disable enhanced Mode for text display */
1290 vgaw(ba
, ECR_ADV_FUNC_CNTL
, (TEXT
? 0x00 : 0x31));
1293 HDE
= ((gv
->disp_width
+ md
->fx
- 1) / md
->fx
) - 1;
1295 HDE
= (gv
->disp_width
+ 3) * hmul
/ 8 - 1; /*HBS;*/
1296 VDE
= gv
->disp_height
- 1;
1300 if (gv
->disp_flags
& GRF_FLAGS_LACE
) {
1309 /* Horizontal/Vertical Sync Pulse */
1311 * GREG_MISC_OUTPUT_W Register:
1312 * bit description (0/1)
1313 * 0 Monochrome/Color emulation
1314 * 1 Disable/Enable access of the display memory from the CPU
1315 * 5 Select the low/high 64K page of memory
1316 * 6 Select a positive/negative horizontal retrace sync pulse
1317 * 7 Select a positive/negative vertical retrace sync pulse
1319 hvsync_pulse
= vgar(ba
, GREG_MISC_OUTPUT_R
);
1320 if (gv
->disp_flags
& GRF_FLAGS_PHSYNC
)
1321 hvsync_pulse
&= ~0x40;
1323 hvsync_pulse
|= 0x40;
1324 if (gv
->disp_flags
& GRF_FLAGS_PVSYNC
)
1325 hvsync_pulse
&= ~0x80;
1327 hvsync_pulse
|= 0x80;
1328 vgaw(ba
, GREG_MISC_OUTPUT_W
, hvsync_pulse
);
1330 /* GFX hardware cursor off */
1331 WCrt(ba
, CRT_ID_HWGC_MODE
, 0x00);
1332 WCrt(ba
, CRT_ID_EXT_DAC_CNTL
, 0x00);
1334 WSeq(ba
, SEQ_ID_MEMORY_MODE
, (TEXT
|| (gv
->depth
== 1)) ? 0x06 : 0x0e);
1335 WGfx(ba
, GCT_ID_READ_MAP_SELECT
, 0x00);
1336 WSeq(ba
, SEQ_ID_MAP_MASK
, (gv
->depth
== 1) ? 0x01 : 0xff);
1337 WSeq(ba
, SEQ_ID_CHAR_MAP_SELECT
, 0x00);
1341 mnr
= cv_compute_clock(gv
->pixel_clock
);
1342 WSeq(ba
, SEQ_ID_DCLK_HI
, ((mnr
& 0xFF00) >> 8));
1343 WSeq(ba
, SEQ_ID_DCLK_LO
, (mnr
& 0xFF));
1345 /* load display parameters into board */
1347 WCrt(ba
, CRT_ID_EXT_HOR_OVF
,
1348 ((HT
& 0x100) ? 0x01 : 0x00) |
1349 ((HDE
& 0x100) ? 0x02 : 0x00) |
1350 ((HBS
& 0x100) ? 0x04 : 0x00) |
1351 /* ((HBE & 0x40) ? 0x08 : 0x00) | */ /* Later... */
1352 ((HSS
& 0x100) ? 0x10 : 0x00) |
1353 /* ((HSE & 0x20) ? 0x20 : 0x00) | */
1354 (((HT
-5) & 0x100) ? 0x40 : 0x00) );
1356 WCrt(ba
, CRT_ID_EXT_VER_OVF
,
1357 0x40 | /* Line compare */
1358 ((VT
& 0x400) ? 0x01 : 0x00) |
1359 ((VDE
& 0x400) ? 0x02 : 0x00) |
1360 ((VBS
& 0x400) ? 0x04 : 0x00) |
1361 ((VSS
& 0x400) ? 0x10 : 0x00) );
1363 WCrt(ba
, CRT_ID_HOR_TOTAL
, HT
);
1364 WCrt(ba
, CRT_ID_DISPLAY_FIFO
, HT
- 5);
1366 WCrt(ba
, CRT_ID_HOR_DISP_ENA_END
, ((HDE
>= HBS
) ? (HBS
- 1) : HDE
));
1367 WCrt(ba
, CRT_ID_START_HOR_BLANK
, HBS
);
1368 WCrt(ba
, CRT_ID_END_HOR_BLANK
, ((HBE
& 0x1f) | 0x80));
1369 WCrt(ba
, CRT_ID_START_HOR_RETR
, HSS
);
1370 WCrt(ba
, CRT_ID_END_HOR_RETR
,
1372 ((HBE
& 0x20) ? 0x80 : 0x00) );
1373 WCrt(ba
, CRT_ID_VER_TOTAL
, VT
);
1374 WCrt(ba
, CRT_ID_OVERFLOW
,
1376 ((VT
& 0x100) ? 0x01 : 0x00) |
1377 ((VDE
& 0x100) ? 0x02 : 0x00) |
1378 ((VSS
& 0x100) ? 0x04 : 0x00) |
1379 ((VBS
& 0x100) ? 0x08 : 0x00) |
1380 ((VT
& 0x200) ? 0x20 : 0x00) |
1381 ((VDE
& 0x200) ? 0x40 : 0x00) |
1382 ((VSS
& 0x200) ? 0x80 : 0x00) );
1384 WCrt(ba
, CRT_ID_MAX_SCAN_LINE
,
1385 0x40 | /* TEXT ? 0x00 ??? */
1386 ((gv
->disp_flags
& GRF_FLAGS_DBLSCAN
) ? 0x80 : 0x00) |
1387 ((VBS
& 0x200) ? 0x20 : 0x00) |
1388 (TEXT
? ((md
->fy
- 1) & 0x1f) : 0x00));
1390 WCrt(ba
, CRT_ID_MODE_CONTROL
, 0xe3);
1396 WCrt(ba
, CRT_ID_CURSOR_START
, (md
->fy
& 0x1f) - 2);
1397 WCrt(ba
, CRT_ID_CURSOR_END
, (md
->fy
& 0x1f) - 1);
1399 WCrt(ba
, CRT_ID_CURSOR_START
, 0x00);
1400 WCrt(ba
, CRT_ID_CURSOR_END
, md
->fy
& 0x1f);
1402 WCrt(ba
, CRT_ID_UNDERLINE_LOC
, (md
->fy
- 1) & 0x1f);
1404 WCrt(ba
, CRT_ID_CURSOR_LOC_HIGH
, 0x00);
1405 WCrt(ba
, CRT_ID_CURSOR_LOC_LOW
, 0x00);
1408 WCrt(ba
, CRT_ID_START_ADDR_HIGH
, 0x00);
1409 WCrt(ba
, CRT_ID_START_ADDR_LOW
, 0x00);
1411 WCrt(ba
, CRT_ID_START_VER_RETR
, VSS
);
1412 WCrt(ba
, CRT_ID_END_VER_RETR
, (VSE
& 0x0f));
1413 WCrt(ba
, CRT_ID_VER_DISP_ENA_END
, VDE
);
1414 WCrt(ba
, CRT_ID_START_VER_BLANK
, VBS
);
1415 WCrt(ba
, CRT_ID_END_VER_BLANK
, VBE
);
1417 WCrt(ba
, CRT_ID_LINE_COMPARE
, 0xff);
1418 WCrt(ba
, CRT_ID_LACE_RETR_START
, HT
/ 2);
1419 WCrt(ba
, CRT_ID_LACE_CONTROL
,
1420 ((gv
->disp_flags
& GRF_FLAGS_LACE
) ? 0x20 : 0x00));
1422 WGfx(ba
, GCT_ID_GRAPHICS_MODE
,
1423 ((TEXT
|| (gv
->depth
== 1)) ? 0x00 : 0x40));
1424 WGfx(ba
, GCT_ID_MISC
, (TEXT
? 0x04 : 0x01));
1426 WSeq (ba
, SEQ_ID_MEMORY_MODE
,
1427 ((TEXT
|| (gv
->depth
== 1)) ? 0x06 : 0x02));
1429 vgaw(ba
, VDAC_MASK
, 0xff);
1432 test
= RCrt(ba
, CRT_ID_BACKWAD_COMP_2
);
1433 WCrt(ba
, CRT_ID_BACKWAD_COMP_2
, (test
| 0x20));
1435 sr15
= RSeq(ba
, SEQ_ID_CLKSYN_CNTL_2
);
1437 sr18
= RSeq(ba
, SEQ_ID_RAMDAC_CNTL
);
1442 test
= RCrt(ba
, CRT_ID_EXT_MISC_CNTL_2
);
1445 /* clear roxxler byte-swapping... */
1446 cv_write_port(0x0040, cv_boardaddr
);
1447 cv_write_port(0x0020, cv_boardaddr
);
1449 switch (gv
->depth
) {
1452 HDE
= gv
->disp_width
/ 16;
1455 if (gv
->pixel_clock
> 80000000) {
1456 clock_mode
= 0x10 | 0x02;
1460 HDE
= gv
->disp_width
/ 8;
1464 cv_write_port (0x8020, cv_boardaddr
);
1466 HDE
= gv
->disp_width
/ 4;
1470 cv_write_port (0x8020, cv_boardaddr
);
1472 HDE
= gv
->disp_width
/ 4;
1475 case 24: /* this is really 32 Bit on CV64 */
1477 cv_write_port(0x8040, cv_boardaddr
);
1479 HDE
= (gv
->disp_width
/ 2);
1484 WCrt(ba
, CRT_ID_EXT_MISC_CNTL_2
, clock_mode
| test
);
1485 WSeq(ba
, SEQ_ID_CLKSYN_CNTL_2
, sr15
);
1486 WSeq(ba
, SEQ_ID_RAMDAC_CNTL
, sr18
);
1487 WCrt(ba
, CRT_ID_SCREEN_OFFSET
, HDE
);
1489 WCrt(ba
, CRT_ID_MISC_1
, (TEXT
? 0x05 : 0x35));
1491 test
= RCrt(ba
, CRT_ID_EXT_SYS_CNTL_2
);
1493 /* HDE Overflow in bits 4-5 */
1494 test
|= (HDE
>> 4) & 0x30;
1495 WCrt(ba
, CRT_ID_EXT_SYS_CNTL_2
, test
);
1497 /* Set up graphics engine */
1498 switch (gv
->disp_width
) {
1517 default: /* XXX The Xserver has to handle this */
1521 WCrt(ba
, CRT_ID_EXT_SYS_CNTL_1
, cr50
);
1524 WAttr(ba
, ACT_ID_ATTR_MODE_CNTL
, (TEXT
? 0x08 : 0x41));
1526 WAttr(ba
, ACT_ID_COLOR_PLANE_ENA
,
1527 (gv
->depth
== 1) ? 0x01 : 0x0f);
1531 * M-Parameter of Display FIFO
1532 * This is dependant on the pixel clock and the memory clock.
1533 * The FIFO filling bandwidth is 240 MHz and the FIFO is 96 Byte wide.
1534 * Then the time to fill the FIFO is tfill = (96/240000000) sec, the time
1535 * to empty the FIFO is tempty = (96/pixelclock) sec.
1536 * Then the M parameter maximum is ((tempty-tfill)*cv_memclk-9)/2.
1537 * This seems to be logical, ain't it?
1538 * Remember: We have to use integer arithmetics :(
1539 * Divide by 1000 to prevent overflows.
1542 tfillm
= (96 * (cv_memclk
/1000))/240000;
1547 temptym
= (24 * (cv_memclk
/1000)) / (gv
->pixel_clock
/1000);
1551 temptym
= (48 * (cv_memclk
/1000)) / (gv
->pixel_clock
/1000);
1554 temptym
= (192 * (cv_memclk
/1000)) / (gv
->pixel_clock
/1000);
1557 temptym
= (96 * (cv_memclk
/1000)) / (gv
->pixel_clock
/1000);
1561 m
= (temptym
- tfillm
- 9) / 2;
1563 m
= 0; /* prevent underflow */
1564 m
= (m
& 0x1f) << 3;
1569 WCrt(ba
, CRT_ID_EXT_MEM_CNTL_2
, m
);
1570 WCrt(ba
, CRT_ID_EXT_MEM_CNTL_3
, n
);
1573 /* text initialization */
1576 cv_inittextmode(gp
);
1581 vgaw(ba
, VDAC_ADDRESS_W
, 0);
1582 for (i
= 0; i
< 16; i
++) {
1583 vgaw(ba
, VDAC_DATA
, cvconscolors
[i
][0]);
1584 vgaw(ba
, VDAC_DATA
, cvconscolors
[i
][1]);
1585 vgaw(ba
, VDAC_DATA
, cvconscolors
[i
][2]);
1589 /* Set display enable flag */
1592 /* turn gfx on again */
1595 /* enable interrupts */
1596 test
= RCrt(ba
, CRT_ID_BACKWAD_COMP_1
);
1598 WCrt(ba
, CRT_ID_BACKWAD_COMP_1
, test
);
1600 test
= RCrt(ba
, CRT_ID_END_VER_RETR
);
1602 WCrt(ba
, CRT_ID_END_VER_RETR
, test
);
1604 WCrt(ba
, CRT_ID_END_VER_RETR
, test
);
1606 WCrt(ba
, CRT_ID_END_VER_RETR
, test
);
1607 #ifndef CV_NO_HARDWARE_CURSOR
1612 cvscreen(0, (volatile char*)ba
- 0x02000000);
1619 cv_inittextmode(struct grf_softc
*gp
)
1621 struct grfcvtext_mode
*tm
= (struct grfcvtext_mode
*)gp
->g_data
;
1622 volatile void *ba
, *fb
;
1623 volatile unsigned char *c
;
1624 unsigned char *f
, y
;
1630 /* load text font into beginning of display memory.
1631 * Each character cell is 32 bytes long (enough for 4 planes)
1632 * In linear addressing text mode, the memory is organized
1633 * so, that the Bytes of all 4 planes are interleaved.
1634 * 1st byte plane 0, 1st byte plane 1, 1st byte plane 2,
1635 * 1st byte plane 3, 2nd byte plane 0, 2nd byte plane 1,...
1636 * The font is loaded in plane 2.
1639 c
= (volatile unsigned char *) fb
;
1642 for (z
= 0; z
< tm
->cols
* tm
->rows
* 3; z
++) {
1649 c
= (volatile unsigned char *)fb
+ (32 * tm
->fdstart
* 4 + 2);
1651 for (z
= tm
->fdstart
; z
<= tm
->fdend
; z
++, c
+= (32 - tm
->fy
) * 4)
1652 for (y
= 0; y
< tm
->fy
; y
++) {
1657 /* print out a little init msg */
1658 c
= (volatile unsigned char *)fb
+ (tm
->cols
- 6) * 4;
1674 cv_write_port(unsigned short bits
, volatile void *BoardAddr
)
1676 volatile char *addr
;
1677 static unsigned char CVPortBits
= 0; /* mirror port bits here */
1679 addr
= (volatile char*)BoardAddr
+ 0x40001;
1681 CVPortBits
|= bits
& 0xFF; /* Set bits */
1684 bits
= (~bits
) & 0xFF ;
1685 CVPortBits
&= bits
; /* Clear bits */
1694 * 0 = CyberVision Signal
1699 cvscreen(int toggle
, volatile void *ba
)
1703 cv_write_port (0x10, ba
);
1705 cv_write_port (0x8010, ba
);
1709 /* 0 = on, 1= off */
1710 /* ba= registerbase */
1712 gfx_on_off(int toggle
, volatile void *ba
)
1717 toggle
= toggle
<< 5;
1719 r
= RSeq(ba
, SEQ_ID_CLOCKING_MODE
);
1720 r
&= ~0x20; /* set Bit 5 to 0 */
1722 WSeq(ba
, SEQ_ID_CLOCKING_MODE
, r
| toggle
);
1726 #ifndef CV_NO_HARDWARE_CURSOR
1728 static unsigned char cv_hotx
= 0, cv_hoty
= 0;
1729 static char cv_cursor_on
= 0;
1731 /* Hardware Cursor handling routines */
1734 cv_getspritepos(struct grf_softc
*gp
, struct grf_position
*pos
)
1737 volatile void *ba
= gp
->g_regkva
;
1739 hi
= RCrt(ba
, CRT_ID_HWGC_ORIGIN_Y_HI
);
1740 lo
= RCrt(ba
, CRT_ID_HWGC_ORIGIN_Y_LO
);
1742 pos
->y
= (hi
<< 8) + lo
;
1743 hi
= RCrt(ba
, CRT_ID_HWGC_ORIGIN_X_HI
);
1744 lo
= RCrt(ba
, CRT_ID_HWGC_ORIGIN_X_LO
);
1745 pos
->x
= (hi
<< 8) + lo
;
1751 cv_setspritepos(struct grf_softc
*gp
, struct grf_position
*pos
)
1753 volatile void *ba
= gp
->g_regkva
;
1755 static short savex
, savey
;
1763 } else { /* restore cursor */
1770 xoff
= ((-x
) & 0xFE);
1777 yoff
= ((-y
) & 0xFE);
1783 WCrt(ba
, CRT_ID_HWGC_ORIGIN_X_HI
, (x
>> 8));
1784 WCrt(ba
, CRT_ID_HWGC_ORIGIN_X_LO
, (x
& 0xff));
1786 WCrt(ba
, CRT_ID_HWGC_ORIGIN_Y_LO
, (y
& 0xff));
1787 WCrt(ba
, CRT_ID_HWGC_DSTART_X
, xoff
);
1788 WCrt(ba
, CRT_ID_HWGC_DSTART_Y
, yoff
);
1789 WCrt(ba
, CRT_ID_HWGC_ORIGIN_Y_HI
, (y
>> 8));
1797 return ( ((val
& 0xff00) >> 8) | ((val
& 0xff) << 8));
1801 cv_getspriteinfo(struct grf_softc
*gp
, struct grf_spriteinfo
*info
)
1803 volatile void *ba
, *fb
;
1808 if (info
->set
& GRFSPRSET_ENABLE
)
1809 info
->enable
= RCrt(ba
, CRT_ID_HWGC_MODE
) & 0x01;
1811 if (info
->set
& GRFSPRSET_POS
)
1812 cv_getspritepos (gp
, &info
->pos
);
1815 if (info
->set
& GRFSPRSET_SHAPE
) {
1816 u_char image
[512], mask
[512];
1817 volatile u_long
*hwp
;
1822 for (row
= 0, hwp
= (u_long
*)(fb
+ HWC_OFF
),
1823 mp
= mask
, imp
= image
;
1826 u_long bp10
, bp20
, bp11
, bp21
;
1835 *imp
++ = (~bp10
) & bp11
;
1836 *imp
++ = (~bp20
) & bp21
;
1837 *mp
++ = (~bp10
) | (bp10
& ~bp11
);
1838 *mp
++ = (~bp20
) & (bp20
& ~bp21
);
1840 copyout (image
, info
->image
, sizeof (image
));
1841 copyout (mask
, info
->mask
, sizeof (mask
));
1849 cv_setup_hwc(struct grf_softc
*gp
)
1851 volatile void *ba
= gp
->g_regkva
;
1855 if (gp
->g_display
.gd_planes
<= 4)
1856 cv_cursor_on
= 0; /* don't enable hwc in text modes */
1857 if (cv_cursor_on
== 0)
1860 /* reset colour stack */
1861 #if !defined(__m68k__)
1862 test
= RCrt(ba
, CRT_ID_HWGC_MODE
);
1865 /* do it in assembler, the above does't seem to work */
1866 __asm
volatile ("moveb #0x45, %1@(0x3d4); \
1867 moveb %1@(0x3d5),%0" : "=d" (test
) : "a" (ba
));
1870 WCrt (ba
, CRT_ID_HWGC_FG_STACK
, 0);
1872 hwc
= (volatile char*)ba
+ CRT_ADDRESS_W
;
1876 #if !defined(__m68k__)
1877 test
= RCrt(ba
, CRT_ID_HWGC_MODE
);
1880 /* do it in assembler, the above does't seem to work */
1881 __asm
volatile ("moveb #0x45, %1@(0x3d4); \
1882 moveb %1@(0x3d5),%0" : "=d" (test
) : "a" (ba
));
1884 switch (gp
->g_display
.gd_planes
) {
1886 WCrt (ba
, CRT_ID_HWGC_BG_STACK
, 0x1);
1890 WCrt (ba
, CRT_ID_HWGC_BG_STACK
, 0xff);
1895 test
= HWC_OFF
/ HWC_SIZE
;
1896 WCrt (ba
, CRT_ID_HWGC_START_AD_HI
, (test
>> 8));
1897 WCrt (ba
, CRT_ID_HWGC_START_AD_LO
, (test
& 0xff));
1899 WCrt (ba
, CRT_ID_HWGC_DSTART_X
, 0);
1900 WCrt (ba
, CRT_ID_HWGC_DSTART_Y
, 0);
1902 WCrt (ba
, CRT_ID_EXT_DAC_CNTL
, 0x10); /* Cursor X11 Mode */
1904 * Put it into Windoze Mode or you'll see sometimes a white stripe
1905 * on the right side (in double clocking modes with a screen bigger
1908 WCrt (ba
, CRT_ID_EXT_DAC_CNTL
, 0x00); /* Cursor Windoze Mode */
1910 WCrt (ba
, CRT_ID_HWGC_MODE
, 0x01);
1915 * This was the reason why you shouldn't use the HWC in the Kernel:(
1916 * Obsoleted now by use of interrupts :-)
1919 #define VerticalRetraceWait(ba) \
1921 while (vgar(ba, GREG_INPUT_STATUS1_R) == 0x00) ; \
1922 while ((vgar(ba, GREG_INPUT_STATUS1_R) & 0x08) == 0x08) ; \
1923 while ((vgar(ba, GREG_INPUT_STATUS1_R) & 0x08) == 0x00) ; \
1928 cv_setspriteinfo(struct grf_softc
*gp
, struct grf_spriteinfo
*info
)
1930 volatile void *ba
, *fb
;
1931 int depth
= gp
->g_display
.gd_planes
;
1936 if (info
->set
& GRFSPRSET_SHAPE
) {
1938 * For an explanation of these weird actions here, see above
1939 * when reading the shape. We set the shape directly into
1940 * the video memory, there's no reason to keep 1k on the
1941 * kernel stack just as template
1943 u_char
*image
, *mask
;
1944 volatile u_short
*hwp
;
1950 WCrt (ba
, CRT_ID_HWGC_MODE
, 0x00);
1953 * The Trio64 crashes if the cursor data is written
1954 * while the cursor is displayed.
1955 * Sadly, turning the cursor off is not enough.
1956 * What we have to do is:
1957 * 1. Wait for vertical retrace, to make sure no-one
1958 * has moved the cursor in this sync period (because
1959 * another write then would have no effect, argh!).
1960 * 2. Move the cursor off-screen
1961 * 3. Another wait for v. retrace to make sure the cursor
1963 * 4. Write the data, finally.
1964 * (thanks to Harald Koenig for this tip!)
1968 * Remark 06/06/96: Update in interrupt obsoletes this,
1969 * but the warning should stay there!
1972 VerticalRetraceWait(ba
);
1974 WCrt (ba
, CRT_ID_HWGC_ORIGIN_X_HI
, 0x7);
1975 WCrt (ba
, CRT_ID_HWGC_ORIGIN_X_LO
, 0xff);
1976 WCrt (ba
, CRT_ID_HWGC_ORIGIN_Y_LO
, 0xff);
1977 WCrt (ba
, CRT_ID_HWGC_DSTART_X
, 0x3f);
1978 WCrt (ba
, CRT_ID_HWGC_DSTART_Y
, 0x3f);
1979 WCrt (ba
, CRT_ID_HWGC_ORIGIN_Y_HI
, 0x7);
1980 #endif /* CV_NO_INT */
1982 if (info
->size
.y
> 64)
1984 if (info
->size
.x
> 64)
1986 if (info
->size
.x
< 32)
1989 image
= malloc(HWC_SIZE
, M_TEMP
, M_WAITOK
);
1990 mask
= image
+ HWC_SIZE
/2;
1992 copyin(info
->image
, image
, info
->size
.y
* info
->size
.x
/ 8);
1993 copyin(info
->mask
, mask
, info
->size
.y
* info
->size
.x
/ 8);
1996 hwp
= (u_short
*)(fb
+HWC_OFF
);
1998 /* This is necessary in order not to crash the board */
1999 VerticalRetraceWait(ba
);
2000 #else /* CV_NO_INT */
2001 hwp
= (u_short
*) cv_cursor_storage
;
2002 #endif /* CV_NO_INT */
2005 * setting it is slightly more difficult, because we can't
2006 * force the application to not pass a *smaller* than
2010 for (row
= 0, mp
= mask
, imp
= image
;
2011 row
< info
->size
.y
; row
++) {
2012 u_short im1
, im2
, im3
, im4
, m1
, m2
, m3
, m4
;
2014 m1
= ~(*(unsigned short *)mp
);
2015 im1
= *(unsigned short *)imp
& *(unsigned short *)mp
;
2019 m2
= ~(*(unsigned short *)mp
);
2020 im2
= *(unsigned short *)imp
& *(unsigned short *)mp
;
2024 if (info
->size
.x
> 32) {
2025 m3
= ~(*(unsigned short *)mp
);
2026 im3
= *(unsigned short *)imp
& *(unsigned short *)mp
;
2029 m4
= ~(*(unsigned short *)mp
);
2030 im4
= *(unsigned short *)imp
& *(unsigned short *)mp
;
2077 for (; row
< 64; row
++) {
2088 for (; row
< 64; row
++) {
2100 free(image
, M_TEMP
);
2101 /* cv_setup_hwc(gp); */
2102 cv_hotx
= info
->hot
.x
;
2103 cv_hoty
= info
->hot
.y
;
2106 /* One must not write twice per vertical blank :-( */
2107 VerticalRetraceWait(ba
);
2108 cv_setspritepos (gp
, &info
->pos
);
2109 #else /* CV_NO_INT */
2110 cv_setspritepos (gp
, &info
->pos
);
2111 curs_update_flag
= 1;
2112 #endif /* CV_NO_INT */
2114 if (info
->set
& GRFSPRSET_CMAP
) {
2118 /* reset colour stack */
2119 test
= RCrt(ba
, CRT_ID_HWGC_MODE
);
2125 WCrt (ba
, CRT_ID_HWGC_FG_STACK
, 0);
2126 hwc
= (volatile char*)ba
+ CRT_ADDRESS_W
;
2131 WCrt (ba
, CRT_ID_HWGC_FG_STACK
, 0);
2132 hwc
= (volatile char*)ba
+ CRT_ADDRESS_W
;
2138 test
= RCrt(ba
, CRT_ID_HWGC_MODE
);
2142 WCrt (ba
, CRT_ID_HWGC_BG_STACK
, 1);
2143 hwc
= (volatile char*)ba
+ CRT_ADDRESS_W
;
2148 WCrt (ba
, CRT_ID_HWGC_BG_STACK
, 0xff);
2149 hwc
= (volatile char*)ba
+ CRT_ADDRESS_W
;
2154 WCrt (ba
, CRT_ID_HWGC_BG_STACK
, 0xff);
2155 hwc
= (volatile char*)ba
+ CRT_ADDRESS_W
;
2162 if (info
->set
& GRFSPRSET_ENABLE
) {
2166 /* WCrt(ba, CRT_ID_HWGC_MODE, 0x01); */
2168 WCrt(ba
, CRT_ID_HWGC_MODE
, 0x00);
2170 if (info
->set
& GRFSPRSET_POS
)
2171 cv_setspritepos(gp
, &info
->pos
);
2172 if (info
->set
& GRFSPRSET_HOT
) {
2174 cv_hotx
= info
->hot
.x
;
2175 cv_hoty
= info
->hot
.y
;
2176 cv_setspritepos (gp
, &info
->pos
);
2183 cv_getspritemax (struct grf_softc
*gp
, struct grf_position
*pos
)
2191 #endif /* !CV_NO_HARDWARE_CURSOR */