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