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