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