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