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