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