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