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