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