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