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