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