1 /* $NetBSD: grf_cv.c,v 1.16 1996/08/27 21:54:48 cgd Exp $ */ 2 3 /* 4 * Copyright (c) 1995 Michael Teske 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 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 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 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 "grfcv.h" 34 #if NGRFCV > 0 35 36 /* 37 * Graphics routines for the CyberVision 64 board, using the S3 Trio64. 38 * 39 * Modified for CV64 from 40 * Kari Mettinen's Cirrus driver by Michael Teske 10/95 41 * For questions mail me at teske@mail.desy.de 42 * 43 * Thanks to Tekelec Airtronic for providing me with a S3 Trio64 documentation. 44 * Thanks to Bernd 'the fabulous bug-finder' Ernesti for bringing my messy 45 * source to NetBSD style :) 46 * 47 * TODO: 48 * Bugfree Hardware Cursor support. 49 * The HWC routines provided here are buggy in 16/24 bit 50 * and may cause a Vertical Bar Crash of the Trio64. 51 * On the other hand it's better to put the routines in the Xserver, 52 * so please _don't_ put CV_HARDWARE_CURSOR in your config file. 53 */ 54 55 #include <sys/param.h> 56 #include <sys/errno.h> 57 #include <sys/ioctl.h> 58 #include <sys/device.h> 59 #include <sys/malloc.h> 60 #include <sys/systm.h> 61 #include <machine/cpu.h> 62 #include <dev/cons.h> 63 #include <amiga/dev/itevar.h> 64 #include <amiga/amiga/device.h> 65 #include <amiga/dev/grfioctl.h> 66 #include <amiga/dev/grfvar.h> 67 #include <amiga/dev/grf_cvreg.h> 68 #include <amiga/dev/zbusvar.h> 69 70 int grfcvmatch __P((struct device *, void *, void *)); 71 void grfcvattach __P((struct device *, struct device *, void *)); 72 int grfcvprint __P((void *, const char *)); 73 74 static int cv_has_4mb __P((volatile caddr_t)); 75 static unsigned short cv_compute_clock __P((unsigned long)); 76 void cv_boardinit __P((struct grf_softc *)); 77 int cv_getvmode __P((struct grf_softc *, struct grfvideo_mode *)); 78 int cv_setvmode __P((struct grf_softc *, unsigned int)); 79 int cv_blank __P((struct grf_softc *, int *)); 80 int cv_mode __P((register struct grf_softc *, u_long, void *, u_long, int)); 81 int cv_ioctl __P((register struct grf_softc *gp, u_long cmd, void *data)); 82 int cv_setmonitor __P((struct grf_softc *, struct grfvideo_mode *)); 83 int cv_getcmap __P((struct grf_softc *, struct grf_colormap *)); 84 int cv_putcmap __P((struct grf_softc *, struct grf_colormap *)); 85 int cv_toggle __P((struct grf_softc *)); 86 int cv_mondefok __P((struct grfvideo_mode *)); 87 int cv_load_mon __P((struct grf_softc *, struct grfcvtext_mode *)); 88 void cv_inittextmode __P((struct grf_softc *)); 89 static inline void cv_write_port __P((unsigned short, volatile caddr_t)); 90 static inline void cvscreen __P((int, volatile caddr_t)); 91 static inline void gfx_on_off __P((int, volatile caddr_t)); 92 93 #ifdef CV_HARDWARE_CURSOR 94 int cv_getspritepos __P((struct grf_softc *, struct grf_position *)); 95 int cv_setspritepos __P((struct grf_softc *, struct grf_position *)); 96 int cv_getspriteinfo __P((struct grf_softc *,struct grf_spriteinfo *)); 97 void cv_setup_hwc __P((struct grf_softc *, 98 unsigned char, unsigned char, unsigned char, unsigned char, 99 const unsigned long *)); 100 int cv_setspriteinfo __P((struct grf_softc *,struct grf_spriteinfo *)); 101 int cv_getspritemax __P((struct grf_softc *,struct grf_position *)); 102 #endif /* CV_HARDWARE_CURSOR */ 103 104 /* Graphics display definitions. 105 * These are filled by 'grfconfig' using GRFIOCSETMON. 106 */ 107 #define monitor_def_max 24 108 static struct grfvideo_mode monitor_def[24] = { 109 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, 110 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, 111 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0} 112 }; 113 static struct grfvideo_mode *monitor_current = &monitor_def[0]; 114 #define MAXPIXELCLOCK 135000000 /* safety */ 115 116 117 /* Console display definition. 118 * Default hardcoded text mode. This grf_cv is set up to 119 * use one text mode only, and this is it. You may use 120 * grfconfig to change the mode after boot. 121 */ 122 123 /* Console font */ 124 #ifdef KFONT_8X11 125 #define S3FONT kernel_font_8x11 126 #define S3FONTY 11 127 #else 128 #define S3FONT kernel_font_8x8 129 #define S3FONTY 8 130 #endif 131 extern unsigned char S3FONT[]; 132 133 /* 134 * Define default console mode 135 * (Internally, we still have to use hvalues/8!) 136 */ 137 struct grfcvtext_mode cvconsole_mode = { 138 {255, "", 25000000, 640, 480, 4, 640/8, 784/8, 680/8, 768/8, 800/8, 139 481, 521, 491, 493, 525}, 140 8, S3FONTY, 80, 480 / S3FONTY, S3FONT, 32, 255 141 }; 142 143 /* Console colors */ 144 unsigned char cvconscolors[16][3] = { /* background, foreground, hilite */ 145 /* R G B */ 146 {0x30, 0x30, 0x30}, 147 {0x00, 0x00, 0x00}, 148 {0x80, 0x00, 0x00}, 149 {0x00, 0x80, 0x00}, 150 {0x00, 0x00, 0x80}, 151 {0x80, 0x80, 0x00}, 152 {0x00, 0x80, 0x80}, 153 {0x80, 0x00, 0x80}, 154 {0xff, 0xff, 0xff}, 155 {0x40, 0x40, 0x40}, 156 {0xff, 0x00, 0x00}, 157 {0x00, 0xff, 0x00}, 158 {0x00, 0x00, 0xff}, 159 {0xff, 0xff, 0x00}, 160 {0x00, 0xff, 0xff}, 161 {0x00, 0x00, 0xff} 162 }; 163 164 static unsigned char clocks[]={ 165 0x13, 0x61, 0x6b, 0x6d, 0x51, 0x69, 0x54, 0x69, 166 0x4f, 0x68, 0x6b, 0x6b, 0x18, 0x61, 0x7b, 0x6c, 167 0x51, 0x67, 0x24, 0x62, 0x56, 0x67, 0x77, 0x6a, 168 0x1d, 0x61, 0x53, 0x66, 0x6b, 0x68, 0x79, 0x69, 169 0x7c, 0x69, 0x7f, 0x69, 0x22, 0x61, 0x54, 0x65, 170 0x56, 0x65, 0x58, 0x65, 0x67, 0x66, 0x41, 0x63, 171 0x27, 0x61, 0x13, 0x41, 0x37, 0x62, 0x6b, 0x4d, 172 0x23, 0x43, 0x51, 0x49, 0x79, 0x66, 0x54, 0x49, 173 0x7d, 0x66, 0x34, 0x56, 0x4f, 0x63, 0x1f, 0x42, 174 0x6b, 0x4b, 0x7e, 0x4d, 0x18, 0x41, 0x2a, 0x43, 175 0x7b, 0x4c, 0x74, 0x4b, 0x51, 0x47, 0x65, 0x49, 176 0x24, 0x42, 0x68, 0x49, 0x56, 0x47, 0x75, 0x4a, 177 0x77, 0x4a, 0x31, 0x43, 0x1d, 0x41, 0x71, 0x49, 178 0x53, 0x46, 0x29, 0x42, 0x6b, 0x48, 0x1f, 0x41, 179 0x79, 0x49, 0x6f, 0x48, 0x7c, 0x49, 0x38, 0x43, 180 0x7f, 0x49, 0x5d, 0x46, 0x22, 0x41, 0x53, 0x45, 181 0x54, 0x45, 0x55, 0x45, 0x56, 0x45, 0x57, 0x45, 182 0x58, 0x45, 0x25, 0x41, 0x67, 0x46, 0x5b, 0x45, 183 0x41, 0x43, 0x78, 0x47, 0x27, 0x41, 0x51, 0x44, 184 0x13, 0x21, 0x7d, 0x47, 0x37, 0x42, 0x71, 0x46, 185 0x6b, 0x2d, 0x14, 0x21, 0x23, 0x23, 0x7d, 0x2f, 186 0x51, 0x29, 0x61, 0x2b, 0x79, 0x46, 0x1d, 0x22, 187 0x54, 0x29, 0x45, 0x27, 0x7d, 0x46, 0x7f, 0x46, 188 0x4f, 0x43, 0x2f, 0x41, 0x1f, 0x22, 0x6a, 0x2b, 189 0x6b, 0x2b, 0x5b, 0x29, 0x7e, 0x2d, 0x65, 0x44, 190 0x18, 0x21, 0x5e, 0x29, 0x2a, 0x23, 0x45, 0x26, 191 0x7b, 0x2c, 0x19, 0x21, 0x74, 0x2b, 0x75, 0x2b, 192 0x51, 0x27, 0x3f, 0x25, 0x65, 0x29, 0x40, 0x25, 193 0x24, 0x22, 0x41, 0x25, 0x68, 0x29, 0x42, 0x25, 194 0x56, 0x27, 0x7e, 0x2b, 0x75, 0x2a, 0x1c, 0x21, 195 0x77, 0x2a, 0x4f, 0x26, 0x31, 0x23, 0x6f, 0x29, 196 0x1d, 0x21, 0x32, 0x23, 0x71, 0x29, 0x72, 0x29, 197 0x53, 0x26, 0x69, 0x28, 0x29, 0x22, 0x75, 0x29, 198 0x6b, 0x28, 0x1f, 0x21, 0x1f, 0x21, 0x6d, 0x28, 199 0x79, 0x29, 0x2b, 0x22, 0x6f, 0x28, 0x59, 0x26, 200 0x7c, 0x29, 0x7d, 0x29, 0x38, 0x23, 0x21, 0x21, 201 0x7f, 0x29, 0x39, 0x23, 0x5d, 0x26, 0x75, 0x28, 202 0x22, 0x21, 0x77, 0x28, 0x53, 0x25, 0x6c, 0x27, 203 0x54, 0x25, 0x61, 0x26, 0x55, 0x25, 0x30, 0x22, 204 0x56, 0x25, 0x63, 0x26, 0x57, 0x25, 0x71, 0x27, 205 0x58, 0x25, 0x7f, 0x28, 0x25, 0x21, 0x74, 0x27, 206 0x67, 0x26, 0x40, 0x23, 0x5b, 0x25, 0x26, 0x21, 207 0x41, 0x23, 0x34, 0x22, 0x78, 0x27, 0x6b, 0x26, 208 0x27, 0x21, 0x35, 0x22, 0x51, 0x24, 0x7b, 0x27, 209 0x13, 0x1, 0x13, 0x1, 0x7d, 0x27, 0x4c, 0x9, 210 0x37, 0x22, 0x5b, 0xb, 0x71, 0x26, 0x5c, 0xb, 211 0x6b, 0xd, 0x47, 0x23, 0x14, 0x1, 0x4f, 0x9, 212 0x23, 0x3, 0x75, 0x26, 0x7d, 0xf, 0x1c, 0x2, 213 0x51, 0x9, 0x59, 0x24, 0x61, 0xb, 0x69, 0x25, 214 0x79, 0x26, 0x34, 0x5, 0x1d, 0x2, 0x6b, 0x25, 215 0x54, 0x9, 0x35, 0x5, 0x45, 0x7, 0x6d, 0x25, 216 0x7d, 0x26, 0x16, 0x1, 0x7f, 0x26, 0x77, 0xd, 217 0x4f, 0x23, 0x78, 0xd, 0x2f, 0x21, 0x27, 0x3, 218 0x1f, 0x2, 0x59, 0x9, 0x6a, 0xb, 0x73, 0x25, 219 0x6b, 0xb, 0x63, 0x24, 0x5b, 0x9, 0x20, 0x2, 220 0x7e, 0xd, 0x4b, 0x7, 0x65, 0x24, 0x43, 0x22, 221 0x18, 0x1, 0x6f, 0xb, 0x5e, 0x9, 0x70, 0xb, 222 0x2a, 0x3, 0x33, 0x4, 0x45, 0x6, 0x60, 0x9, 223 0x7b, 0xc, 0x19, 0x1, 0x19, 0x1, 0x7d, 0xc, 224 0x74, 0xb, 0x50, 0x7, 0x75, 0xb, 0x63, 0x9, 225 0x51, 0x7, 0x23, 0x2, 0x3f, 0x5, 0x1a, 0x1, 226 0x65, 0x9, 0x2d, 0x3, 0x40, 0x5, 0x0, 0x0, 227 }; 228 229 230 /* Board Address of CV64 */ 231 static volatile caddr_t cv_boardaddr; 232 static int cv_fbsize; 233 234 /* 235 * Memory clock (binpatchable). 236 * Let's be defensive: 50 MHz runs on all boards I know of. 237 * 55 MHz runs on most boards. But you should know what you're doing 238 * if you set this flag. Again: This flag may destroy your CV Board. 239 * Use it at your own risk!!! 240 * Anyway, this doesn't imply that I'm responsible if your board breaks 241 * without setting this flag :-). 242 */ 243 #ifdef CV_AGGRESSIVE_TIMING 244 long cv_memclk = 55000000; 245 #else 246 long cv_memclk = 50000000; 247 #endif 248 249 /* standard driver stuff */ 250 struct cfattach grfcv_ca = { 251 sizeof(struct grf_softc), grfcvmatch, grfcvattach 252 }; 253 254 struct cfdriver grfcv_cd = { 255 NULL, "grfcv", DV_DULL, NULL, 0 256 }; 257 static struct cfdata *cfdata; 258 259 260 /* 261 * Get frambuffer memory size. 262 * phase5 didn't provide the bit in CR36, 263 * so we have to do it this way. 264 * Return 0 for 2MB, 1 for 4MB 265 */ 266 static int 267 cv_has_4mb(fb) 268 volatile caddr_t fb; 269 { 270 volatile unsigned long *testfbw, *testfbr; 271 272 /* write patterns in memory and test if they can be read */ 273 testfbw = (volatile unsigned long *)fb; 274 testfbr = (volatile unsigned long *)(fb + 0x02000000); 275 *testfbw = 0x87654321; 276 if (*testfbr != 0x87654321) 277 return (0); 278 279 /* upper memory region */ 280 testfbw = (volatile unsigned long *)(fb + 0x00200000); 281 testfbr = (volatile unsigned long *)(fb + 0x02200000); 282 *testfbw = 0x87654321; 283 if (*testfbr != 0x87654321) 284 return (0); 285 *testfbw = 0xAAAAAAAA; 286 if (*testfbr != 0xAAAAAAAA) 287 return (0); 288 *testfbw = 0x55555555; 289 if (*testfbr != 0x55555555) 290 return (0); 291 return (1); 292 } 293 294 int 295 grfcvmatch(pdp, match, auxp) 296 struct device *pdp; 297 void *match, *auxp; 298 { 299 #ifdef CV64CONSOLE 300 struct cfdata *cfp = match; 301 static int cvcons_unit = -1; 302 #endif 303 struct zbus_args *zap; 304 305 zap = auxp; 306 307 if (amiga_realconfig == 0) 308 #ifdef CV64CONSOLE 309 if (cvcons_unit != -1) 310 #endif 311 return (0); 312 313 /* Lets be Paranoid: Test man and prod id */ 314 if (zap->manid != 8512 || zap->prodid != 34) 315 return (0); 316 317 cv_boardaddr = zap->va; 318 319 #ifdef CV64CONSOLE 320 if (amiga_realconfig == 0) { 321 cvcons_unit = cfp->cf_unit; 322 cfdata = cfp; 323 } 324 #endif 325 326 return (1); 327 } 328 329 void 330 grfcvattach(pdp, dp, auxp) 331 struct device *pdp, *dp; 332 void *auxp; 333 { 334 static struct grf_softc congrf; 335 struct zbus_args *zap; 336 struct grf_softc *gp; 337 static char attachflag = 0; 338 339 zap = auxp; 340 341 /* 342 * This function is called twice, once on console init (dp == NULL) 343 * and once on "normal" grf5 init. 344 */ 345 346 if (dp == NULL) /* console init */ 347 gp = &congrf; 348 else 349 gp = (struct grf_softc *)dp; 350 351 if (dp != NULL && congrf.g_regkva != 0) { 352 /* 353 * inited earlier, just copy (not device struct) 354 */ 355 356 printf("\n"); 357 #ifdef CV64CONSOLE 358 bcopy(&congrf.g_display, &gp->g_display, 359 (char *) &gp[1] - (char *) &gp->g_display); 360 #else 361 gp->g_regkva = (volatile caddr_t)cv_boardaddr + 0x02000000; 362 gp->g_fbkva = (volatile caddr_t)cv_boardaddr + 0x01400000; 363 364 gp->g_unit = GRF_CV64_UNIT; 365 gp->g_mode = cv_mode; 366 gp->g_conpri = grfcv_cnprobe(); 367 gp->g_flags = GF_ALIVE; 368 #endif 369 } else { 370 gp->g_regkva = (volatile caddr_t)cv_boardaddr + 0x02000000; 371 gp->g_fbkva = (volatile caddr_t)cv_boardaddr + 0x01400000; 372 373 gp->g_unit = GRF_CV64_UNIT; 374 gp->g_mode = cv_mode; 375 gp->g_conpri = grfcv_cnprobe(); 376 gp->g_flags = GF_ALIVE; 377 378 /* wakeup the board */ 379 cv_boardinit(gp); 380 381 #ifdef CV64CONSOLE 382 grfcv_iteinit(gp); 383 (void)cv_load_mon(gp, &cvconsole_mode); 384 #endif 385 } 386 387 /* 388 * attach grf 389 */ 390 if (amiga_config_found(cfdata, &gp->g_device, gp, grfcvprint)) { 391 if (dp != NULL) 392 printf("grfcv: CyberVision64 with %dMB being used\n", cv_fbsize/0x100000); 393 attachflag = 1; 394 } else { 395 if (!attachflag) 396 /*printf("grfcv unattached!!\n")*/; 397 } 398 } 399 400 int 401 grfcvprint(auxp, pnp) 402 void *auxp; 403 const char *pnp; 404 { 405 if (pnp) 406 printf("ite at %s: ", pnp); 407 return (UNCONF); 408 } 409 410 411 /* 412 * Computes M, N, and R values from 413 * given input frequency. It uses a table of 414 * precomputed values, to keep CPU time low. 415 * 416 * The return value consist of: 417 * lower byte: Bits 4-0: N Divider Value 418 * Bits 5-6: R Value for e.g. SR10 or SR12 419 * higher byte: Bits 0-6: M divider value for e.g. SR11 or SR13 420 */ 421 422 static unsigned short 423 cv_compute_clock(freq) 424 unsigned long freq; 425 { 426 static unsigned char *mnr, *save; /* M, N + R vals */ 427 unsigned long work_freq, r; 428 unsigned short erg; 429 long diff, d2; 430 431 if (freq < 12500000 || freq > MAXPIXELCLOCK) { 432 printf("grfcv: Illegal clock frequency: %ldMHz\n", freq/1000000); 433 printf("grfcv: Using default frequency: 25MHz\n"); 434 printf("grfcv: See the manpage of grfconfig for more informations.\n"); 435 freq = 25000000; 436 } 437 438 mnr = clocks; /* there the vals are stored */ 439 d2 = 0x7fffffff; 440 441 while (*mnr) { /* mnr vals are 0-terminated */ 442 work_freq = (0x37EE * (mnr[0] + 2)) / ((mnr[1] & 0x1F) + 2); 443 444 r = (mnr[1] >> 5) & 0x03; 445 if (r != 0) 446 work_freq=work_freq >> r; /* r is the freq divider */ 447 448 work_freq *= 0x3E8; /* 2nd part of OSC */ 449 450 diff = abs(freq - work_freq); 451 452 if (d2 >= diff) { 453 d2 = diff; 454 /* In save are the vals for minimal diff */ 455 save = mnr; 456 } 457 mnr += 2; 458 } 459 erg = *((unsigned short *)save); 460 461 return (erg); 462 } 463 464 465 void 466 cv_boardinit(gp) 467 struct grf_softc *gp; 468 { 469 volatile caddr_t ba; 470 unsigned char test; 471 unsigned int clockpar; 472 int i; 473 struct grfinfo *gi; 474 475 ba = gp->g_regkva; 476 /* Reset board */ 477 for (i = 0; i < 6; i++) 478 cv_write_port (0xff, ba - 0x02000000); /* Clear all bits */ 479 480 /* Return to operational Mode */ 481 cv_write_port(0x8004, ba - 0x02000000); 482 483 /* Wakeup Chip */ 484 vgaw(ba, SREG_VIDEO_SUBS_ENABLE, 0x10); 485 vgaw(ba, SREG_OPTION_SELECT, 0x01); 486 vgaw(ba, SREG_VIDEO_SUBS_ENABLE, 0x08); 487 488 vgaw(ba, GREG_MISC_OUTPUT_W, 0x03); 489 490 WCrt(ba, CRT_ID_REGISTER_LOCK_1, 0x48); /* unlock S3 VGA regs */ 491 WCrt(ba, CRT_ID_REGISTER_LOCK_2, 0xA5); /* unlock syscontrol */ 492 493 test = RCrt(ba, CRT_ID_SYSTEM_CONFIG); 494 test = test | 0x01; /* enable enhaced register access */ 495 test = test & 0xEF; /* clear bit 4, 0 wait state */ 496 WCrt(ba, CRT_ID_SYSTEM_CONFIG, test); 497 498 /* 499 * bit 1=1: enable enhanced mode functions 500 * bit 4=1: enable linear adressing 501 * bit 5=1: enable MMIO 502 */ 503 vgaw(ba, ECR_ADV_FUNC_CNTL, 0x31); 504 505 /* enable cpu acess, color mode, high 64k page */ 506 vgaw(ba, GREG_MISC_OUTPUT_W, 0x23); 507 508 /* Cpu base addr */ 509 WCrt(ba, CRT_ID_EXT_SYS_CNTL_4, 0x00); 510 511 /* Reset. This does nothing, but everyone does it:) */ 512 WSeq(ba, SEQ_ID_RESET, 0x03); 513 514 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01); /* 8 Dot Clock */ 515 WSeq(ba, SEQ_ID_MAP_MASK, 0x0f); /* Enable write planes */ 516 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); /* Character Font */ 517 518 WSeq(ba, SEQ_ID_MEMORY_MODE, 0x02); /* Complete mem access */ 519 520 WSeq(ba, SEQ_ID_UNLOCK_EXT, 0x06); /* Unlock extensions */ 521 test = RSeq(ba, SEQ_ID_BUS_REQ_CNTL); /* Bus Request */ 522 523 /* enable 4MB fast Page Mode */ 524 test = test | 1 << 6; 525 WSeq(ba, SEQ_ID_BUS_REQ_CNTL, test); 526 /* faster LUT write */ 527 WSeq(ba, SEQ_ID_RAMDAC_CNTL, 0xC0); 528 529 test = RSeq(ba, SEQ_ID_CLKSYN_CNTL_2); /* Clksyn2 read */ 530 531 /* immediately Clkload bit clear */ 532 test = test & 0xDF; 533 534 /* 2 MCLK Memory Write.... */ 535 if (cv_memclk >= 55000000) 536 test |= 0x80; 537 538 WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, test); 539 540 /* Memory CLK */ 541 clockpar = cv_compute_clock(cv_memclk); 542 test = (clockpar & 0xFF00) >> 8; 543 WSeq(ba, SEQ_ID_MCLK_HI, test); /* PLL N-Divider Value */ 544 545 test = clockpar & 0xFF; 546 WSeq(ba, SEQ_ID_MCLK_LO, test); /* PLL M-Divider Value */ 547 548 if (RCrt(ba, CRT_ID_REVISION) == 0x10) /* bugfix for new S3 chips */ 549 WSeq(ba, SEQ_ID_MORE_MAGIC, test); 550 551 /* We now load an 25 MHz, 31 kHz, 640x480 standard VGA Mode. */ 552 /* DCLK */ 553 WSeq(ba, SEQ_ID_DCLK_HI, 0x13); 554 WSeq(ba, SEQ_ID_DCLK_LO, 0x41); 555 556 test = RSeq (ba, SEQ_ID_CLKSYN_CNTL_2); 557 test = test | 0x22; 558 559 /* DCLK + MCLK Clock immediate load! */ 560 WSeq(ba,SEQ_ID_CLKSYN_CNTL_2, test); 561 562 /* DCLK load */ 563 test = vgar(ba, 0x3cc); 564 test = test | 0x0c; 565 vgaw(ba, 0x3c2, test); 566 567 /* Clear bit 5 again, prevent further loading. */ 568 WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, 0x02); 569 570 WCrt(ba, CRT_ID_HOR_TOTAL, 0x5F); 571 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, 0x4F); 572 WCrt(ba, CRT_ID_START_HOR_BLANK, 0x50); 573 WCrt(ba, CRT_ID_END_HOR_BLANK, 0x82); 574 WCrt(ba, CRT_ID_START_HOR_RETR, 0x54); 575 WCrt(ba, CRT_ID_END_HOR_RETR, 0x80); 576 WCrt(ba, CRT_ID_VER_TOTAL, 0xBF); 577 578 WCrt(ba, CRT_ID_OVERFLOW, 0x1F); /* overflow reg */ 579 580 WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00); /* no panning */ 581 582 WCrt(ba, CRT_ID_MAX_SCAN_LINE, 0x40); /* vscan */ 583 584 WCrt(ba, CRT_ID_CURSOR_START, 0x00); 585 WCrt(ba, CRT_ID_CURSOR_END, 0x00); 586 587 /* Display start adress */ 588 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00); 589 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00); 590 591 /* Cursor location */ 592 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00); 593 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00); 594 595 /* Vertical retrace */ 596 WCrt(ba, CRT_ID_START_VER_RETR, 0x9C); 597 WCrt(ba, CRT_ID_END_VER_RETR, 0x0E); 598 599 WCrt(ba, CRT_ID_VER_DISP_ENA_END, 0x8F); 600 WCrt(ba, CRT_ID_SCREEN_OFFSET, 0x50); 601 602 WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x00); 603 604 WCrt(ba, CRT_ID_START_VER_BLANK, 0x96); 605 WCrt(ba, CRT_ID_END_VER_BLANK, 0xB9); 606 607 WCrt(ba, CRT_ID_MODE_CONTROL, 0xE3); 608 609 WCrt(ba, CRT_ID_LINE_COMPARE, 0xFF); 610 611 WCrt(ba, CRT_ID_BACKWAD_COMP_3, 0x10); /* FIFO enabled */ 612 613 /* Refresh count 1, High speed text font, enhanced color mode */ 614 WCrt(ba, CRT_ID_MISC_1, 0x35); 615 616 /* start fifo position */ 617 WCrt(ba, CRT_ID_DISPLAY_FIFO, 0x5a); 618 619 WCrt(ba, CRT_ID_EXT_MEM_CNTL_2, 0x70); 620 621 /* address window position */ 622 WCrt(ba, CRT_ID_LAW_POS_LO, 0x40); 623 624 /* N Parameter for Display FIFO */ 625 WCrt(ba, CRT_ID_EXT_MEM_CNTL_3, 0xFF); 626 627 WGfx(ba, GCT_ID_SET_RESET, 0x00); 628 WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00); 629 WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00); 630 WGfx(ba, GCT_ID_DATA_ROTATE, 0x00); 631 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00); 632 WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x40); 633 WGfx(ba, GCT_ID_MISC, 0x01); 634 WGfx(ba, GCT_ID_COLOR_XCARE, 0x0F); 635 WGfx(ba, GCT_ID_BITMASK, 0xFF); 636 637 /* colors for text mode */ 638 for (i = 0; i <= 0xf; i++) 639 WAttr (ba, i, i); 640 641 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x41); 642 WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x01); 643 WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0F); 644 WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00); 645 WAttr(ba, ACT_ID_COLOR_SELECT, 0x00); 646 647 vgaw(ba, VDAC_MASK, 0xFF); /* DAC Mask */ 648 649 *((unsigned long *)(ba + ECR_FRGD_COLOR)) = 0xFF; 650 *((unsigned long *)(ba + ECR_BKGD_COLOR)) = 0; 651 652 /* colors initially set to greyscale */ 653 654 vgaw(ba, VDAC_ADDRESS_W, 0); 655 for (i = 255; i >= 0 ; i--) { 656 vgaw(ba, VDAC_DATA, i); 657 vgaw(ba, VDAC_DATA, i); 658 vgaw(ba, VDAC_DATA, i); 659 } 660 661 /* GFx hardware cursor off */ 662 WCrt(ba, CRT_ID_HWGC_MODE, 0x00); 663 664 /* Set first to 4 MB, so test will work */ 665 WCrt(ba, CRT_ID_LAW_CNTL, 0x13); 666 667 /* find *correct* fbsize of z3 board */ 668 if (cv_has_4mb((volatile caddr_t)cv_boardaddr + 0x01400000)) { 669 cv_fbsize = 1024 * 1024 * 4; 670 WCrt(ba, CRT_ID_LAW_CNTL, 0x13); /* 4 MB */ 671 } else { 672 cv_fbsize = 1024 * 1024 * 2; 673 WCrt(ba, CRT_ID_LAW_CNTL, 0x12); /* 2 MB */ 674 } 675 676 /* Initialize graphics engine */ 677 GfxBusyWait(ba); 678 vgaw16(ba, ECR_FRGD_MIX, 0x27); 679 vgaw16(ba, ECR_BKGD_MIX, 0x07); 680 681 vgaw16(ba, ECR_READ_REG_DATA, 0x1000); 682 delay(200000); 683 vgaw16(ba, ECR_READ_REG_DATA, 0x2000); 684 GfxBusyWait(ba); 685 vgaw16(ba, ECR_READ_REG_DATA, 0x3fff); 686 GfxBusyWait(ba); 687 delay(200000); 688 vgaw16(ba, ECR_READ_REG_DATA, 0x4fff); 689 GfxBusyWait(ba); 690 691 vgaw16(ba, ECR_BITPLANE_WRITE_MASK, ~0); 692 693 GfxBusyWait (ba); 694 vgaw16(ba, ECR_READ_REG_DATA, 0xe000); 695 vgaw16(ba, ECR_CURRENT_Y_POS2, 0x00); 696 vgaw16(ba, ECR_CURRENT_X_POS2, 0x00); 697 vgaw16(ba, ECR_READ_REG_DATA, 0xa000); 698 vgaw16(ba, ECR_DEST_Y__AX_STEP, 0x00); 699 vgaw16(ba, ECR_DEST_Y2__AX_STEP2, 0x00); 700 vgaw16(ba, ECR_DEST_X__DIA_STEP, 0x00); 701 vgaw16(ba, ECR_DEST_X2__DIA_STEP2, 0x00); 702 vgaw16(ba, ECR_SHORT_STROKE, 0x00); 703 vgaw16(ba, ECR_DRAW_CMD, 0x01); 704 GfxBusyWait (ba); 705 706 /* It ain't easy to write here, so let's do it again */ 707 vgaw16(ba, ECR_READ_REG_DATA, 0x4fff); 708 709 vgaw16(ba, ECR_BKGD_COLOR, 0x01); 710 vgaw16(ba, ECR_FRGD_COLOR, 0x00); 711 712 /* Enable Video Display (Set Bit 5) */ 713 WAttr(ba, 0x33, 0); 714 715 gi = &gp->g_display; 716 gi->gd_regaddr = (caddr_t) kvtop (ba); 717 gi->gd_regsize = 64 * 1024; 718 gi->gd_fbaddr = (caddr_t) kvtop (gp->g_fbkva); 719 gi->gd_fbsize = cv_fbsize; 720 } 721 722 723 int 724 cv_getvmode(gp, vm) 725 struct grf_softc *gp; 726 struct grfvideo_mode *vm; 727 { 728 struct grfvideo_mode *gv; 729 730 #ifdef CV64CONSOLE 731 /* Handle grabbing console mode */ 732 if (vm->mode_num == 255) { 733 bcopy(&cvconsole_mode, vm, sizeof(struct grfvideo_mode)); 734 /* XXX so grfconfig can tell us the correct text dimensions. */ 735 vm->depth = cvconsole_mode.fy; 736 } else 737 #endif 738 { 739 if (vm->mode_num == 0) 740 vm->mode_num = (monitor_current - monitor_def) + 1; 741 if (vm->mode_num < 1 || vm->mode_num > monitor_def_max) 742 return (EINVAL); 743 gv = monitor_def + (vm->mode_num - 1); 744 if (gv->mode_num == 0) 745 return (EINVAL); 746 747 bcopy(gv, vm, sizeof(struct grfvideo_mode)); 748 } 749 750 /* adjust internal values to pixel values */ 751 752 vm->hblank_start *= 8; 753 vm->hblank_stop *= 8; 754 vm->hsync_start *= 8; 755 vm->hsync_stop *= 8; 756 vm->htotal *= 8; 757 758 return (0); 759 } 760 761 762 int 763 cv_setvmode(gp, mode) 764 struct grf_softc *gp; 765 unsigned mode; 766 { 767 768 if (!mode || (mode > monitor_def_max) || 769 monitor_def[mode - 1].mode_num == 0) 770 return (EINVAL); 771 772 monitor_current = monitor_def + (mode - 1); 773 774 return (0); 775 } 776 777 778 int 779 cv_blank(gp, on) 780 struct grf_softc *gp; 781 int *on; 782 { 783 volatile caddr_t ba; 784 785 ba = gp->g_regkva; 786 gfx_on_off(*on > 0 ? 0 : 1, ba); 787 return (0); 788 } 789 790 791 /* 792 * Change the mode of the display. 793 * Return a UNIX error number or 0 for success. 794 */ 795 int 796 cv_mode(gp, cmd, arg, a2, a3) 797 register struct grf_softc *gp; 798 u_long cmd; 799 void *arg; 800 u_long a2; 801 int a3; 802 { 803 int error; 804 805 switch (cmd) { 806 case GM_GRFON: 807 error = cv_load_mon (gp, 808 (struct grfcvtext_mode *) monitor_current) ? 0 : EINVAL; 809 return (error); 810 811 case GM_GRFOFF: 812 #ifndef CV64CONSOLE 813 (void)cv_toggle(gp); 814 #else 815 cv_load_mon(gp, &cvconsole_mode); 816 ite_reinit(gp->g_itedev); 817 #endif 818 return (0); 819 820 case GM_GRFCONFIG: 821 return (0); 822 823 case GM_GRFGETVMODE: 824 return (cv_getvmode (gp, (struct grfvideo_mode *) arg)); 825 826 case GM_GRFSETVMODE: 827 error = cv_setvmode (gp, *(unsigned *) arg); 828 if (!error && (gp->g_flags & GF_GRFON)) 829 cv_load_mon(gp, 830 (struct grfcvtext_mode *) monitor_current); 831 return (error); 832 833 case GM_GRFGETNUMVM: 834 *(int *)arg = monitor_def_max; 835 return (0); 836 837 case GM_GRFIOCTL: 838 return (cv_ioctl (gp, a2, arg)); 839 840 default: 841 break; 842 } 843 844 return (EINVAL); 845 } 846 847 848 int 849 cv_ioctl (gp, cmd, data) 850 register struct grf_softc *gp; 851 u_long cmd; 852 void *data; 853 { 854 switch (cmd) { 855 #ifdef CV_HARDWARE_CURSOR 856 case GRFIOCGSPRITEPOS: 857 return(cv_getspritepos (gp, (struct grf_position *) data)); 858 859 case GRFIOCSSPRITEPOS: 860 return(cv_setspritepos (gp, (struct grf_position *) data)); 861 862 case GRFIOCSSPRITEINF: 863 return(cv_setspriteinfo (gp, (struct grf_spriteinfo *) data)); 864 865 case GRFIOCGSPRITEINF: 866 return(cv_getspriteinfo (gp, (struct grf_spriteinfo *) data)); 867 868 case GRFIOCGSPRITEMAX: 869 return(cv_getspritemax (gp, (struct grf_position *) data)); 870 #else /* CV_HARDWARE_CURSOR */ 871 case GRFIOCGSPRITEPOS: 872 case GRFIOCSSPRITEPOS: 873 case GRFIOCSSPRITEINF: 874 case GRFIOCGSPRITEINF: 875 case GRFIOCGSPRITEMAX: 876 break; 877 #endif /* CV_HARDWARE_CURSOR */ 878 879 case GRFIOCGETCMAP: 880 return (cv_getcmap (gp, (struct grf_colormap *) data)); 881 882 case GRFIOCPUTCMAP: 883 return (cv_putcmap (gp, (struct grf_colormap *) data)); 884 885 case GRFIOCBITBLT: 886 break; 887 888 case GRFTOGGLE: 889 return (cv_toggle (gp)); 890 891 case GRFIOCSETMON: 892 return (cv_setmonitor (gp, (struct grfvideo_mode *)data)); 893 894 case GRFIOCBLANK: 895 return (cv_blank (gp, (int *)data)); 896 } 897 return (EINVAL); 898 } 899 900 901 int 902 cv_setmonitor(gp, gv) 903 struct grf_softc *gp; 904 struct grfvideo_mode *gv; 905 { 906 struct grfvideo_mode *md; 907 908 if (!cv_mondefok(gv)) 909 return (EINVAL); 910 911 #ifdef CV64CONSOLE 912 /* handle interactive setting of console mode */ 913 if (gv->mode_num == 255) { 914 bcopy(gv, &cvconsole_mode.gv, sizeof(struct grfvideo_mode)); 915 cvconsole_mode.gv.hblank_start /= 8; 916 cvconsole_mode.gv.hblank_stop /= 8; 917 cvconsole_mode.gv.hsync_start /= 8; 918 cvconsole_mode.gv.hsync_stop /= 8; 919 cvconsole_mode.gv.htotal /= 8; 920 cvconsole_mode.rows = gv->disp_height / cvconsole_mode.fy; 921 cvconsole_mode.cols = gv->disp_width / cvconsole_mode.fx; 922 if (!(gp->g_flags & GF_GRFON)) 923 cv_load_mon(gp, &cvconsole_mode); 924 ite_reinit(gp->g_itedev); 925 return (0); 926 } 927 #endif 928 929 md = monitor_def + (gv->mode_num - 1); 930 931 /* 932 * Prevent user from crashing the system by using 933 * grfconfig while in X 934 */ 935 if (gp->g_flags & GF_GRFON) 936 if (md == monitor_current) { 937 printf("grf_cv: Changing the used mode not allowed!\n"); 938 return (EINVAL); 939 } 940 941 bcopy(gv, md, sizeof(struct grfvideo_mode)); 942 943 /* adjust pixel oriented values to internal rep. */ 944 945 md->hblank_start /= 8; 946 md->hblank_stop /= 8; 947 md->hsync_start /= 8; 948 md->hsync_stop /= 8; 949 md->htotal /= 8; 950 951 return (0); 952 } 953 954 955 int 956 cv_getcmap(gfp, cmap) 957 struct grf_softc *gfp; 958 struct grf_colormap *cmap; 959 { 960 volatile caddr_t ba; 961 u_char red[256], green[256], blue[256], *rp, *gp, *bp; 962 short x; 963 int error; 964 965 ba = gfp->g_regkva; 966 if (cmap->count == 0 || cmap->index >= 256) 967 return (0); 968 969 if (cmap->index + cmap->count > 256) 970 cmap->count = 256 - cmap->index; 971 972 /* first read colors out of the chip, then copyout to userspace */ 973 vgaw (ba, VDAC_ADDRESS_W, cmap->index); 974 x = cmap->count - 1; 975 976 rp = red + cmap->index; 977 gp = green + cmap->index; 978 bp = blue + cmap->index; 979 980 do { 981 *rp++ = vgar (ba, VDAC_DATA) << 2; 982 *gp++ = vgar (ba, VDAC_DATA) << 2; 983 *bp++ = vgar (ba, VDAC_DATA) << 2; 984 } while (x-- > 0); 985 986 if (!(error = copyout (red + cmap->index, cmap->red, cmap->count)) 987 && !(error = copyout (green + cmap->index, cmap->green, cmap->count)) 988 && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count))) 989 return (0); 990 991 return (error); 992 } 993 994 995 int 996 cv_putcmap(gfp, cmap) 997 struct grf_softc *gfp; 998 struct grf_colormap *cmap; 999 { 1000 volatile caddr_t ba; 1001 u_char red[256], green[256], blue[256], *rp, *gp, *bp; 1002 short x; 1003 int error; 1004 1005 ba = gfp->g_regkva; 1006 if (cmap->count == 0 || cmap->index >= 256) 1007 return (0); 1008 1009 if (cmap->index + cmap->count > 256) 1010 cmap->count = 256 - cmap->index; 1011 1012 /* first copy the colors into kernelspace */ 1013 if (!(error = copyin (cmap->red, red + cmap->index, cmap->count)) 1014 && !(error = copyin (cmap->green, green + cmap->index, cmap->count)) 1015 && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count))) { 1016 vgaw (ba, VDAC_ADDRESS_W, cmap->index); 1017 x = cmap->count - 1; 1018 1019 rp = red + cmap->index; 1020 gp = green + cmap->index; 1021 bp = blue + cmap->index; 1022 1023 do { 1024 vgaw (ba, VDAC_DATA, *rp++ >> 2); 1025 vgaw (ba, VDAC_DATA, *gp++ >> 2); 1026 vgaw (ba, VDAC_DATA, *bp++ >> 2); 1027 } while (x-- > 0); 1028 return (0); 1029 } else 1030 return (error); 1031 } 1032 1033 1034 int 1035 cv_toggle(gp) 1036 struct grf_softc *gp; 1037 { 1038 volatile caddr_t ba; 1039 1040 ba = gp->g_regkva; 1041 cvscreen(1, ba - 0x02000000); 1042 1043 return (0); 1044 } 1045 1046 1047 int 1048 cv_mondefok(gv) 1049 struct grfvideo_mode *gv; 1050 { 1051 unsigned long maxpix; 1052 1053 if (gv->mode_num < 1 || gv->mode_num > monitor_def_max) { 1054 if (gv->mode_num != 255 || gv->depth != 4) 1055 return (0); 1056 } 1057 1058 switch(gv->depth) { 1059 case 4: 1060 maxpix = MAXPIXELCLOCK - 55000000; 1061 break; 1062 case 8: 1063 maxpix = MAXPIXELCLOCK; 1064 break; 1065 case 15: 1066 case 16: 1067 #ifdef CV_AGGRESSIVE_TIMING 1068 maxpix = MAXPIXELCLOCK - 35000000; 1069 #else 1070 maxpix = MAXPIXELCLOCK - 55000000; 1071 #endif 1072 break; 1073 case 24: 1074 case 32: 1075 #ifdef CV_AGGRESSIVE_TIMING 1076 maxpix = MAXPIXELCLOCK - 75000000; 1077 #else 1078 maxpix = MAXPIXELCLOCK - 85000000; 1079 #endif 1080 break; 1081 default: 1082 printf("grf_cv: Illegal depth in mode %d\n", 1083 (int) gv->mode_num); 1084 return (0); 1085 } 1086 1087 if (gv->pixel_clock > maxpix) { 1088 printf("grf_cv: Pixelclock too high in mode %d\n", 1089 (int) gv->mode_num); 1090 return (0); 1091 } 1092 1093 if (gv->mode_num == 255) { /* console mode */ 1094 if ((gv->disp_width / 8) > MAXCOLS) { 1095 printf ("grfcv: Too many columns for console\n"); 1096 return (0); 1097 } else if ((gv->disp_height / S3FONTY) > MAXROWS) { 1098 printf ("grfcv: Too many rows for console\n"); 1099 return (0); 1100 } 1101 } 1102 1103 return (1); 1104 } 1105 1106 1107 int 1108 cv_load_mon(gp, md) 1109 struct grf_softc *gp; 1110 struct grfcvtext_mode *md; 1111 { 1112 struct grfvideo_mode *gv; 1113 struct grfinfo *gi; 1114 volatile caddr_t ba, fb; 1115 unsigned short mnr; 1116 unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS, 1117 VSE, VT; 1118 char LACE, DBLSCAN, TEXT, CONSOLE; 1119 int uplim, lowlim; 1120 int cr50, sr15, sr18, clock_mode, test; 1121 int m, n; /* For calc'ing display FIFO */ 1122 int tfillm, temptym; /* FIFO fill and empty mclk's */ 1123 int hmul; /* Multiplier for hor. Values */ 1124 /* identity */ 1125 gv = &md->gv; 1126 1127 TEXT = (gv->depth == 4); 1128 CONSOLE = (gv->mode_num == 255); 1129 1130 if (!cv_mondefok(gv)) { 1131 printf("grfcv: The monitor definition is illegal.\n"); 1132 printf("grfcv: See the manpage of grfconfig for more informations\n"); 1133 return (0); 1134 } 1135 ba = gp->g_regkva; 1136 fb = gp->g_fbkva; 1137 1138 /* turn gfx off, don't mess up the display */ 1139 gfx_on_off(1, ba); 1140 1141 /* provide all needed information in grf device-independant locations */ 1142 gp->g_data = (caddr_t) gv; 1143 gi = &gp->g_display; 1144 gi->gd_colors = 1 << gv->depth; 1145 gi->gd_planes = gv->depth; 1146 gi->gd_fbwidth = gv->disp_width; 1147 gi->gd_fbheight = gv->disp_height; 1148 gi->gd_fbx = 0; 1149 gi->gd_fby = 0; 1150 if (CONSOLE) { 1151 gi->gd_dwidth = md->fx * md->cols; 1152 gi->gd_dheight = md->fy * md->rows; 1153 } else { 1154 gi->gd_dwidth = gv->disp_width; 1155 gi->gd_dheight = gv->disp_height; 1156 } 1157 gi->gd_dx = 0; 1158 gi->gd_dy = 0; 1159 1160 /* get display mode parameters */ 1161 switch (gv->depth) { 1162 case 15: 1163 case 16: 1164 hmul = 2; 1165 break; 1166 default: 1167 hmul = 1; 1168 break; 1169 } 1170 1171 HBS = gv->hblank_start * hmul; 1172 HBE = gv->hblank_stop * hmul; 1173 HSS = gv->hsync_start * hmul; 1174 HSE = gv->hsync_stop * hmul; 1175 HT = gv->htotal*hmul - 5; 1176 VBS = gv->vblank_start - 1; 1177 VSS = gv->vsync_start; 1178 VSE = gv->vsync_stop; 1179 VBE = gv->vblank_stop; 1180 VT = gv->vtotal - 2; 1181 1182 /* Disable enhanced Mode for text display */ 1183 1184 vgaw(ba, ECR_ADV_FUNC_CNTL, (TEXT ? 0x00 : 0x31)); 1185 1186 if (TEXT) 1187 HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1; 1188 else 1189 HDE = (gv->disp_width + 3) * hmul / 8 - 1; /*HBS;*/ 1190 VDE = gv->disp_height - 1; 1191 1192 /* figure out whether lace or dblscan is needed */ 1193 1194 uplim = gv->disp_height + (gv->disp_height / 4); 1195 lowlim = gv->disp_height - (gv->disp_height / 4); 1196 LACE = (((VT * 2) > lowlim) && ((VT * 2) < uplim)) ? 1 : 0; 1197 DBLSCAN = (((VT / 2) > lowlim) && ((VT / 2) < uplim)) ? 1 : 0; 1198 1199 /* adjustments */ 1200 1201 if (LACE) 1202 VDE /= 2; 1203 1204 /* GFX hardware cursor off */ 1205 WCrt(ba, CRT_ID_HWGC_MODE, 0x00); 1206 WCrt(ba, CRT_ID_EXT_DAC_CNTL, 0x00); 1207 1208 WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e); 1209 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00); 1210 WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff); 1211 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); 1212 1213 /* Set clock */ 1214 1215 mnr = cv_compute_clock(gv->pixel_clock); 1216 WSeq(ba, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8)); 1217 WSeq(ba, SEQ_ID_DCLK_LO, (mnr & 0xFF)); 1218 1219 /* load display parameters into board */ 1220 1221 WCrt(ba, CRT_ID_EXT_HOR_OVF, 1222 ((HT & 0x100) ? 0x01 : 0x00) | 1223 ((HDE & 0x100) ? 0x02 : 0x00) | 1224 ((HBS & 0x100) ? 0x04 : 0x00) | 1225 /* ((HBE & 0x40) ? 0x08 : 0x00) | */ /* Later... */ 1226 ((HSS & 0x100) ? 0x10 : 0x00) | 1227 /* ((HSE & 0x20) ? 0x20 : 0x00) | */ 1228 (((HT-5) & 0x100) ? 0x40 : 0x00) ); 1229 1230 WCrt(ba, CRT_ID_EXT_VER_OVF, 1231 0x40 | /* Line compare */ 1232 ((VT & 0x400) ? 0x01 : 0x00) | 1233 ((VDE & 0x400) ? 0x02 : 0x00) | 1234 ((VBS & 0x400) ? 0x04 : 0x00) | 1235 ((VSS & 0x400) ? 0x10 : 0x00) ); 1236 1237 WCrt(ba, CRT_ID_HOR_TOTAL, HT); 1238 WCrt(ba, CRT_ID_DISPLAY_FIFO, HT - 5); 1239 1240 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? (HBS - 1) : HDE)); 1241 WCrt(ba, CRT_ID_START_HOR_BLANK, HBS); 1242 WCrt(ba, CRT_ID_END_HOR_BLANK, ((HBE & 0x1f) | 0x80)); 1243 WCrt(ba, CRT_ID_START_HOR_RETR, HSS); 1244 WCrt(ba, CRT_ID_END_HOR_RETR, 1245 (HSE & 0x1f) | 1246 ((HBE & 0x20) ? 0x80 : 0x00) ); 1247 WCrt(ba, CRT_ID_VER_TOTAL, VT); 1248 WCrt(ba, CRT_ID_OVERFLOW, 1249 0x10 | 1250 ((VT & 0x100) ? 0x01 : 0x00) | 1251 ((VDE & 0x100) ? 0x02 : 0x00) | 1252 ((VSS & 0x100) ? 0x04 : 0x00) | 1253 ((VBS & 0x100) ? 0x08 : 0x00) | 1254 ((VT & 0x200) ? 0x20 : 0x00) | 1255 ((VDE & 0x200) ? 0x40 : 0x00) | 1256 ((VSS & 0x200) ? 0x80 : 0x00) ); 1257 1258 WCrt(ba, CRT_ID_MAX_SCAN_LINE, 1259 0x40 | /* TEXT ? 0x00 ??? */ 1260 (DBLSCAN ? 0x80 : 0x00) | 1261 ((VBS & 0x200) ? 0x20 : 0x00) | 1262 (TEXT ? ((md->fy - 1) & 0x1f) : 0x00)); 1263 1264 WCrt(ba, CRT_ID_MODE_CONTROL, 0xe3); 1265 1266 /* text cursor */ 1267 1268 if (TEXT) { 1269 #if 1 1270 WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2); 1271 WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1); 1272 #else 1273 WCrt(ba, CRT_ID_CURSOR_START, 0x00); 1274 WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f); 1275 #endif 1276 WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->fy - 1) & 0x1f); 1277 1278 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00); 1279 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00); 1280 } 1281 1282 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00); 1283 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00); 1284 1285 WCrt(ba, CRT_ID_START_VER_RETR, VSS); 1286 WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f)); 1287 WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE); 1288 WCrt(ba, CRT_ID_START_VER_BLANK, VBS); 1289 WCrt(ba, CRT_ID_END_VER_BLANK, VBE); 1290 1291 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); 1292 WCrt(ba, CRT_ID_LACE_RETR_START, HT / 2); 1293 WCrt(ba, CRT_ID_LACE_CONTROL, (LACE ? 0x20 : 0x00)); 1294 1295 WGfx(ba, GCT_ID_GRAPHICS_MODE, 1296 ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40)); 1297 WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01)); 1298 1299 WSeq (ba, SEQ_ID_MEMORY_MODE, 1300 ((TEXT || (gv->depth == 1)) ? 0x06 : 0x02)); 1301 1302 vgaw(ba, VDAC_MASK, 0xff); 1303 1304 /* Blank border */ 1305 test = RCrt(ba, CRT_ID_BACKWAD_COMP_2); 1306 WCrt(ba, CRT_ID_BACKWAD_COMP_2, (test | 0x20)); 1307 1308 sr15 = RSeq(ba, SEQ_ID_CLKSYN_CNTL_2); 1309 sr15 &= 0xef; 1310 sr18 = RSeq(ba, SEQ_ID_RAMDAC_CNTL); 1311 sr18 &= 0x7f; 1312 clock_mode = 0x00; 1313 cr50 = 0x00; 1314 1315 test = RCrt(ba, CRT_ID_EXT_MISC_CNTL_2); 1316 test &= 0xd; 1317 1318 /* clear roxxler byte-swapping... */ 1319 cv_write_port(0x0040, cv_boardaddr); 1320 cv_write_port(0x0020, cv_boardaddr); 1321 1322 switch (gv->depth) { 1323 case 1: 1324 case 4: /* text */ 1325 HDE = gv->disp_width / 16; 1326 break; 1327 case 8: 1328 if (gv->pixel_clock > 80000000) { 1329 clock_mode = 0x10 | 0x02; 1330 sr15 |= 0x10; 1331 sr18 |= 0x80; 1332 } 1333 HDE = gv->disp_width / 8; 1334 cr50 |= 0x00; 1335 break; 1336 case 15: 1337 cv_write_port (0x8020, cv_boardaddr); 1338 clock_mode = 0x30; 1339 HDE = gv->disp_width / 4; 1340 cr50 |= 0x10; 1341 break; 1342 case 16: 1343 cv_write_port (0x8020, cv_boardaddr); 1344 clock_mode = 0x50; 1345 HDE = gv->disp_width / 4; 1346 cr50 |= 0x10; 1347 break; 1348 case 24: /* this is really 32 Bit on CV64 */ 1349 case 32: 1350 cv_write_port(0x8040, cv_boardaddr); 1351 clock_mode = 0xd0; 1352 HDE = (gv->disp_width / 2); 1353 cr50 |= 0x30; 1354 break; 1355 } 1356 1357 WCrt(ba, CRT_ID_EXT_MISC_CNTL_2, clock_mode | test); 1358 WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, sr15); 1359 WSeq(ba, SEQ_ID_RAMDAC_CNTL, sr18); 1360 WCrt(ba, CRT_ID_SCREEN_OFFSET, HDE); 1361 1362 WCrt(ba, CRT_ID_MISC_1, (TEXT ? 0x05 : 0x35)); 1363 1364 test = RCrt(ba, CRT_ID_EXT_SYS_CNTL_2); 1365 test &= ~0x30; 1366 /* HDE Overflow in bits 4-5 */ 1367 test |= (HDE >> 4) & 0x30; 1368 WCrt(ba, CRT_ID_EXT_SYS_CNTL_2, test); 1369 1370 /* Set up graphics engine */ 1371 switch (gv->disp_width) { 1372 case 1024: 1373 cr50 |= 0x00; 1374 break; 1375 case 640: 1376 cr50 |= 0x40; 1377 break; 1378 case 800: 1379 cr50 |= 0x80; 1380 break; 1381 case 1280: 1382 cr50 |= 0xc0; 1383 break; 1384 case 1152: 1385 cr50 |= 0x01; 1386 break; 1387 case 1600: 1388 cr50 |= 0x81; 1389 break; 1390 default: /* XXX The Xserver has to handle this */ 1391 break; 1392 } 1393 1394 WCrt(ba, CRT_ID_EXT_SYS_CNTL_1, cr50); 1395 1396 delay(100000); 1397 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x08 : 0x41)); 1398 delay(100000); 1399 WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 1400 (gv->depth == 1) ? 0x01 : 0x0f); 1401 delay(100000); 1402 1403 /* 1404 * M-Parameter of Display FIFO 1405 * This is dependant on the pixel clock and the memory clock. 1406 * The FIFO filling bandwidth is 240 MHz and the FIFO is 96 Byte wide. 1407 * Then the time to fill the FIFO is tfill = (96/240000000) sec, the time 1408 * to empty the FIFO is tempty = (96/pixelclock) sec. 1409 * Then the M parameter maximum is ((tempty-tfill)*cv_memclk-9)/2. 1410 * This seems to be logical, ain't it? 1411 * Remember: We have to use integer arithmetics :( 1412 * Divide by 1000 to prevent overflows. 1413 */ 1414 1415 tfillm = (96 * (cv_memclk/1000))/240000; 1416 1417 switch(gv->depth) { 1418 case 32: 1419 case 24: 1420 temptym = (24 * (cv_memclk/1000)) / (gv->pixel_clock/1000); 1421 break; 1422 case 15: 1423 case 16: 1424 temptym = (48 * (cv_memclk/1000)) / (gv->pixel_clock/1000); 1425 break; 1426 case 4: 1427 temptym = (192 * (cv_memclk/1000)) / (gv->pixel_clock/1000); 1428 break; 1429 default: 1430 temptym = (96 * (cv_memclk/1000)) / (gv->pixel_clock/1000); 1431 break; 1432 } 1433 1434 m = (temptym - tfillm - 9) / 2; 1435 if (m < 0) 1436 m = 0; /* prevent underflow */ 1437 m = (m & 0x1f) << 3; 1438 if (m < 0x18) 1439 m = 0x18; 1440 n = 0xff; 1441 1442 WCrt(ba, CRT_ID_EXT_MEM_CNTL_2, m); 1443 WCrt(ba, CRT_ID_EXT_MEM_CNTL_3, n); 1444 delay(10000); 1445 1446 /* text initialization */ 1447 1448 if (TEXT) { 1449 cv_inittextmode(gp); 1450 } 1451 1452 if (CONSOLE) { 1453 int i; 1454 vgaw(ba, VDAC_ADDRESS_W, 0); 1455 for (i = 0; i < 16; i++) { 1456 vgaw(ba, VDAC_DATA, cvconscolors[i][0]); 1457 vgaw(ba, VDAC_DATA, cvconscolors[i][1]); 1458 vgaw(ba, VDAC_DATA, cvconscolors[i][2]); 1459 } 1460 } 1461 1462 /* Some kind of Magic */ 1463 WAttr(ba, 0x33, 0); 1464 1465 /* turn gfx on again */ 1466 gfx_on_off(0, ba); 1467 1468 /* Pass-through */ 1469 cvscreen(0, ba - 0x02000000); 1470 1471 return (1); 1472 } 1473 1474 1475 void 1476 cv_inittextmode(gp) 1477 struct grf_softc *gp; 1478 { 1479 struct grfcvtext_mode *tm = (struct grfcvtext_mode *)gp->g_data; 1480 volatile caddr_t ba, fb; 1481 unsigned char *c, *f, y; 1482 unsigned short z; 1483 1484 ba = gp->g_regkva; 1485 fb = gp->g_fbkva; 1486 1487 /* load text font into beginning of display memory. 1488 * Each character cell is 32 bytes long (enough for 4 planes) 1489 * In linear adressing text mode, the memory is organized 1490 * so, that the Bytes of all 4 planes are interleaved. 1491 * 1st byte plane 0, 1st byte plane 1, 1st byte plane 2, 1492 * 1st byte plane 3, 2nd byte plane 0, 2nd byte plane 1,... 1493 * The font is loaded in plane 2. 1494 */ 1495 1496 c = (unsigned char *) fb; 1497 1498 /* clear screen */ 1499 for (z = 0; z < tm->cols * tm->rows * 3; z++) { 1500 *c++ = 0x20; 1501 *c++ = 0x07; 1502 *c++ = 0; 1503 *c++ = 0; 1504 } 1505 1506 c = (unsigned char *) (fb) + (32 * tm->fdstart * 4 + 2); 1507 f = tm->fdata; 1508 for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy) * 4) 1509 for (y = 0; y < tm->fy; y++) { 1510 *c = *f++; 1511 c += 4; 1512 } 1513 1514 /* print out a little init msg */ 1515 c = (unsigned char *)(fb) + (tm->cols - 6) * 4; 1516 *c++ = 'C'; 1517 *c++ = 0x0a; 1518 c +=2; 1519 *c++ = 'V'; 1520 *c++ = 0x0b; 1521 c +=2; 1522 *c++ = '6'; 1523 *c++ = 0x0c; 1524 c +=2; 1525 *c++ = '4'; 1526 *c++ = 0x0d; 1527 } 1528 1529 1530 static inline void 1531 cv_write_port(bits, BoardAddr) 1532 unsigned short bits; 1533 volatile caddr_t BoardAddr; 1534 { 1535 volatile caddr_t addr; 1536 static unsigned char CVPortBits = 0; /* mirror port bits here */ 1537 1538 addr = BoardAddr + 0x40001; 1539 if (bits & 0x8000) 1540 CVPortBits |= bits & 0xFF; /* Set bits */ 1541 else { 1542 bits = bits & 0xFF; 1543 bits = (~bits) & 0xFF ; 1544 CVPortBits &= bits; /* Clear bits */ 1545 } 1546 1547 *addr = CVPortBits; 1548 } 1549 1550 1551 /* 1552 * Monitor Switch 1553 * 0 = CyberVision Signal 1554 * 1 = Amiga Signal, 1555 * ba = boardaddr 1556 */ 1557 static inline void 1558 cvscreen(toggle, ba) 1559 int toggle; 1560 volatile caddr_t ba; 1561 { 1562 1563 if (toggle == 1) 1564 cv_write_port (0x10, ba); 1565 else 1566 cv_write_port (0x8010, ba); 1567 } 1568 1569 1570 /* 0 = on, 1= off */ 1571 /* ba= registerbase */ 1572 static inline void 1573 gfx_on_off(toggle, ba) 1574 int toggle; 1575 volatile caddr_t ba; 1576 { 1577 int r; 1578 1579 toggle &= 0x1; 1580 toggle = toggle << 5; 1581 1582 r = RSeq(ba, SEQ_ID_CLOCKING_MODE); 1583 r &= 0xdf; /* set Bit 5 to 0 */ 1584 1585 WSeq(ba, SEQ_ID_CLOCKING_MODE, r | toggle); 1586 } 1587 1588 1589 #ifdef CV_HARDWARE_CURSOR 1590 1591 static unsigned char cv_hotx = 0, cv_hoty = 0; 1592 1593 /* Hardware Cursor handling routines */ 1594 1595 int 1596 cv_getspritepos (gp, pos) 1597 struct grf_softc *gp; 1598 struct grf_position *pos; 1599 { 1600 int hi,lo; 1601 volatile caddr_t ba = gp->g_regkva; 1602 1603 hi = RCrt (ba, CRT_ID_HWGC_ORIGIN_Y_HI); 1604 lo = RCrt (ba, CRT_ID_HWGC_ORIGIN_Y_LO); 1605 1606 pos->y = (hi << 8) + lo; 1607 hi = RCrt (ba, CRT_ID_HWGC_ORIGIN_X_HI); 1608 lo = RCrt (ba, CRT_ID_HWGC_ORIGIN_X_LO); 1609 pos->x = (hi << 8) + lo; 1610 return (0); 1611 } 1612 1613 1614 int 1615 cv_setspritepos (gp, pos) 1616 struct grf_softc *gp; 1617 struct grf_position *pos; 1618 { 1619 volatile caddr_t ba = gp->g_regkva; 1620 short x = pos->x, y = pos->y; 1621 short xoff, yoff; 1622 1623 x -= cv_hotx; 1624 y -= cv_hoty; 1625 if (x < 0) { 1626 xoff = ((-x) & 0xFE); 1627 x = 0; 1628 } else { 1629 xoff = 0; 1630 } 1631 1632 if (y < 0) { 1633 yoff = ((-y) & 0xFE); 1634 y = 0; 1635 } else { 1636 yoff = 0; 1637 } 1638 1639 WCrt (ba, CRT_ID_HWGC_ORIGIN_X_HI, (x >> 8)); 1640 WCrt (ba, CRT_ID_HWGC_ORIGIN_X_LO, (x & 0xff)); 1641 1642 WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_LO, (y & 0xff)); 1643 WCrt (ba, CRT_ID_HWGC_DSTART_X, xoff); 1644 WCrt (ba, CRT_ID_HWGC_DSTART_Y, yoff); 1645 WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_HI, (y >> 8)); 1646 1647 return(0); 1648 } 1649 1650 static inline short 1651 M2I(short val) { 1652 asm volatile (" rorw #8,%0 ; \ 1653 swap %0 ; \ 1654 rorw #8,%0 ; " : "=d" (val) : "0" (val)); 1655 return (val); 1656 } 1657 1658 #define M2INS(val) \ 1659 asm volatile (" rorw #8,%0 ; \ 1660 swap %0 ; \ 1661 rorw #8,%0 ; \ 1662 swap %0 ; " : "=d" (val) : "0" (val)); 1663 1664 #define HWC_OFF (cv_fbsize - 1024*2) 1665 #define HWC_SIZE 1024 1666 1667 1668 int 1669 cv_getspriteinfo (gp, info) 1670 struct grf_softc *gp; 1671 struct grf_spriteinfo *info; 1672 { 1673 volatile caddr_t ba, fb; 1674 1675 ba = gp->g_regkva; 1676 fb = gp->g_fbkva; 1677 1678 if (info->set & GRFSPRSET_ENABLE) 1679 info->enable = RCrt(ba, CRT_ID_HWGC_MODE) & 0x01; 1680 1681 if (info->set & GRFSPRSET_POS) 1682 cv_getspritepos (gp, &info->pos); 1683 1684 #if 0 /* XXX */ 1685 if (info->set & GRFSPRSET_SHAPE) { 1686 u_char image[512], mask[512]; 1687 volatile u_long *hwp; 1688 u_char *imp, *mp; 1689 short row; 1690 info->size.x = 64; 1691 info->size.y = 64; 1692 for (row = 0, hwp = (u_long *)(fb + HWC_OFF), 1693 mp = mask, imp = image; 1694 row < 64; 1695 row++) { 1696 u_long bp10, bp20, bp11, bp21; 1697 bp10 = *hwp++; 1698 bp20 = *hwp++; 1699 bp11 = *hwp++; 1700 bp21 = *hwp++; 1701 M2I (bp10); 1702 M2I (bp20); 1703 M2I (bp11); 1704 M2I (bp21); 1705 *imp++ = (~bp10) & bp11; 1706 *imp++ = (~bp20) & bp21; 1707 *mp++ = (~bp10) | (bp10 & ~bp11); 1708 *mp++ = (~bp20) & (bp20 & ~bp21); 1709 } 1710 copyout (image, info->image, sizeof (image)); 1711 copyout (mask, info->mask, sizeof (mask)); 1712 } 1713 #endif 1714 return(0); 1715 } 1716 1717 1718 void 1719 cv_setup_hwc (gp, col1, col2, hsx, hsy, data) 1720 struct grf_softc *gp; 1721 unsigned char col1; 1722 unsigned char col2; 1723 unsigned char hsx; 1724 unsigned char hsy; 1725 const unsigned long *data; 1726 { 1727 volatile caddr_t ba = gp->g_regkva; 1728 unsigned long *c = (unsigned long *)(gp->g_fbkva + HWC_OFF); 1729 const unsigned long *s = data; 1730 int test; 1731 1732 short x = (HWC_SIZE / (4*4)) - 1; 1733 /* copy only, if there is a data pointer. */ 1734 if (data) do { 1735 *c++ = *s++; 1736 *c++ = *s++; 1737 *c++ = *s++; 1738 *c++ = *s++; 1739 } while (x-- > 0); 1740 1741 /* reset colour stack */ 1742 test = RCrt(ba, CRT_ID_HWGC_MODE); 1743 asm volatile("nop"); 1744 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0); 1745 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0); 1746 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0); 1747 1748 test = RCrt(ba, CRT_ID_HWGC_MODE); 1749 asm volatile("nop"); 1750 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0x1); 1751 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0x1); 1752 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0x1); 1753 1754 test = HWC_OFF / HWC_SIZE; 1755 WCrt (ba, CRT_ID_HWGC_START_AD_HI, (test >> 8)); 1756 WCrt (ba, CRT_ID_HWGC_START_AD_LO, (test & 0xff)); 1757 1758 WCrt (ba, CRT_ID_HWGC_DSTART_X , 0); 1759 WCrt (ba, CRT_ID_HWGC_DSTART_Y , 0); 1760 1761 WCrt (ba, CRT_ID_EXT_DAC_CNTL, 0x10); /* Cursor X11 Mode */ 1762 1763 WCrt (ba, CRT_ID_HWGC_MODE, 0x01); 1764 } 1765 1766 1767 /* This is the reason why you shouldn't use the HGC in the Kernel:( */ 1768 1769 #define VerticalRetraceWait(ba) \ 1770 { \ 1771 while (vgar(ba, GREG_INPUT_STATUS1_R) == 0x00) ; \ 1772 while ((vgar(ba, GREG_INPUT_STATUS1_R) & 0x08) == 0x08) ; \ 1773 while ((vgar(ba, GREG_INPUT_STATUS1_R) & 0x08) == 0x00) ; \ 1774 } 1775 1776 1777 int 1778 cv_setspriteinfo (gp, info) 1779 struct grf_softc *gp; 1780 struct grf_spriteinfo *info; 1781 { 1782 volatile caddr_t ba, fb; 1783 int depth = gp->g_display.gd_planes; 1784 1785 ba = gp->g_regkva; 1786 fb = gp->g_fbkva; 1787 1788 if (info->set & GRFSPRSET_SHAPE) { 1789 /* 1790 * For an explanation of these weird actions here, see above 1791 * when reading the shape. We set the shape directly into 1792 * the video memory, there's no reason to keep 1k on the 1793 * kernel stack just as template 1794 */ 1795 u_char *image, *mask; 1796 volatile u_short *hwp; 1797 u_char *imp, *mp; 1798 unsigned short row; 1799 1800 /* Cursor off */ 1801 WCrt (ba, CRT_ID_HWGC_MODE, 0x00); 1802 1803 /* 1804 * The Trio64 crashes if the cursor data is written 1805 * while the cursor is displayed. 1806 * Sadly, turning the cursor off is not enough. 1807 * What we have to do is: 1808 * 1. Wait for vertical retrace, to make sure no-one 1809 * has moved the cursor in this sync period (because 1810 * another write then would have no effect, argh!). 1811 * 2. Move the cursor off-screen 1812 * 3. Another wait for v. retrace to make sure the cursor 1813 * is really off. 1814 * 4. Write the data, finally. 1815 * (thanks to Harald Koenig for this tip!) 1816 */ 1817 1818 VerticalRetraceWait(ba); 1819 1820 WCrt (ba, CRT_ID_HWGC_ORIGIN_X_HI, 0x7); 1821 WCrt (ba, CRT_ID_HWGC_ORIGIN_X_LO, 0xff); 1822 WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_LO, 0xff); 1823 WCrt (ba, CRT_ID_HWGC_DSTART_X, 0x3f); 1824 WCrt (ba, CRT_ID_HWGC_DSTART_Y, 0x3f); 1825 WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_HI, 0x7); 1826 1827 if (info->size.y > 64) 1828 info->size.y = 64; 1829 if (info->size.x > 64) 1830 info->size.x = 64; 1831 if (info->size.x < 32) 1832 info->size.x = 32; 1833 1834 image = malloc(HWC_SIZE, M_TEMP, M_WAITOK); 1835 mask = image + HWC_SIZE/2; 1836 1837 copyin(info->image, image, info->size.y * info->size.x / 8); 1838 copyin(info->mask, mask, info->size.y * info->size.x / 8); 1839 1840 hwp = (u_short *)(fb +HWC_OFF); 1841 1842 /* This is necessary in order not to crash the board */ 1843 1844 VerticalRetraceWait(ba); 1845 1846 /* 1847 * setting it is slightly more difficult, because we can't 1848 * force the application to not pass a *smaller* than 1849 * supported bitmap 1850 */ 1851 1852 for (row = 0, mp = mask, imp = image; 1853 row < info->size.y; row++) { 1854 u_short im1, im2, im3, im4, m1, m2, m3, m4; 1855 1856 im1 = *(unsigned short *)imp; 1857 imp += 2; 1858 m1 = *(unsigned short *)mp; 1859 mp += 2; 1860 1861 im2 = *(unsigned short *)imp; 1862 imp += 2; 1863 m2 = *(unsigned short *)mp; 1864 mp += 2; 1865 1866 if (info->size.x > 32) { 1867 im3 = *(unsigned long *)imp; 1868 imp += 4; 1869 m3 = *(unsigned long *)mp; 1870 mp += 4; 1871 im4 = *(unsigned long *)imp; 1872 imp += 4; 1873 m4 = *(unsigned long *)mp; 1874 mp += 4; 1875 } 1876 else 1877 im3 = m3 = im4 = m4 = 0; 1878 1879 switch (depth) { 1880 case 8: 1881 *hwp++ = m1; 1882 *hwp++ = im1; 1883 *hwp++ = m2; 1884 *hwp++ = im2; 1885 *hwp++ = m3; 1886 *hwp++ = im3; 1887 *hwp++ = m4; 1888 *hwp++ = im4; 1889 break; 1890 case 15: 1891 case 16: 1892 *hwp++ = M2I(m1); 1893 *hwp++ = M2I(im1); 1894 *hwp++ = M2I(m2); 1895 *hwp++ = M2I(im2); 1896 *hwp++ = M2I(m3); 1897 *hwp++ = M2I(im3); 1898 *hwp++ = M2I(m4); 1899 *hwp++ = M2I(im4); 1900 break; 1901 case 24: 1902 case 32: 1903 *hwp++ = M2I(im1); 1904 *hwp++ = M2I(m1); 1905 *hwp++ = M2I(im2); 1906 *hwp++ = M2I(m2); 1907 *hwp++ = M2I(im3); 1908 *hwp++ = M2I(m3); 1909 *hwp++ = M2I(im4); 1910 *hwp++ = M2I(m4); 1911 break; 1912 } 1913 } 1914 for (; row < 64; row++) { 1915 *hwp++ = 0x0000; 1916 *hwp++ = 0x0000; 1917 *hwp++ = 0x0000; 1918 *hwp++ = 0x0000; 1919 *hwp++ = 0x0000; 1920 *hwp++ = 0x0000; 1921 *hwp++ = 0x0000; 1922 *hwp++ = 0x0000; 1923 } 1924 free(image, M_TEMP); 1925 cv_setup_hwc(gp, 1, 0, 0, 0, NULL); 1926 cv_hotx = info->hot.x; 1927 cv_hoty = info->hot.y; 1928 1929 /* One must not write twice per vertical blank :-( */ 1930 /* VerticalRetraceWait(ba); */ 1931 1932 cv_setspritepos (gp, &info->pos); 1933 } 1934 if (info->set & GRFSPRSET_CMAP) { 1935 int test; 1936 1937 VerticalRetraceWait(ba); 1938 1939 /* reset colour stack */ 1940 test = RCrt(ba, CRT_ID_HWGC_MODE); 1941 asm volatile("nop"); 1942 switch (depth) { 1943 case 32: 1944 case 24: 1945 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0); 1946 case 16: 1947 case 8: 1948 /* info->cmap.green[1] */ 1949 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0); 1950 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0); 1951 } 1952 1953 test = RCrt(ba, CRT_ID_HWGC_MODE); 1954 asm volatile("nop"); 1955 switch (depth) { 1956 case 8: 1957 WCrt (ba, CRT_ID_HWGC_BG_STACK, 1); 1958 WCrt (ba, CRT_ID_HWGC_BG_STACK, 1); 1959 break; 1960 case 32: case 24: 1961 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff); 1962 case 16: 1963 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff); 1964 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff); 1965 } 1966 } 1967 1968 if (info->set & GRFSPRSET_ENABLE) { 1969 #if 0 1970 if (info->enable) 1971 control = 0x85; 1972 else 1973 control = 0; 1974 WSeq(ba, SEQ_ID_CURSOR_CONTROL, control); 1975 #endif 1976 } 1977 if (info->set & GRFSPRSET_POS) 1978 cv_setspritepos(gp, &info->pos); 1979 if (info->set & GRFSPRSET_HOT) { 1980 1981 cv_hotx = info->hot.x; 1982 cv_hoty = info->hot.y; 1983 cv_setspritepos (gp, &info->pos); 1984 } 1985 return(0); 1986 } 1987 1988 1989 int 1990 cv_getspritemax (gp, pos) 1991 struct grf_softc *gp; 1992 struct grf_position *pos; 1993 { 1994 1995 pos->x = 64; 1996 pos->y = 64; 1997 return(0); 1998 } 1999 2000 #endif /* CV_HARDWARE_CURSOR */ 2001 2002 #endif /* NGRFCV */ 2003