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