1 /* $NetBSD: grf_cl.c,v 1.46 2011/12/15 14:25:13 phx Exp $ */ 2 3 /* 4 * Copyright (c) 1997 Klaus Burkert 5 * Copyright (c) 1995 Ezra Story 6 * Copyright (c) 1995 Kari Mettinen 7 * Copyright (c) 1994 Markus Wild 8 * Copyright (c) 1994 Lutz Vieweg 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by Lutz Vieweg. 22 * 4. The name of the author may not be used to endorse or promote products 23 * derived from this software without specific prior written permission 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 */ 36 #include "opt_amigacons.h" 37 38 #include <sys/cdefs.h> 39 __KERNEL_RCSID(0, "$NetBSD: grf_cl.c,v 1.46 2011/12/15 14:25:13 phx Exp $"); 40 41 #include "grfcl.h" 42 #include "ite.h" 43 #if NGRFCL > 0 44 45 /* 46 * Graphics routines for Cirrus CL GD 5426 boards, 47 * 48 * This code offers low-level routines to access Cirrus Cl GD 5426 49 * graphics-boards from within NetBSD for the Amiga. 50 * No warranties for any kind of function at all - this 51 * code may crash your hardware and scratch your harddisk. Use at your 52 * own risk. Freely distributable. 53 * 54 * Modified for Cirrus CL GD 5426 from 55 * Lutz Vieweg's retina driver by Kari Mettinen 08/94 56 * Contributions by Ill, ScottE, MiL 57 * Extensively hacked and rewritten by Ezra Story (Ezy) 01/95 58 * Picasso/040 patches (wee!) by crest 01/96 59 * 60 * PicassoIV support bz Klaus "crest" Burkert. 61 * Fixed interlace and doublescan, added clockdoubling and 62 * HiColor&TrueColor suuport by crest 01/97 63 * 64 * Thanks to Village Tronic Marketing Gmbh for providing me with 65 * a Picasso-II board. 66 * Thanks for Integrated Electronics Oy Ab for providing me with 67 * Cirrus CL GD 542x family documentation. 68 * 69 * TODO: 70 * Mouse support (almost there! :-)) 71 * Blitter support 72 * 73 */ 74 75 #include <sys/param.h> 76 #include <sys/systm.h> 77 #include <sys/errno.h> 78 #include <sys/ioctl.h> 79 #include <sys/device.h> 80 #include <sys/malloc.h> 81 82 #include <machine/cpu.h> 83 #include <dev/cons.h> 84 #include <amiga/dev/itevar.h> 85 #include <amiga/amiga/device.h> 86 #include <amiga/dev/grfioctl.h> 87 #include <amiga/dev/grfvar.h> 88 #include <amiga/dev/grf_clreg.h> 89 #include <amiga/dev/zbusvar.h> 90 91 int cl_mondefok(struct grfvideo_mode *); 92 void cl_boardinit(struct grf_softc *); 93 static void cl_CompFQ(u_int, u_char *, u_char *, u_char *); 94 int cl_getvmode(struct grf_softc *, struct grfvideo_mode *); 95 int cl_setvmode(struct grf_softc *, unsigned int); 96 int cl_toggle(struct grf_softc *, unsigned short); 97 int cl_getcmap(struct grf_softc *, struct grf_colormap *); 98 int cl_putcmap(struct grf_softc *, struct grf_colormap *); 99 #ifndef CL5426CONSOLE 100 void cl_off(struct grf_softc *); 101 #endif 102 void cl_inittextmode(struct grf_softc *); 103 int cl_ioctl(register struct grf_softc *, u_long, void *); 104 int cl_getmousepos(struct grf_softc *, struct grf_position *); 105 int cl_setmousepos(struct grf_softc *, struct grf_position *); 106 static int cl_setspriteinfo(struct grf_softc *, struct grf_spriteinfo *); 107 int cl_getspriteinfo(struct grf_softc *, struct grf_spriteinfo *); 108 static int cl_getspritemax(struct grf_softc *, struct grf_position *); 109 int cl_blank(struct grf_softc *, int *); 110 int cl_setmonitor(struct grf_softc *, struct grfvideo_mode *); 111 void cl_writesprpos(volatile char *, short, short); 112 void writeshifted(volatile char *, signed char, signed char); 113 114 static void RegWakeup(volatile void *); 115 static void RegOnpass(volatile void *); 116 static void RegOffpass(volatile void *); 117 118 void grfclattach(struct device *, struct device *, void *); 119 int grfclprint(void *, const char *); 120 int grfclmatch(struct device *, struct cfdata *, void *); 121 void cl_memset(unsigned char *, unsigned char, int); 122 123 /* Graphics display definitions. 124 * These are filled by 'grfconfig' using GRFIOCSETMON. 125 */ 126 #define monitor_def_max 24 127 static struct grfvideo_mode monitor_def[24] = { 128 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, 129 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, 130 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0} 131 }; 132 static struct grfvideo_mode *monitor_current = &monitor_def[0]; 133 134 /* Patchable maximum pixel clock */ 135 unsigned long cl_maxpixelclock = 86000000; 136 137 /* Console display definition. 138 * Default hardcoded text mode. This grf_cl is set up to 139 * use one text mode only, and this is it. You may use 140 * grfconfig to change the mode after boot. 141 */ 142 /* Console font */ 143 #ifdef KFONT_8X11 144 #define CIRRUSFONT kernel_font_8x11 145 #define CIRRUSFONTY 11 146 #else 147 #define CIRRUSFONT kernel_font_8x8 148 #define CIRRUSFONTY 8 149 #endif 150 extern unsigned char CIRRUSFONT[]; 151 152 struct grfcltext_mode clconsole_mode = { 153 {255, "", 25000000, 640, 480, 4, 640/8, 680/8, 768/8, 800/8, 154 481, 490, 498, 522, 0}, 155 8, CIRRUSFONTY, 80, 480 / CIRRUSFONTY, CIRRUSFONT, 32, 255 156 }; 157 /* Console colors */ 158 unsigned char clconscolors[3][3] = { /* background, foreground, hilite */ 159 {0, 0x40, 0x50}, {152, 152, 152}, {255, 255, 255} 160 }; 161 162 int cltype = 0; /* Picasso, Spectrum or Piccolo */ 163 int cl_64bit = 0; /* PiccoloSD64 or PicassoIV */ 164 unsigned char cl_pass_toggle; /* passthru status tracker */ 165 166 /* 167 * because all 542x-boards have 2 configdev entries, one for 168 * framebuffer mem and the other for regs, we have to hold onto 169 * the pointers globally until we match on both. This and 'cltype' 170 * are the primary obsticles to multiple board support, but if you 171 * have multiple boards you have bigger problems than grf_cl. 172 */ 173 static void *cl_fbaddr = 0; /* framebuffer */ 174 static void *cl_regaddr = 0; /* registers */ 175 static int cl_fbsize; /* framebuffer size */ 176 static int cl_fbautosize; /* framebuffer autoconfig size */ 177 178 179 /* 180 * current sprite info, if you add support for multiple boards 181 * make this an array or something 182 */ 183 struct grf_spriteinfo cl_cursprite; 184 185 /* sprite bitmaps in kernel stack, you'll need to arrayize these too if 186 * you add multiple board support 187 */ 188 static unsigned char cl_imageptr[8 * 64], cl_maskptr[8 * 64]; 189 static unsigned char cl_sprred[2], cl_sprgreen[2], cl_sprblue[2]; 190 191 /* standard driver stuff */ 192 CFATTACH_DECL(grfcl, sizeof(struct grf_softc), 193 grfclmatch, grfclattach, NULL, NULL); 194 195 static struct cfdata *cfdata; 196 197 int 198 grfclmatch(struct device *pdp, struct cfdata *cfp, void *auxp) 199 { 200 struct zbus_args *zap; 201 static int regprod, fbprod, fbprod2; 202 int error; 203 204 fbprod2 = 0; 205 zap = auxp; 206 207 #ifndef CL5426CONSOLE 208 if (amiga_realconfig == 0) 209 return (0); 210 #endif 211 212 /* Grab the first board we encounter as the preferred one. This will 213 * allow one board to work in a multiple 5426 board system, but not 214 * multiple boards at the same time. */ 215 if (cltype == 0) { 216 switch (zap->manid) { 217 case PICASSO: 218 switch (zap->prodid) { 219 case 11: 220 case 12: 221 regprod = 12; 222 fbprod = 11; 223 error = 0; 224 break; 225 case 22: 226 fbprod2 = 22; 227 error = 0; 228 break; 229 case 21: 230 case 23: 231 regprod = 23; 232 fbprod = 21; 233 cl_64bit = 1; 234 error = 0; 235 break; 236 case 24: 237 regprod = 24; 238 fbprod = 24; 239 cl_64bit = 1; 240 error = 0; 241 break; 242 default: 243 error = 1; 244 break; 245 } 246 if (error == 1) 247 return (0); 248 else 249 break; 250 case SPECTRUM: 251 if (zap->prodid != 2 && zap->prodid != 1) 252 return (0); 253 regprod = 2; 254 fbprod = 1; 255 break; 256 case PICCOLO: 257 switch (zap->prodid) { 258 case 5: 259 case 6: 260 regprod = 6; 261 fbprod = 5; 262 error = 0; 263 break; 264 case 10: 265 case 11: 266 regprod = 11; 267 fbprod = 10; 268 cl_64bit = 1; 269 error = 0; 270 break; 271 default: 272 error = 1; 273 break; 274 } 275 if (error == 1) 276 return (0); 277 else 278 break; 279 default: 280 return (0); 281 } 282 cltype = zap->manid; 283 } else { 284 if (cltype != zap->manid) { 285 return (0); 286 } 287 } 288 289 /* Configure either registers or framebuffer in any order */ 290 if ((cltype == PICASSO) && (cl_64bit == 1)) { 291 switch (zap->prodid) { 292 case 21: 293 cl_fbaddr = zap->va; 294 cl_fbautosize = zap->size; 295 break; 296 case 22: 297 cl_fbautosize += zap->size; 298 break; 299 case 23: 300 cl_regaddr = (void *)((unsigned long)(zap->va) + 0x10000); 301 break; 302 case 24: 303 cl_regaddr = (void *)((unsigned long)(zap->va) + 0x600000); 304 /* check for PicassoIV with 64MB config and handle it */ 305 if (zap->size == 0x04000000) { 306 cl_fbaddr = (void *)((unsigned long)(zap->va) + 0x02000000); 307 } else { 308 cl_fbaddr = (void *)((unsigned long)(zap->va) + 0x01000000); 309 } 310 cl_fbautosize = 0x400000; 311 break; 312 default: 313 return (0); 314 } 315 } 316 else { 317 if (zap->prodid == regprod) 318 cl_regaddr = zap->va; 319 else 320 if (zap->prodid == fbprod) { 321 cl_fbaddr = zap->va; 322 cl_fbautosize = zap->size; 323 } else 324 return (0); 325 } 326 327 #ifdef CL5426CONSOLE 328 if (amiga_realconfig == 0) { 329 cfdata = cfp; 330 } 331 #endif 332 333 return (1); 334 } 335 336 void 337 grfclattach(struct device *pdp, struct device *dp, void *auxp) 338 { 339 static struct grf_softc congrf; 340 struct zbus_args *zap; 341 struct grf_softc *gp; 342 static char attachflag = 0; 343 344 zap = auxp; 345 346 printf("\n"); 347 348 /* make sure both halves have matched */ 349 if (!cl_regaddr || !cl_fbaddr) 350 return; 351 352 /* do all that messy console/grf stuff */ 353 if (dp == NULL) 354 gp = &congrf; 355 else 356 gp = (struct grf_softc *) dp; 357 358 if (dp != NULL && congrf.g_regkva != 0) { 359 /* 360 * inited earlier, just copy (not device struct) 361 */ 362 memcpy(&gp->g_display, &congrf.g_display, 363 (char *) &gp[1] - (char *) &gp->g_display); 364 } else { 365 gp->g_regkva = (volatile void *) cl_regaddr; 366 gp->g_fbkva = (volatile void *) cl_fbaddr; 367 368 gp->g_unit = GRF_CL5426_UNIT; 369 gp->g_mode = cl_mode; 370 #if NITE > 0 371 gp->g_conpri = grfcl_cnprobe(); 372 #endif 373 gp->g_flags = GF_ALIVE; 374 375 /* wakeup the board */ 376 cl_boardinit(gp); 377 #ifdef CL5426CONSOLE 378 #if NITE > 0 379 grfcl_iteinit(gp); 380 #endif 381 (void) cl_load_mon(gp, &clconsole_mode); 382 #endif 383 384 } 385 386 /* 387 * attach grf (once) 388 */ 389 if (amiga_config_found(cfdata, &gp->g_device, gp, grfclprint)) { 390 attachflag = 1; 391 printf("grfcl: %dMB ", cl_fbsize / 0x100000); 392 switch (cltype) { 393 case PICASSO: 394 if (cl_64bit == 1) { 395 printf("Picasso IV"); 396 /* 135MHz will be supported if we 397 * have a palette doubling mode. 398 */ 399 cl_maxpixelclock = 86000000; 400 } 401 else { 402 printf("Picasso II"); 403 404 /* check for PicassoII+ (crest) */ 405 if(zap->serno == 0x00100000) 406 printf("+"); 407 408 /* determine used Gfx/chipset (crest) */ 409 vgaw(gp->g_regkva, CRT_ADDRESS, 0x27); /* Chip ID */ 410 switch(vgar(gp->g_regkva, CRT_ADDRESS_R)>>2) { 411 case 0x24: 412 printf(" (with CL-GD5426)"); 413 break; 414 case 0x26: 415 printf(" (with CL-GD5428)"); 416 break; 417 case 0x27: 418 printf(" (with CL-GD5429)"); 419 break; 420 } 421 cl_maxpixelclock = 86000000; 422 } 423 break; 424 case SPECTRUM: 425 printf("Spectrum"); 426 cl_maxpixelclock = 90000000; 427 break; 428 case PICCOLO: 429 if (cl_64bit == 1) { 430 printf("Piccolo SD64"); 431 /* 110MHz will be supported if we 432 * have a palette doubling mode. 433 */ 434 cl_maxpixelclock = 90000000; 435 } else { 436 printf("Piccolo"); 437 cl_maxpixelclock = 90000000; 438 } 439 break; 440 } 441 printf(" being used\n"); 442 #ifdef CL_OVERCLOCK 443 cl_maxpixelclock = 115000000; 444 #endif 445 } else { 446 if (!attachflag) 447 printf("grfcl unattached!!\n"); 448 } 449 } 450 451 int 452 grfclprint(void *auxp, const char *pnp) 453 { 454 if (pnp) 455 aprint_normal("ite at %s: ", pnp); 456 return (UNCONF); 457 } 458 459 void 460 cl_boardinit(struct grf_softc *gp) 461 { 462 volatile unsigned char *ba = gp->g_regkva; 463 int x; 464 465 if ((cltype == PICASSO) && (cl_64bit == 1)) { /* PicassoIV */ 466 WCrt(ba, 0x51, 0x00); /* disable capture (FlickerFixer) */ 467 delay(200000); /* wait some time (two frames as of now) */ 468 WGfx(ba, 0x2f, 0x00); /* get Blitter into 542x */ 469 WGfx(ba, GCT_ID_RESERVED, 0x00); /* compatibility mode */ 470 WGfx(ba, GCT_ID_BLT_STAT_START, 0x00); /* or at least, try so... */ 471 cl_fbsize = cl_fbautosize; 472 } else { 473 474 /* wakeup board and flip passthru OFF */ 475 RegWakeup(ba); 476 RegOnpass(ba); 477 478 vgaw(ba, 0x46e8, 0x16); 479 vgaw(ba, 0x102, 1); 480 vgaw(ba, 0x46e8, 0x0e); 481 if (cl_64bit != 1) 482 vgaw(ba, 0x3c3, 1); 483 484 cl_fbsize = cl_fbautosize; 485 486 /* setup initial unchanging parameters */ 487 488 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21); /* 8 dot - display off */ 489 vgaw(ba, GREG_MISC_OUTPUT_W, 0xed); /* mem disable */ 490 491 WGfx(ba, GCT_ID_OFFSET_1, 0xec); /* magic cookie */ 492 WSeq(ba, SEQ_ID_UNLOCK_EXT, 0x12); /* yum! cookies! */ 493 494 if (cl_64bit == 1) { 495 WSeq(ba, SEQ_ID_CONF_RBACK, 0x00); 496 WSeq(ba, SEQ_ID_DRAM_CNTL, (cl_fbsize / 0x100000 == 2) ? 0x38 : 0xb8); 497 } else { 498 WSeq(ba, SEQ_ID_DRAM_CNTL, 0xb0); 499 } 500 WSeq(ba, SEQ_ID_RESET, 0x03); 501 WSeq(ba, SEQ_ID_MAP_MASK, 0xff); 502 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); 503 WSeq(ba, SEQ_ID_MEMORY_MODE, 0x0e); /* a or 6? */ 504 WSeq(ba, SEQ_ID_EXT_SEQ_MODE, (cltype == PICASSO) ? 0x21 : 0x81); 505 WSeq(ba, SEQ_ID_EEPROM_CNTL, 0x00); 506 if (cl_64bit == 1) 507 WSeq(ba, SEQ_ID_PERF_TUNE, 0x5a); 508 else 509 WSeq(ba, SEQ_ID_PERF_TUNE, 0x0a); /* mouse 0a fa */ 510 WSeq(ba, SEQ_ID_SIG_CNTL, 0x02); 511 WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x04); 512 513 if (cl_64bit == 1) 514 WSeq(ba, SEQ_ID_MCLK_SELECT, 0x1c); 515 else 516 WSeq(ba, SEQ_ID_MCLK_SELECT, 0x22); 517 518 WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00); 519 WCrt(ba, CRT_ID_CURSOR_START, 0x00); 520 WCrt(ba, CRT_ID_CURSOR_END, 0x08); 521 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00); 522 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00); 523 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00); 524 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00); 525 526 WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x07); 527 WCrt(ba, CRT_ID_MODE_CONTROL, 0xe3); 528 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); /* ff */ 529 WCrt(ba, CRT_ID_EXT_DISP_CNTL, 0x22); 530 if (cl_64bit == 1) { 531 WCrt(ba, CRT_ID_SYNC_ADJ_GENLOCK, 0x00); 532 WCrt(ba, CRT_ID_OVERLAY_EXT_CTRL_REG, 0x40); 533 } 534 WSeq(ba, SEQ_ID_CURSOR_STORE, 0x3c); /* mouse 0x00 */ 535 536 WGfx(ba, GCT_ID_SET_RESET, 0x00); 537 WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00); 538 WGfx(ba, GCT_ID_DATA_ROTATE, 0x00); 539 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00); 540 WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x00); 541 WGfx(ba, GCT_ID_MISC, 0x01); 542 WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f); 543 WGfx(ba, GCT_ID_BITMASK, 0xff); 544 WGfx(ba, GCT_ID_MODE_EXT, 0x28); 545 546 for (x = 0; x < 0x10; x++) 547 WAttr(ba, x, x); 548 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x01); 549 WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00); 550 WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f); 551 WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00); 552 WAttr(ba, ACT_ID_COLOR_SELECT, 0x00); 553 WAttr(ba, 0x34, 0x00); 554 555 vgaw(ba, VDAC_MASK, 0xff); 556 vgaw(ba, GREG_MISC_OUTPUT_W, 0xef); 557 558 WGfx(ba, GCT_ID_BLT_STAT_START, 0x04); 559 WGfx(ba, GCT_ID_BLT_STAT_START, 0x00); 560 } 561 562 /* colors initially set to greyscale */ 563 vgaw(ba, VDAC_ADDRESS_W, 0); 564 for (x = 255; x >= 0; x--) { 565 vgaw(ba, VDAC_DATA, x); 566 vgaw(ba, VDAC_DATA, x); 567 vgaw(ba, VDAC_DATA, x); 568 } 569 /* set sprite bitmap pointers */ 570 cl_cursprite.image = cl_imageptr; 571 cl_cursprite.mask = cl_maskptr; 572 cl_cursprite.cmap.red = cl_sprred; 573 cl_cursprite.cmap.green = cl_sprgreen; 574 cl_cursprite.cmap.blue = cl_sprblue; 575 576 if (cl_64bit == 0) { 577 578 /* check for 1MB or 2MB board (crest) */ 579 volatile unsigned long *cl_fbtestaddr; 580 cl_fbtestaddr = (volatile unsigned long *)gp->g_fbkva; 581 582 WGfx(ba, GCT_ID_OFFSET_0, 0x40); 583 *cl_fbtestaddr = 0x12345678; 584 585 if (*cl_fbtestaddr != 0x12345678) { 586 WSeq(ba, SEQ_ID_DRAM_CNTL, 0x30); 587 cl_fbsize = 0x100000; 588 } 589 else 590 { 591 cl_fbsize = 0x200000; 592 } 593 } 594 WGfx(ba, GCT_ID_OFFSET_0, 0x00); 595 } 596 597 598 int 599 cl_getvmode(struct grf_softc *gp, struct grfvideo_mode *vm) 600 { 601 struct grfvideo_mode *gv; 602 603 #ifdef CL5426CONSOLE 604 /* Handle grabbing console mode */ 605 if (vm->mode_num == 255) { 606 memcpy(vm, &clconsole_mode, sizeof(struct grfvideo_mode)); 607 /* XXX so grfconfig can tell us the correct text dimensions. */ 608 vm->depth = clconsole_mode.fy; 609 } else 610 #endif 611 { 612 if (vm->mode_num == 0) 613 vm->mode_num = (monitor_current - monitor_def) + 1; 614 if (vm->mode_num < 1 || vm->mode_num > monitor_def_max) 615 return (EINVAL); 616 gv = monitor_def + (vm->mode_num - 1); 617 if (gv->mode_num == 0) 618 return (EINVAL); 619 620 memcpy(vm, gv, sizeof(struct grfvideo_mode)); 621 } 622 623 /* adjust internal values to pixel values */ 624 625 vm->hblank_start *= 8; 626 vm->hsync_start *= 8; 627 vm->hsync_stop *= 8; 628 vm->htotal *= 8; 629 630 return (0); 631 } 632 633 634 int 635 cl_setvmode(struct grf_softc *gp, unsigned mode) 636 { 637 if (!mode || (mode > monitor_def_max) || 638 monitor_def[mode - 1].mode_num == 0) 639 return (EINVAL); 640 641 monitor_current = monitor_def + (mode - 1); 642 643 return (0); 644 } 645 646 #ifndef CL5426CONSOLE 647 void 648 cl_off(struct grf_softc *gp) 649 { 650 char *ba = gp->g_regkva; 651 652 /* 653 * we'll put the pass-through on for cc ite and set Full Bandwidth bit 654 * on just in case it didn't work...but then it doesn't matter does 655 * it? =) 656 */ 657 RegOnpass(ba); 658 vgaw(ba, SEQ_ADDRESS, SEQ_ID_CLOCKING_MODE); 659 vgaw(ba, SEQ_ADDRESS_W, vgar(ba, SEQ_ADDRESS_W) | 0x20); 660 } 661 #endif 662 663 int 664 cl_blank(struct grf_softc *gp, int *on) 665 { 666 WSeq(gp->g_regkva, SEQ_ID_CLOCKING_MODE, *on > 0 ? 0x01 : 0x21); 667 return(0); 668 } 669 670 /* 671 * Change the mode of the display. 672 * Return a UNIX error number or 0 for success. 673 */ 674 int 675 cl_mode(register struct grf_softc *gp, u_long cmd, void *arg, u_long a2, int a3) 676 { 677 int error; 678 679 switch (cmd) { 680 case GM_GRFON: 681 error = cl_load_mon(gp, 682 (struct grfcltext_mode *) monitor_current) ? 0 : EINVAL; 683 return (error); 684 685 case GM_GRFOFF: 686 #ifndef CL5426CONSOLE 687 cl_off(gp); 688 #else 689 cl_load_mon(gp, &clconsole_mode); 690 #endif 691 return (0); 692 693 case GM_GRFCONFIG: 694 return (0); 695 696 case GM_GRFGETVMODE: 697 return (cl_getvmode(gp, (struct grfvideo_mode *) arg)); 698 699 case GM_GRFSETVMODE: 700 error = cl_setvmode(gp, *(unsigned *) arg); 701 if (!error && (gp->g_flags & GF_GRFON)) 702 cl_load_mon(gp, 703 (struct grfcltext_mode *) monitor_current); 704 return (error); 705 706 case GM_GRFGETNUMVM: 707 *(int *) arg = monitor_def_max; 708 return (0); 709 710 case GM_GRFIOCTL: 711 return (cl_ioctl(gp, a2, arg)); 712 713 default: 714 break; 715 } 716 717 return (EPASSTHROUGH); 718 } 719 720 int 721 cl_ioctl(register struct grf_softc *gp, u_long cmd, void *data) 722 { 723 switch (cmd) { 724 case GRFIOCGSPRITEPOS: 725 return (cl_getmousepos(gp, (struct grf_position *) data)); 726 727 case GRFIOCSSPRITEPOS: 728 return (cl_setmousepos(gp, (struct grf_position *) data)); 729 730 case GRFIOCSSPRITEINF: 731 return (cl_setspriteinfo(gp, (struct grf_spriteinfo *) data)); 732 733 case GRFIOCGSPRITEINF: 734 return (cl_getspriteinfo(gp, (struct grf_spriteinfo *) data)); 735 736 case GRFIOCGSPRITEMAX: 737 return (cl_getspritemax(gp, (struct grf_position *) data)); 738 739 case GRFIOCGETCMAP: 740 return (cl_getcmap(gp, (struct grf_colormap *) data)); 741 742 case GRFIOCPUTCMAP: 743 return (cl_putcmap(gp, (struct grf_colormap *) data)); 744 745 case GRFIOCBITBLT: 746 break; 747 748 case GRFTOGGLE: 749 return (cl_toggle(gp, 0)); 750 751 case GRFIOCSETMON: 752 return (cl_setmonitor(gp, (struct grfvideo_mode *) data)); 753 754 case GRFIOCBLANK: 755 return (cl_blank(gp, (int *)data)); 756 757 } 758 return (EPASSTHROUGH); 759 } 760 761 int 762 cl_getmousepos(struct grf_softc *gp, struct grf_position *data) 763 { 764 data->x = cl_cursprite.pos.x; 765 data->y = cl_cursprite.pos.y; 766 return (0); 767 } 768 769 void 770 cl_writesprpos(volatile char *ba, short x, short y) 771 { 772 /* we want to use a 16-bit write to 3c4 so no macros used */ 773 volatile unsigned char *cwp; 774 volatile unsigned short *wp; 775 776 cwp = ba + 0x3c4; 777 wp = (volatile unsigned short *)cwp; 778 779 /* 780 * don't ask me why, but apparently you can't do a 16-bit write with 781 * x-position like with y-position below (dagge) 782 */ 783 cwp[0] = 0x10 | ((x << 5) & 0xff); 784 cwp[1] = (x >> 3) & 0xff; 785 786 *wp = 0x1100 | ((y & 7) << 13) | ((y >> 3) & 0xff); 787 } 788 789 void 790 writeshifted(volatile char *to, signed char shiftx, signed char shifty) 791 { 792 int y; 793 unsigned long long *tptr, *iptr, *mptr, line; 794 795 tptr = (unsigned long long *) __UNVOLATILE(to); 796 iptr = (unsigned long long *) cl_cursprite.image; 797 mptr = (unsigned long long *) cl_cursprite.mask; 798 799 shiftx = shiftx < 0 ? 0 : shiftx; 800 shifty = shifty < 0 ? 0 : shifty; 801 802 /* start reading shifty lines down, and 803 * shift each line in by shiftx 804 */ 805 for (y = shifty; y < 64; y++) { 806 807 /* image */ 808 line = iptr[y]; 809 *tptr++ = line << shiftx; 810 811 /* mask */ 812 line = mptr[y]; 813 *tptr++ = line << shiftx; 814 } 815 816 /* clear the remainder */ 817 for (y = shifty; y > 0; y--) { 818 *tptr++ = 0; 819 *tptr++ = 0; 820 } 821 } 822 823 int 824 cl_setmousepos(struct grf_softc *gp, struct grf_position *data) 825 { 826 volatile char *ba = gp->g_regkva; 827 short rx, ry, prx, pry; 828 #ifdef CL_SHIFTSPRITE 829 volatile char *fb = gp->g_fbkva; 830 volatile char *sprite = fb + (cl_fbsize - 1024); 831 #endif 832 833 /* no movement */ 834 if (cl_cursprite.pos.x == data->x && cl_cursprite.pos.y == data->y) 835 return (0); 836 837 /* current and previous real coordinates */ 838 rx = data->x - cl_cursprite.hot.x; 839 ry = data->y - cl_cursprite.hot.y; 840 prx = cl_cursprite.pos.x - cl_cursprite.hot.x; 841 pry = cl_cursprite.pos.y - cl_cursprite.hot.y; 842 843 /* 844 * if we are/were on an edge, create (un)shifted bitmap -- 845 * ripped out optimization (not extremely worthwhile, 846 * and kind of buggy anyhow). 847 */ 848 #ifdef CL_SHIFTSPRITE 849 if (rx < 0 || ry < 0 || prx < 0 || pry < 0) { 850 writeshifted(sprite, rx < 0 ? -rx : 0, ry < 0 ? -ry : 0); 851 } 852 #endif 853 854 /* do movement, save position */ 855 cl_writesprpos(ba, rx < 0 ? 0 : rx, ry < 0 ? 0 : ry); 856 cl_cursprite.pos.x = data->x; 857 cl_cursprite.pos.y = data->y; 858 859 return (0); 860 } 861 862 int 863 cl_getspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *data) 864 { 865 copyout(&cl_cursprite, data, sizeof(struct grf_spriteinfo)); 866 copyout(cl_cursprite.image, data->image, 64 * 8); 867 copyout(cl_cursprite.mask, data->mask, 64 * 8); 868 return (0); 869 } 870 871 static int 872 cl_setspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *data) 873 { 874 volatile unsigned char *ba = gp->g_regkva, *fb = gp->g_fbkva; 875 volatile char *sprite = fb + (cl_fbsize - 1024); 876 877 if (data->set & GRFSPRSET_SHAPE) { 878 879 unsigned short dsx, dsy, i; 880 unsigned long *di, *dm, *si, *sm; 881 unsigned long ssi[128], ssm[128]; 882 struct grf_position gpos; 883 884 885 /* check for a too large sprite (no clipping!) */ 886 dsy = data->size.y; 887 dsx = data->size.x; 888 if (dsy > 64 || dsx > 64) 889 return(EINVAL); 890 891 /* prepare destination */ 892 di = (unsigned long *)cl_cursprite.image; 893 dm = (unsigned long *)cl_cursprite.mask; 894 cl_memset((unsigned char *)di, 0, 8*64); 895 cl_memset((unsigned char *)dm, 0, 8*64); 896 897 /* two alternatives: 64 across, then it's 898 * the same format we use, just copy. Otherwise, 899 * copy into tmp buf and recopy skipping the 900 * unused 32 bits. 901 */ 902 if ((dsx - 1) / 32) { 903 copyin(data->image, di, 8 * dsy); 904 copyin(data->mask, dm, 8 * dsy); 905 } else { 906 si = ssi; sm = ssm; 907 copyin(data->image, si, 4 * dsy); 908 copyin(data->mask, sm, 4 * dsy); 909 for (i = 0; i < dsy; i++) { 910 *di = *si++; 911 *dm = *sm++; 912 di += 2; 913 dm += 2; 914 } 915 } 916 917 /* set size */ 918 cl_cursprite.size.x = data->size.x; 919 cl_cursprite.size.y = data->size.y; 920 921 /* forcably load into board */ 922 gpos.x = cl_cursprite.pos.x; 923 gpos.y = cl_cursprite.pos.y; 924 cl_cursprite.pos.x = -1; 925 cl_cursprite.pos.y = -1; 926 writeshifted(sprite, 0, 0); 927 cl_setmousepos(gp, &gpos); 928 929 } 930 if (data->set & GRFSPRSET_HOT) { 931 932 cl_cursprite.hot = data->hot; 933 934 } 935 if (data->set & GRFSPRSET_CMAP) { 936 937 u_char red[2], green[2], blue[2]; 938 939 copyin(data->cmap.red, red, 2); 940 copyin(data->cmap.green, green, 2); 941 copyin(data->cmap.blue, blue, 2); 942 memcpy(cl_cursprite.cmap.red, red, 2); 943 memcpy(cl_cursprite.cmap.green, green, 2); 944 memcpy(cl_cursprite.cmap.blue, blue, 2); 945 946 /* enable and load colors 256 & 257 */ 947 WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x06); 948 949 /* 256 */ 950 vgaw(ba, VDAC_ADDRESS_W, 0x00); 951 if (cltype == PICASSO) { 952 vgaw(ba, VDAC_DATA, (u_char) (red[0] >> 2)); 953 vgaw(ba, VDAC_DATA, (u_char) (green[0] >> 2)); 954 vgaw(ba, VDAC_DATA, (u_char) (blue[0] >> 2)); 955 } else { 956 vgaw(ba, VDAC_DATA, (u_char) (blue[0] >> 2)); 957 vgaw(ba, VDAC_DATA, (u_char) (green[0] >> 2)); 958 vgaw(ba, VDAC_DATA, (u_char) (red[0] >> 2)); 959 } 960 961 /* 257 */ 962 vgaw(ba, VDAC_ADDRESS_W, 0x0f); 963 if (cltype == PICASSO) { 964 vgaw(ba, VDAC_DATA, (u_char) (red[1] >> 2)); 965 vgaw(ba, VDAC_DATA, (u_char) (green[1] >> 2)); 966 vgaw(ba, VDAC_DATA, (u_char) (blue[1] >> 2)); 967 } else { 968 vgaw(ba, VDAC_DATA, (u_char) (blue[1] >> 2)); 969 vgaw(ba, VDAC_DATA, (u_char) (green[1] >> 2)); 970 vgaw(ba, VDAC_DATA, (u_char) (red[1] >> 2)); 971 } 972 973 /* turn on/off sprite */ 974 if (cl_cursprite.enable) { 975 WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x05); 976 } else { 977 WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x04); 978 } 979 980 } 981 if (data->set & GRFSPRSET_ENABLE) { 982 983 if (data->enable == 1) { 984 WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x05); 985 cl_cursprite.enable = 1; 986 } else { 987 WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x04); 988 cl_cursprite.enable = 0; 989 } 990 991 } 992 if (data->set & GRFSPRSET_POS) { 993 994 /* force placement */ 995 cl_cursprite.pos.x = -1; 996 cl_cursprite.pos.y = -1; 997 998 /* do it */ 999 cl_setmousepos(gp, &data->pos); 1000 1001 } 1002 return (0); 1003 } 1004 1005 static int 1006 cl_getspritemax(struct grf_softc *gp, struct grf_position *data) 1007 { 1008 if (gp->g_display.gd_planes == 24) 1009 return (EINVAL); 1010 data->x = 64; 1011 data->y = 64; 1012 return (0); 1013 } 1014 1015 int 1016 cl_setmonitor(struct grf_softc *gp, struct grfvideo_mode *gv) 1017 { 1018 struct grfvideo_mode *md; 1019 1020 if (!cl_mondefok(gv)) 1021 return(EINVAL); 1022 1023 #ifdef CL5426CONSOLE 1024 /* handle interactive setting of console mode */ 1025 if (gv->mode_num == 255) { 1026 memcpy(&clconsole_mode.gv, gv, sizeof(struct grfvideo_mode)); 1027 clconsole_mode.gv.hblank_start /= 8; 1028 clconsole_mode.gv.hsync_start /= 8; 1029 clconsole_mode.gv.hsync_stop /= 8; 1030 clconsole_mode.gv.htotal /= 8; 1031 clconsole_mode.rows = gv->disp_height / clconsole_mode.fy; 1032 clconsole_mode.cols = gv->disp_width / clconsole_mode.fx; 1033 if (!(gp->g_flags & GF_GRFON)) 1034 cl_load_mon(gp, &clconsole_mode); 1035 #if NITE > 0 1036 ite_reinit(gp->g_itedev); 1037 #endif 1038 return (0); 1039 } 1040 #endif 1041 1042 md = monitor_def + (gv->mode_num - 1); 1043 memcpy(md, gv, sizeof(struct grfvideo_mode)); 1044 1045 /* adjust pixel oriented values to internal rep. */ 1046 1047 md->hblank_start /= 8; 1048 md->hsync_start /= 8; 1049 md->hsync_stop /= 8; 1050 md->htotal /= 8; 1051 1052 return (0); 1053 } 1054 1055 int 1056 cl_getcmap(struct grf_softc *gfp, struct grf_colormap *cmap) 1057 { 1058 volatile unsigned char *ba; 1059 u_char red[256], green[256], blue[256], *rp, *gp, *bp; 1060 short x; 1061 int error; 1062 1063 if (cmap->count == 0 || cmap->index >= 256) 1064 return 0; 1065 1066 if (cmap->count > 256 - cmap->index) 1067 cmap->count = 256 - cmap->index; 1068 1069 ba = gfp->g_regkva; 1070 /* first read colors out of the chip, then copyout to userspace */ 1071 vgaw(ba, VDAC_ADDRESS_R, cmap->index); 1072 x = cmap->count - 1; 1073 1074 /* 1075 * Some sort 'o Magic. Spectrum has some changes on the board to speed 1076 * up 15 and 16Bit modes. They can access these modes with easy-to-programm 1077 * rgbrgbrgb instead of rrrgggbbb. Side effect: when in 8Bit mode, rgb 1078 * is swapped to bgr. I wonder if we need to check for 8Bit though, ill 1079 */ 1080 1081 /* 1082 * The source for the above comment is somewhat unknow to me. 1083 * The Spectrum, Piccolo and PiccoloSD64 have the analog Red and Blue 1084 * lines swapped. In 24BPP this provides RGB instead of BGR as it would 1085 * be native to the chipset. This requires special programming for the 1086 * CLUT in 8BPP to compensate and avoid false colors. 1087 * I didn't find any special stuff for 15 and 16BPP though, crest. 1088 */ 1089 1090 switch (cltype) { 1091 case SPECTRUM: 1092 case PICCOLO: 1093 rp = blue + cmap->index; 1094 gp = green + cmap->index; 1095 bp = red + cmap->index; 1096 break; 1097 case PICASSO: 1098 rp = red + cmap->index; 1099 gp = green + cmap->index; 1100 bp = blue + cmap->index; 1101 break; 1102 default: 1103 rp = gp = bp = 0; 1104 break; 1105 } 1106 1107 do { 1108 *rp++ = vgar(ba, VDAC_DATA) << 2; 1109 *gp++ = vgar(ba, VDAC_DATA) << 2; 1110 *bp++ = vgar(ba, VDAC_DATA) << 2; 1111 } while (x-- > 0); 1112 1113 if (!(error = copyout(red + cmap->index, cmap->red, cmap->count)) 1114 && !(error = copyout(green + cmap->index, cmap->green, cmap->count)) 1115 && !(error = copyout(blue + cmap->index, cmap->blue, cmap->count))) 1116 return (0); 1117 1118 return (error); 1119 } 1120 1121 int 1122 cl_putcmap(struct grf_softc *gfp, struct grf_colormap *cmap) 1123 { 1124 volatile unsigned char *ba; 1125 u_char red[256], green[256], blue[256], *rp, *gp, *bp; 1126 short x; 1127 int error; 1128 1129 if (cmap->count == 0 || cmap->index >= 256) 1130 return (0); 1131 1132 if (cmap->count > 256 - cmap->index) 1133 cmap->count = 256 - cmap->index; 1134 1135 /* first copy the colors into kernelspace */ 1136 if (!(error = copyin(cmap->red, red + cmap->index, cmap->count)) 1137 && !(error = copyin(cmap->green, green + cmap->index, cmap->count)) 1138 && !(error = copyin(cmap->blue, blue + cmap->index, cmap->count))) { 1139 ba = gfp->g_regkva; 1140 vgaw(ba, VDAC_ADDRESS_W, cmap->index); 1141 x = cmap->count - 1; 1142 1143 switch (cltype) { 1144 case SPECTRUM: 1145 case PICCOLO: 1146 rp = blue + cmap->index; 1147 gp = green + cmap->index; 1148 bp = red + cmap->index; 1149 break; 1150 case PICASSO: 1151 rp = red + cmap->index; 1152 gp = green + cmap->index; 1153 bp = blue + cmap->index; 1154 break; 1155 default: 1156 rp = gp = bp = 0; 1157 break; 1158 } 1159 1160 do { 1161 vgaw(ba, VDAC_DATA, *rp++ >> 2); 1162 vgaw(ba, VDAC_DATA, *gp++ >> 2); 1163 vgaw(ba, VDAC_DATA, *bp++ >> 2); 1164 } while (x-- > 0); 1165 return (0); 1166 } else 1167 return (error); 1168 } 1169 1170 1171 int 1172 cl_toggle(struct grf_softc *gp, unsigned short wopp) 1173 /* wopp: don't need that one yet, ill */ 1174 { 1175 volatile void *ba; 1176 1177 ba = gp->g_regkva; 1178 1179 if (cl_pass_toggle) { 1180 RegOffpass(ba); 1181 } else { 1182 RegOnpass(ba); 1183 } 1184 return (0); 1185 } 1186 1187 static void 1188 cl_CompFQ(u_int fq, u_char *num, u_char *denom, u_char *clkdoub) 1189 { 1190 #define OSC 14318180 1191 /* OK, here's what we're doing here: 1192 * 1193 * OSC * NUMERATOR 1194 * VCLK = ------------------- Hz 1195 * DENOMINATOR * (1+P) 1196 * 1197 * so we're given VCLK and we should give out some useful 1198 * values.... 1199 * 1200 * NUMERATOR is 7 bits wide 1201 * DENOMINATOR is 5 bits wide with bit P in the same char as bit 0. 1202 * 1203 * We run through all the possible combinations and 1204 * return the values which deviate the least from the chosen frequency. 1205 * 1206 */ 1207 #define OSC 14318180 1208 #define count(n,d,p) ((OSC * n)/(d * (1+p))) 1209 1210 unsigned char n, d, p, minn, mind, minp = 0; 1211 unsigned long err, minerr; 1212 1213 /* 1214 numer = 0x00 - 0x7f 1215 denom = 0x00 - 0x1f (1) 0x20 - 0x3e (even) 1216 */ 1217 1218 /* find lowest error in 6144 iterations. */ 1219 minerr = fq; 1220 minn = 0; 1221 mind = 0; 1222 p = 0; 1223 1224 if ((cl_64bit == 1) && (fq >= 86000000)) 1225 { 1226 for (d = 1; d < 0x20; d++) { 1227 for (n = 1; n < 0x80; n++) { 1228 err = abs(count(n, d, 0) - fq); 1229 if (err < minerr) { 1230 minerr = err; 1231 minn = n; 1232 mind = d; 1233 minp = 1; 1234 } 1235 } 1236 } 1237 *clkdoub = 1; 1238 } 1239 else { 1240 for (d = 1; d < 0x20; d++) { 1241 for (n = 1; n < 0x80; n++) { 1242 err = abs(count(n, d, p) - fq); 1243 if (err < minerr) { 1244 minerr = err; 1245 minn = n; 1246 mind = d; 1247 minp = p; 1248 } 1249 } 1250 if (d == 0x1f && p == 0) { 1251 p = 1; 1252 d = 0x0f; 1253 } 1254 } 1255 *clkdoub = 0; 1256 } 1257 1258 *num = minn; 1259 *denom = (mind << 1) | minp; 1260 if (minerr > 500000) 1261 printf("Warning: CompFQ minimum error = %ld\n", minerr); 1262 return; 1263 } 1264 1265 int 1266 cl_mondefok(struct grfvideo_mode *gv) 1267 { 1268 unsigned long maxpix; 1269 1270 if (gv->mode_num < 1 || gv->mode_num > monitor_def_max) 1271 if (gv->mode_num != 255 || gv->depth != 4) 1272 return(0); 1273 1274 switch (gv->depth) { 1275 case 4: 1276 if (gv->mode_num != 255) 1277 return(0); 1278 case 1: 1279 case 8: 1280 maxpix = cl_maxpixelclock; 1281 if (cl_64bit == 1) 1282 { 1283 if (cltype == PICASSO) /* Picasso IV */ 1284 maxpix = 135000000; 1285 else /* Piccolo SD64 */ 1286 maxpix = 110000000; 1287 } 1288 break; 1289 case 15: 1290 case 16: 1291 if (cl_64bit == 1) 1292 maxpix = 85000000; 1293 else 1294 maxpix = cl_maxpixelclock - (cl_maxpixelclock / 3); 1295 break; 1296 case 24: 1297 if ((cltype == PICASSO) && (cl_64bit == 1)) 1298 maxpix = 85000000; 1299 else 1300 maxpix = cl_maxpixelclock / 3; 1301 break; 1302 case 32: 1303 if ((cltype == PICCOLO) && (cl_64bit == 1)) 1304 maxpix = 50000000; 1305 else 1306 maxpix = 0; 1307 break; 1308 default: 1309 printf("grfcl: Illegal depth in mode %d\n", 1310 (int) gv->mode_num); 1311 return (0); 1312 } 1313 1314 if (gv->pixel_clock > maxpix) { 1315 printf("grfcl: Pixelclock too high in mode %d\n", 1316 (int) gv->mode_num); 1317 return (0); 1318 } 1319 1320 if (gv->disp_flags & GRF_FLAGS_SYNC_ON_GREEN) { 1321 printf("grfcl: sync-on-green is not supported\n"); 1322 return (0); 1323 } 1324 1325 return (1); 1326 } 1327 1328 int 1329 cl_load_mon(struct grf_softc *gp, struct grfcltext_mode *md) 1330 { 1331 struct grfvideo_mode *gv; 1332 struct grfinfo *gi; 1333 volatile void *ba, *fb; 1334 unsigned char num0, denom0, clkdoub; 1335 unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS, 1336 VSE, VT; 1337 int clkmul, offsmul, clkmode; 1338 int vmul; 1339 int sr15; 1340 unsigned char hvsync_pulse; 1341 char TEXT; 1342 1343 /* identity */ 1344 gv = &md->gv; 1345 TEXT = (gv->depth == 4); 1346 1347 if (!cl_mondefok(gv)) { 1348 printf("grfcl: Monitor definition not ok\n"); 1349 return (0); 1350 } 1351 1352 ba = gp->g_regkva; 1353 fb = gp->g_fbkva; 1354 1355 /* provide all needed information in grf device-independent locations */ 1356 gp->g_data = (void *) gv; 1357 gi = &gp->g_display; 1358 gi->gd_regaddr = (void *) kvtop(__UNVOLATILE(ba)); 1359 gi->gd_regsize = 64 * 1024; 1360 gi->gd_fbaddr = (void *) kvtop(__UNVOLATILE(fb)); 1361 gi->gd_fbsize = cl_fbsize; 1362 gi->gd_colors = 1 << gv->depth; 1363 gi->gd_planes = gv->depth; 1364 gi->gd_fbwidth = gv->disp_width; 1365 gi->gd_fbheight = gv->disp_height; 1366 gi->gd_fbx = 0; 1367 gi->gd_fby = 0; 1368 if (TEXT) { 1369 gi->gd_dwidth = md->fx * md->cols; 1370 gi->gd_dheight = md->fy * md->rows; 1371 } else { 1372 gi->gd_dwidth = gv->disp_width; 1373 gi->gd_dheight = gv->disp_height; 1374 } 1375 gi->gd_dx = 0; 1376 gi->gd_dy = 0; 1377 1378 /* get display mode parameters */ 1379 1380 HBS = gv->hblank_start; 1381 HSS = gv->hsync_start; 1382 HSE = gv->hsync_stop; 1383 HBE = gv->htotal - 1; 1384 HT = gv->htotal; 1385 VBS = gv->vblank_start; 1386 VSS = gv->vsync_start; 1387 VSE = gv->vsync_stop; 1388 VBE = gv->vtotal - 1; 1389 VT = gv->vtotal; 1390 1391 if (TEXT) 1392 HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1; 1393 else 1394 HDE = (gv->disp_width + 3) / 8 - 1; /* HBS; */ 1395 VDE = gv->disp_height - 1; 1396 1397 /* adjustments */ 1398 switch (gv->depth) { 1399 case 8: 1400 clkmul = 1; 1401 offsmul = 1; 1402 clkmode = 0x0; 1403 break; 1404 case 15: 1405 case 16: 1406 clkmul = 1; 1407 offsmul = 2; 1408 clkmode = 0x6; 1409 break; 1410 case 24: 1411 if ((cltype == PICASSO) && (cl_64bit == 1)) /* Picasso IV */ 1412 clkmul = 1; 1413 else 1414 clkmul = 3; 1415 offsmul = 3; 1416 clkmode = 0x4; 1417 break; 1418 case 32: 1419 clkmul = 1; 1420 offsmul = 2; 1421 clkmode = 0x8; 1422 break; 1423 default: 1424 clkmul = 1; 1425 offsmul = 1; 1426 clkmode = 0x0; 1427 break; 1428 } 1429 1430 if ((VT > 1023) && (!(gv->disp_flags & GRF_FLAGS_LACE))) { 1431 WCrt(ba, CRT_ID_MODE_CONTROL, 0xe7); 1432 } else 1433 WCrt(ba, CRT_ID_MODE_CONTROL, 0xe3); 1434 1435 vmul = 2; 1436 if ((VT > 1023) || (gv->disp_flags & GRF_FLAGS_LACE)) 1437 vmul = 1; 1438 if (gv->disp_flags & GRF_FLAGS_DBLSCAN) 1439 vmul = 4; 1440 1441 VDE = VDE * vmul / 2; 1442 VBS = VBS * vmul / 2; 1443 VSS = VSS * vmul / 2; 1444 VSE = VSE * vmul / 2; 1445 VBE = VBE * vmul / 2; 1446 VT = VT * vmul / 2; 1447 1448 WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e); 1449 if (cl_64bit == 1) { 1450 if (TEXT || (gv->depth == 1)) 1451 sr15 = 0xd0; 1452 else 1453 sr15 = ((cl_fbsize / 0x100000 == 2) ? 0x38 : 0xb8); 1454 WSeq(ba, SEQ_ID_CONF_RBACK, 0x00); 1455 } else { 1456 sr15 = (TEXT || (gv->depth == 1)) ? 0xd0 : 0xb0; 1457 sr15 &= ((cl_fbsize / 0x100000) == 2) ? 0xff : 0x7f; 1458 } 1459 WSeq(ba, SEQ_ID_DRAM_CNTL, sr15); 1460 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00); 1461 WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff); 1462 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); 1463 1464 /* Set clock */ 1465 1466 cl_CompFQ(gv->pixel_clock * clkmul, &num0, &denom0, &clkdoub); 1467 1468 /* Horizontal/Vertical Sync Pulse */ 1469 hvsync_pulse = vgar(ba, GREG_MISC_OUTPUT_R); 1470 if (gv->disp_flags & GRF_FLAGS_PHSYNC) 1471 hvsync_pulse &= ~0x40; 1472 else 1473 hvsync_pulse |= 0x40; 1474 if (gv->disp_flags & GRF_FLAGS_PVSYNC) 1475 hvsync_pulse &= ~0x80; 1476 else 1477 hvsync_pulse |= 0x80; 1478 vgaw(ba, GREG_MISC_OUTPUT_W, hvsync_pulse); 1479 1480 if (clkdoub) { 1481 HDE /= 2; 1482 HBS /= 2; 1483 HSS /= 2; 1484 HSE /= 2; 1485 HBE /= 2; 1486 HT /= 2; 1487 clkmode = 0x6; 1488 } 1489 1490 WSeq(ba, SEQ_ID_VCLK_3_NUM, num0); 1491 WSeq(ba, SEQ_ID_VCLK_3_DENOM, denom0); 1492 1493 /* load display parameters into board */ 1494 1495 WCrt(ba, CRT_ID_HOR_TOTAL, HT); 1496 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? HBS - 1 : HDE)); 1497 WCrt(ba, CRT_ID_START_HOR_BLANK, HBS); 1498 WCrt(ba, CRT_ID_END_HOR_BLANK, (HBE & 0x1f) | 0x80); /* | 0x80? */ 1499 WCrt(ba, CRT_ID_START_HOR_RETR, HSS); 1500 WCrt(ba, CRT_ID_END_HOR_RETR, 1501 (HSE & 0x1f) | 1502 ((HBE & 0x20) ? 0x80 : 0x00)); 1503 WCrt(ba, CRT_ID_VER_TOTAL, VT); 1504 WCrt(ba, CRT_ID_OVERFLOW, 1505 0x10 | 1506 ((VT & 0x100) ? 0x01 : 0x00) | 1507 ((VDE & 0x100) ? 0x02 : 0x00) | 1508 ((VSS & 0x100) ? 0x04 : 0x00) | 1509 ((VBS & 0x100) ? 0x08 : 0x00) | 1510 ((VT & 0x200) ? 0x20 : 0x00) | 1511 ((VDE & 0x200) ? 0x40 : 0x00) | 1512 ((VSS & 0x200) ? 0x80 : 0x00)); 1513 1514 WCrt(ba, CRT_ID_CHAR_HEIGHT, 1515 0x40 | /* TEXT ? 0x00 ??? */ 1516 ((gv->disp_flags & GRF_FLAGS_DBLSCAN) ? 0x80 : 0x00) | 1517 ((VBS & 0x200) ? 0x20 : 0x00) | 1518 (TEXT ? ((md->fy - 1) & 0x1f) : 0x00)); 1519 1520 /* text cursor */ 1521 1522 if (TEXT) { 1523 #if CL_ULCURSOR 1524 WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2); 1525 WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1); 1526 #else 1527 WCrt(ba, CRT_ID_CURSOR_START, 0x00); 1528 WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f); 1529 #endif 1530 WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->fy - 1) & 0x1f); 1531 1532 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00); 1533 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00); 1534 } 1535 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00); 1536 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00); 1537 1538 WCrt(ba, CRT_ID_START_VER_RETR, VSS); 1539 WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f) | 0x20); 1540 WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE); 1541 WCrt(ba, CRT_ID_START_VER_BLANK, VBS); 1542 WCrt(ba, CRT_ID_END_VER_BLANK, VBE); 1543 1544 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); 1545 WCrt(ba, CRT_ID_LACE_END, HT / 2); /* MW/16 */ 1546 WCrt(ba, CRT_ID_LACE_CNTL, 1547 ((gv->disp_flags & GRF_FLAGS_LACE) ? 0x01 : 0x00) | 1548 ((HBE & 0x40) ? 0x10 : 0x00) | 1549 ((HBE & 0x80) ? 0x20 : 0x00) | 1550 ((VBE & 0x100) ? 0x40 : 0x00) | 1551 ((VBE & 0x200) ? 0x80 : 0x00)); 1552 1553 WGfx(ba, GCT_ID_GRAPHICS_MODE, 1554 ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40)); 1555 WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01)); 1556 1557 WSeq(ba, SEQ_ID_EXT_SEQ_MODE, 1558 ((TEXT || (gv->depth == 1)) ? 0x00 : 0x01) | 1559 ((cltype == PICASSO) ? 0x20 : 0x80) | clkmode); 1560 1561 /* write 0x00 to VDAC_MASK before accessing HDR this helps 1562 sometimes, out of "secret" application note (crest) */ 1563 vgaw(ba, VDAC_MASK, 0); 1564 /* reset HDR "magic" access counter (crest) */ 1565 vgar(ba, VDAC_ADDRESS); 1566 1567 delay(200000); 1568 vgar(ba, VDAC_MASK); 1569 delay(200000); 1570 vgar(ba, VDAC_MASK); 1571 delay(200000); 1572 vgar(ba, VDAC_MASK); 1573 delay(200000); 1574 vgar(ba, VDAC_MASK); 1575 delay(200000); 1576 switch (gv->depth) { 1577 case 1: 1578 case 4: /* text */ 1579 vgaw(ba, VDAC_MASK, 0); 1580 HDE = gv->disp_width / 16; 1581 break; 1582 case 8: 1583 if (clkdoub) 1584 vgaw(ba, VDAC_MASK, 0x4a); /* Clockdouble Magic */ 1585 else 1586 vgaw(ba, VDAC_MASK, 0); 1587 HDE = gv->disp_width / 8; 1588 break; 1589 case 15: 1590 vgaw(ba, VDAC_MASK, 0xd0); 1591 HDE = gv->disp_width / 4; 1592 break; 1593 case 16: 1594 vgaw(ba, VDAC_MASK, 0xc1); 1595 HDE = gv->disp_width / 4; 1596 break; 1597 case 24: 1598 vgaw(ba, VDAC_MASK, 0xc5); 1599 HDE = (gv->disp_width / 8) * 3; 1600 break; 1601 case 32: 1602 vgaw(ba, VDAC_MASK, 0xc5); 1603 HDE = (gv->disp_width / 4); 1604 break; 1605 } 1606 1607 /* reset HDR "magic" access counter (crest) */ 1608 vgar(ba, VDAC_ADDRESS); 1609 /* then enable all bit in VDAC_MASK afterwards (crest) */ 1610 vgaw(ba, VDAC_MASK, 0xff); 1611 1612 WCrt(ba, CRT_ID_OFFSET, HDE); 1613 if (cl_64bit == 1) { 1614 WCrt(ba, CRT_ID_SYNC_ADJ_GENLOCK, 0x00); 1615 WCrt(ba, CRT_ID_OVERLAY_EXT_CTRL_REG, 0x40); 1616 } 1617 WCrt(ba, CRT_ID_EXT_DISP_CNTL, 1618 ((TEXT && gv->pixel_clock > 29000000) ? 0x40 : 0x00) | 1619 0x22 | 1620 ((HDE > 0xff) ? 0x10 : 0x00)); 1621 1622 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x0a : 0x01)); 1623 WAttr(ba, 0x20 | ACT_ID_COLOR_PLANE_ENA, 1624 (gv->depth == 1) ? 0x01 : 0x0f); 1625 1626 /* text initialization */ 1627 1628 if (TEXT) { 1629 cl_inittextmode(gp); 1630 } 1631 WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x14); 1632 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01); 1633 1634 /* Pass-through */ 1635 1636 RegOffpass(ba); 1637 1638 return (1); 1639 } 1640 1641 void 1642 cl_inittextmode(struct grf_softc *gp) 1643 { 1644 struct grfcltext_mode *tm = (struct grfcltext_mode *) gp->g_data; 1645 volatile unsigned char *ba = gp->g_regkva; 1646 unsigned char *fb = __UNVOLATILE(gp->g_fbkva); 1647 unsigned char *c, *f, y; 1648 unsigned short z; 1649 1650 1651 /* load text font into beginning of display memory. Each character 1652 * cell is 32 bytes long (enough for 4 planes) */ 1653 1654 SetTextPlane(ba, 0x02); 1655 cl_memset(fb, 0, 256 * 32); 1656 c = (unsigned char *) (fb) + (32 * tm->fdstart); 1657 f = tm->fdata; 1658 for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy)) 1659 for (y = 0; y < tm->fy; y++) 1660 *c++ = *f++; 1661 1662 /* clear out text/attr planes (three screens worth) */ 1663 1664 SetTextPlane(ba, 0x01); 1665 cl_memset(fb, 0x07, tm->cols * tm->rows * 3); 1666 SetTextPlane(ba, 0x00); 1667 cl_memset(fb, 0x20, tm->cols * tm->rows * 3); 1668 1669 /* print out a little init msg */ 1670 1671 c = (unsigned char *) (fb) + (tm->cols - 16); 1672 strcpy(c, "CIRRUS"); 1673 c[6] = 0x20; 1674 1675 /* set colors (B&W) */ 1676 1677 vgaw(ba, VDAC_ADDRESS_W, 0); 1678 for (z = 0; z < 256; z++) { 1679 unsigned char r, g, b; 1680 1681 y = (z & 1) ? ((z > 7) ? 2 : 1) : 0; 1682 1683 if (cltype == PICASSO) { 1684 r = clconscolors[y][0]; 1685 g = clconscolors[y][1]; 1686 b = clconscolors[y][2]; 1687 } else { 1688 b = clconscolors[y][0]; 1689 g = clconscolors[y][1]; 1690 r = clconscolors[y][2]; 1691 } 1692 vgaw(ba, VDAC_DATA, r >> 2); 1693 vgaw(ba, VDAC_DATA, g >> 2); 1694 vgaw(ba, VDAC_DATA, b >> 2); 1695 } 1696 } 1697 1698 void 1699 cl_memset(unsigned char *d, unsigned char c, int l) 1700 { 1701 for (; l > 0; l--) 1702 *d++ = c; 1703 } 1704 1705 /* 1706 * Special wakeup/passthrough registers on graphics boards 1707 * 1708 * The methods have diverged a bit for each board, so 1709 * WPass(P) has been converted into a set of specific 1710 * inline functions. 1711 */ 1712 static void 1713 RegWakeup(volatile void *ba) 1714 { 1715 1716 switch (cltype) { 1717 case SPECTRUM: 1718 vgaw(ba, PASS_ADDRESS_W, 0x1f); 1719 break; 1720 case PICASSO: 1721 /* Picasso needs no wakeup */ 1722 break; 1723 case PICCOLO: 1724 if (cl_64bit == 1) 1725 vgaw(ba, PASS_ADDRESS_W, 0x1f); 1726 else 1727 vgaw(ba, PASS_ADDRESS_W, vgar(ba, PASS_ADDRESS) | 0x10); 1728 break; 1729 } 1730 delay(200000); 1731 } 1732 1733 static void 1734 RegOnpass(volatile void *ba) 1735 { 1736 1737 switch (cltype) { 1738 case SPECTRUM: 1739 vgaw(ba, PASS_ADDRESS_W, 0x4f); 1740 break; 1741 case PICASSO: 1742 if (cl_64bit == 0) 1743 vgaw(ba, PASS_ADDRESS_WP, 0x01); 1744 break; 1745 case PICCOLO: 1746 if (cl_64bit == 1) 1747 vgaw(ba, PASS_ADDRESS_W, 0x4f); 1748 else 1749 vgaw(ba, PASS_ADDRESS_W, vgar(ba, PASS_ADDRESS) & 0xdf); 1750 break; 1751 } 1752 cl_pass_toggle = 1; 1753 delay(200000); 1754 } 1755 1756 static void 1757 RegOffpass(volatile void *ba) 1758 { 1759 1760 switch (cltype) { 1761 case SPECTRUM: 1762 vgaw(ba, PASS_ADDRESS_W, 0x6f); 1763 break; 1764 case PICASSO: 1765 if (cl_64bit == 0) 1766 vgaw(ba, PASS_ADDRESS_W, 0xff); 1767 break; 1768 case PICCOLO: 1769 if (cl_64bit == 1) 1770 vgaw(ba, PASS_ADDRESS_W, 0x6f); 1771 else 1772 vgaw(ba, PASS_ADDRESS_W, vgar(ba, PASS_ADDRESS) | 0x20); 1773 break; 1774 } 1775 cl_pass_toggle = 0; 1776 delay(200000); 1777 } 1778 1779 #endif /* NGRFCL */ 1780