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