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