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