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