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