1 /* $NetBSD: grf_et.c,v 1.9 1997/03/05 22:50:38 veego Exp $ */ 2 3 /* 4 * Copyright (c) 1997 Klaus Burkert 5 * Copyright (c) 1996 Tobias Abt 6 * Copyright (c) 1995 Ezra Story 7 * Copyright (c) 1995 Kari Mettinen 8 * Copyright (c) 1994 Markus Wild 9 * Copyright (c) 1994 Lutz Vieweg 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by Lutz Vieweg. 23 * 4. The name of the author may not be used to endorse or promote products 24 * derived from this software without specific prior written permission 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 */ 37 #include "grfet.h" 38 #if NGRFET > 0 39 40 /* 41 * Graphics routines for Tseng ET4000 (&W32) boards, 42 * 43 * This code offers low-level routines to access Tseng ET4000 44 * graphics-boards from within NetBSD for the Amiga. 45 * No warranties for any kind of function at all - this 46 * code may crash your hardware and scratch your harddisk. Use at your 47 * own risk. Freely distributable. 48 * 49 * Modified for Tseng ET4000 from 50 * Kari Mettinen's Cirrus driver by Tobias Abt 51 * 52 * Fixed Merlin in Z-III, fixed LACE and DBLSCAN, added Domino16M proto 53 * and AT&T ATT20c491 DAC, added memory-size detection by Klaus Burkert. 54 * 55 * 56 * TODO: 57 * 58 */ 59 60 #include <sys/param.h> 61 #include <sys/systm.h> 62 #include <sys/errno.h> 63 #include <sys/ioctl.h> 64 #include <sys/device.h> 65 #include <sys/malloc.h> 66 67 #include <machine/cpu.h> 68 #include <dev/cons.h> 69 #ifdef TSENGCONSOLE 70 #include <amiga/dev/itevar.h> 71 #endif 72 #include <amiga/amiga/device.h> 73 #include <amiga/dev/grfioctl.h> 74 #include <amiga/dev/grfvar.h> 75 #include <amiga/dev/grf_etreg.h> 76 #include <amiga/dev/zbusvar.h> 77 78 int et_mondefok __P((struct grfvideo_mode *gv)); 79 void et_boardinit __P((struct grf_softc *gp)); 80 static void et_CompFQ __P((u_int fq, u_char *num, u_char *denom)); 81 int et_getvmode __P((struct grf_softc *gp, struct grfvideo_mode *vm)); 82 int et_setvmode __P((struct grf_softc *gp, unsigned int mode)); 83 int et_toggle __P((struct grf_softc *gp, unsigned short)); 84 int et_getcmap __P((struct grf_softc *gfp, struct grf_colormap *cmap)); 85 int et_putcmap __P((struct grf_softc *gfp, struct grf_colormap *cmap)); 86 #ifndef TSENGCONSOLE 87 void et_off __P((struct grf_softc *gp)); 88 #endif 89 void et_inittextmode __P((struct grf_softc *gp)); 90 int et_ioctl __P((register struct grf_softc *gp, u_long cmd, void *data)); 91 int et_getmousepos __P((struct grf_softc *gp, struct grf_position *data)); 92 void et_writesprpos __P((volatile char *ba, short x, short y)); 93 int et_setmousepos __P((struct grf_softc *gp, struct grf_position *data)); 94 static int et_setspriteinfo __P((struct grf_softc *gp, 95 struct grf_spriteinfo *data)); 96 int et_getspriteinfo __P((struct grf_softc *gp, 97 struct grf_spriteinfo *data)); 98 static int et_getspritemax __P((struct grf_softc *gp, 99 struct grf_position *data)); 100 int et_setmonitor __P((struct grf_softc *gp, struct grfvideo_mode *gv)); 101 int et_blank __P((struct grf_softc *gp, int *on)); 102 static int et_getControllerType __P((struct grf_softc *gp)); 103 static int et_getDACType __P((struct grf_softc *gp)); 104 105 int grfetmatch __P((struct device *, struct cfdata *, void *)); 106 void grfetattach __P((struct device *, struct device *, void *)); 107 int grfetprint __P((void *, const char *)); 108 void et_memset __P((unsigned char *d, unsigned char c, int l)); 109 110 /* 111 * Graphics display definitions. 112 * These are filled by 'grfconfig' using GRFIOCSETMON. 113 */ 114 #define monitor_def_max 8 115 static struct grfvideo_mode monitor_def[8] = { 116 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0} 117 }; 118 static struct grfvideo_mode *monitor_current = &monitor_def[0]; 119 120 /* Console display definition. 121 * Default hardcoded text mode. This grf_et 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 TSENGFONT kernel_font_8x11 128 #define TSENGFONTY 11 129 #else 130 #define TSENGFONT kernel_font_8x8 131 #define TSENGFONTY 8 132 #endif 133 extern unsigned char TSENGFONT[]; 134 135 struct grfettext_mode etconsole_mode = { 136 {255, "", 25000000, 640, 480, 4, 640/8, 784/8, 680/8, 768/8, 800/8, 137 481, 521, 491, 493, 525}, 138 8, TSENGFONTY, 640 / 8, 480 / TSENGFONTY, TSENGFONT, 32, 255 139 }; 140 141 /* Console colors */ 142 unsigned char etconscolors[3][3] = { /* background, foreground, hilite */ 143 {0, 0x40, 0x50}, {152, 152, 152}, {255, 255, 255} 144 }; 145 146 int ettype = 0; /* oMniBus, Domino or Merlin */ 147 int etctype = 0; /* ET4000 or ETW32 */ 148 int etdtype = 0; /* Type of DAC (see grf_etregs.h) */ 149 150 char etcmap_shift = 0; /* 6 or 8 bit cmap entries */ 151 unsigned char pass_toggle; /* passthru status tracker */ 152 153 unsigned char Merlin_switch = 0; 154 155 /* 156 * Because all Tseng-boards have 2 configdev entries, one for 157 * framebuffer mem and the other for regs, we have to hold onto 158 * the pointers globally until we match on both. This and 'ettype' 159 * are the primary obsticles to multiple board support, but if you 160 * have multiple boards you have bigger problems than grf_et. 161 */ 162 static void *et_fbaddr = 0; /* framebuffer */ 163 static void *et_regaddr = 0; /* registers */ 164 static int et_fbsize; /* framebuffer size */ 165 166 /* current sprite info, if you add support for multiple boards 167 * make this an array or something 168 */ 169 struct grf_spriteinfo et_cursprite; 170 171 /* sprite bitmaps in kernel stack, you'll need to arrayize these too if 172 * you add multiple board support 173 */ 174 static unsigned char et_imageptr[8 * 64], et_maskptr[8 * 64]; 175 static unsigned char et_sprred[2], et_sprgreen[2], et_sprblue[2]; 176 177 /* standard driver stuff */ 178 struct cfattach grfet_ca = { 179 sizeof(struct grf_softc), grfetmatch, grfetattach 180 }; 181 182 struct cfdriver grfet_cd = { 183 NULL, "grfet", DV_DULL, NULL, 0 184 }; 185 186 static struct cfdata *cfdata; 187 188 int 189 grfetmatch(pdp, cfp, auxp) 190 struct device *pdp; 191 struct cfdata *cfp; 192 void *auxp; 193 { 194 struct zbus_args *zap; 195 static int regprod, regprod2 = 0, fbprod; 196 197 zap = auxp; 198 199 #ifndef TSENGCONSOLE 200 if (amiga_realconfig == 0) 201 return (0); 202 #endif 203 204 /* Grab the first board we encounter as the preferred one. This will 205 * allow one board to work in a multiple Tseng board system, but not 206 * multiple boards at the same time. */ 207 if (ettype == 0) { 208 switch (zap->manid) { 209 case OMNIBUS: 210 if (zap->prodid != 0) 211 return (0); 212 regprod = 0; 213 fbprod = 0; 214 break; 215 case DOMINO: 216 /* 2167/3 is Domino16M proto (crest) */ 217 if (zap->prodid != 3 && zap->prodid != 2 && zap->prodid != 1) 218 return (0); 219 regprod = 2; 220 regprod2 = 3; 221 fbprod = 1; 222 break; 223 case MERLIN: 224 if (zap->prodid != 3 && zap->prodid != 4) 225 return (0); 226 regprod = 4; 227 fbprod = 3; 228 break; 229 default: 230 return (0); 231 } 232 ettype = zap->manid; 233 } else { 234 if (ettype != zap->manid) { 235 return (0); 236 } 237 } 238 239 /* Configure either registers or framebuffer in any order */ 240 /* as said before, oMniBus does not support ProdID */ 241 if (ettype == OMNIBUS) { 242 if (zap->size == 64 * 1024) { 243 /* register area */ 244 et_regaddr = zap->va; 245 } else { 246 /* memory area */ 247 et_fbaddr = zap->va; 248 et_fbsize = zap->size; 249 } 250 } else { 251 if (zap->prodid == regprod || zap->prodid == regprod2) { 252 et_regaddr = zap->va; 253 } else { 254 if (zap->prodid == fbprod) { 255 et_fbaddr = zap->va; 256 et_fbsize = zap->size; 257 } else { 258 return (0); 259 } 260 } 261 } 262 263 #ifdef TSENGCONSOLE 264 if (amiga_realconfig == 0) { 265 cfdata = cfp; 266 } 267 #endif 268 269 return (1); 270 } 271 272 273 void 274 grfetattach(pdp, dp, auxp) 275 struct device *pdp, *dp; 276 void *auxp; 277 { 278 static struct grf_softc congrf; 279 struct zbus_args *zap; 280 struct grf_softc *gp; 281 static char attachflag = 0; 282 283 zap = auxp; 284 285 printf("\n"); 286 287 /* make sure both halves have matched */ 288 if (!et_regaddr || !et_fbaddr) 289 return; 290 291 /* do all that messy console/grf stuff */ 292 if (dp == NULL) 293 gp = &congrf; 294 else 295 gp = (struct grf_softc *) dp; 296 297 if (dp != NULL && congrf.g_regkva != 0) { 298 /* 299 * inited earlier, just copy (not device struct) 300 */ 301 bcopy(&congrf.g_display, &gp->g_display, 302 (char *) &gp[1] - (char *) &gp->g_display); 303 } else { 304 gp->g_regkva = (volatile caddr_t) et_regaddr; 305 gp->g_fbkva = (volatile caddr_t) et_fbaddr; 306 307 gp->g_unit = GRF_ET4000_UNIT; 308 gp->g_mode = et_mode; 309 gp->g_conpri = grfet_cnprobe(); 310 gp->g_flags = GF_ALIVE; 311 312 /* wakeup the board */ 313 et_boardinit(gp); 314 315 #ifdef TSENGCONSOLE 316 grfet_iteinit(gp); 317 (void) et_load_mon(gp, &etconsole_mode); 318 #endif 319 } 320 321 /* 322 * attach grf (once) 323 */ 324 if (amiga_config_found(cfdata, &gp->g_device, gp, grfetprint)) { 325 attachflag = 1; 326 printf("grfet: %dMB ", et_fbsize / 0x100000); 327 switch (ettype) { 328 case OMNIBUS: 329 printf("oMniBus"); 330 break; 331 case DOMINO: 332 printf("Domino"); 333 break; 334 case MERLIN: 335 printf("Merlin"); 336 break; 337 } 338 printf(" with "); 339 switch (etctype) { 340 case ET4000: 341 printf("Tseng ET4000"); 342 break; 343 case ETW32: 344 printf("Tseng ETW32"); 345 break; 346 } 347 printf(" and "); 348 switch (etdtype) { 349 case SIERRA11483: 350 printf("Sierra SC11483 DAC"); 351 break; 352 case SIERRA15025: 353 printf("Sierra SC15025 DAC"); 354 break; 355 case MUSICDAC: 356 printf("MUSIC DAC"); 357 break; 358 case MERLINDAC: 359 printf("BrookTree Bt482 DAC"); 360 break; 361 case ATT20C491: 362 printf("AT&T ATT20c491 DAC"); 363 break; 364 } 365 printf(" being used\n"); 366 } else { 367 if (!attachflag) 368 printf("grfet unattached!!\n"); 369 } 370 } 371 372 373 int 374 grfetprint(auxp, pnp) 375 void *auxp; 376 const char *pnp; 377 { 378 if (pnp) 379 printf("ite at %s: ", pnp); 380 return (UNCONF); 381 } 382 383 384 void 385 et_boardinit(gp) 386 struct grf_softc *gp; 387 { 388 unsigned char *ba = gp->g_regkva; 389 int x; 390 391 /* wakeup board and flip passthru OFF */ 392 393 RegWakeup(ba); 394 RegOnpass(ba); 395 396 if (ettype == MERLIN) { 397 /* Merlin needs some special initialisations */ 398 vgaw(ba, MERLIN_SWITCH_REG, 0); 399 delay(20000); 400 vgaw(ba, MERLIN_SWITCH_REG, 8); 401 delay(20000); 402 vgaw(ba, MERLIN_SWITCH_REG, 0); 403 delay(20000); 404 vgaw(ba, MERLIN_VDAC_DATA, 1); 405 406 vgaw(ba, MERLIN_VDAC_INDEX, 0x00); 407 vgaw(ba, MERLIN_VDAC_SPRITE, 0xff); 408 vgaw(ba, MERLIN_VDAC_INDEX, 0x01); 409 vgaw(ba, MERLIN_VDAC_SPRITE, 0x0f); 410 vgaw(ba, MERLIN_VDAC_INDEX, 0x02); 411 vgaw(ba, MERLIN_VDAC_SPRITE, 0x42); 412 vgaw(ba, MERLIN_VDAC_INDEX, 0x03); 413 vgaw(ba, MERLIN_VDAC_SPRITE, 0x00); 414 415 vgaw(ba, MERLIN_VDAC_DATA, 0); 416 } 417 418 419 /* setup initial unchanging parameters */ 420 421 vgaw(ba, GREG_HERCULESCOMPAT + ((ettype == DOMINO) ? 0x0fff : 0), 0x03); 422 vgaw(ba, GREG_DISPMODECONTROL, 0xa0); 423 vgaw(ba, GREG_MISC_OUTPUT_W, 0x63); 424 425 if (ettype == DOMINO) 426 { 427 vgaw(ba, CRT_ADDRESS, CRT_ID_VIDEO_CONFIG1); 428 vgaw(ba, CRT_ADDRESS_W + 0x0fff, 429 0xc0 | vgar(ba, CRT_ADDRESS_R + 0x0fff)); 430 } 431 432 WSeq(ba, SEQ_ID_RESET, 0x03); 433 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21); /* 8 dot, Display off */ 434 WSeq(ba, SEQ_ID_MAP_MASK, 0x0f); 435 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); 436 WSeq(ba, SEQ_ID_MEMORY_MODE, 0x0e); 437 WSeq(ba, SEQ_ID_STATE_CONTROL, 0x00); 438 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf4); 439 440 WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00); 441 WCrt(ba, CRT_ID_CURSOR_START, 0x00); 442 WCrt(ba, CRT_ID_CURSOR_END, 0x08); 443 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00); 444 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00); 445 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00); 446 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00); 447 448 WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x67); 449 WCrt(ba, CRT_ID_MODE_CONTROL, 0xc3); 450 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); 451 452 /* ET4000 special */ 453 WCrt(ba, CRT_ID_RASCAS_CONFIG, 0x28); 454 WCrt(ba, CRT_ID_EXT_START, 0x00); 455 WCrt(ba, CRT_ID_6845_COMPAT, 0x08); 456 457 /* ET4000/W32 special (currently only for Merlin (crest) */ 458 if (ettype == MERLIN) { 459 WCrt(ba, CRT_ID_SEGMENT_COMP, 0x1c); 460 WCrt(ba, CRT_ID_GENERAL_PURPOSE, 0x00); 461 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0x93); 462 } 463 else { 464 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xd3); 465 } 466 467 WCrt(ba, CRT_ID_VIDEO_CONFIG2, 0x0f); 468 WCrt(ba, CRT_ID_HOR_OVERFLOW, 0x00); 469 470 vgaw(ba, GREG_SEGMENTSELECT, 0x00); 471 472 WGfx(ba, GCT_ID_SET_RESET, 0x00); 473 WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00); 474 WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00); 475 WGfx(ba, GCT_ID_DATA_ROTATE, 0x00); 476 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00); 477 WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x40); 478 WGfx(ba, GCT_ID_MISC, 0x01); 479 WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f); 480 WGfx(ba, GCT_ID_BITMASK, 0xff); 481 482 for (x = 0; x < 0x10; x++) 483 WAttr(ba, x, x); 484 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x01); 485 WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00); 486 WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f); 487 WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00); 488 WAttr(ba, ACT_ID_COLOR_SELECT, 0x00); 489 WAttr(ba, ACT_ID_MISCELLANEOUS, 0x00); 490 491 vgaw(ba, VDAC_MASK, 0xff); 492 delay(200000); 493 vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3); 494 495 /* colors initially set to greyscale */ 496 switch(ettype) { 497 case MERLIN: 498 vgaw(ba, MERLIN_VDAC_INDEX, 0); 499 for (x = 255; x >= 0; x--) { 500 vgaw(ba, MERLIN_VDAC_COLORS, x); 501 vgaw(ba, MERLIN_VDAC_COLORS, x); 502 vgaw(ba, MERLIN_VDAC_COLORS, x); 503 } 504 break; 505 default: 506 vgaw(ba, VDAC_ADDRESS_W, 0); 507 for (x = 255; x >= 0; x--) { 508 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), x); 509 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), x); 510 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), x); 511 } 512 break; 513 } 514 /* set sprite bitmap pointers */ 515 /* should work like that */ 516 et_cursprite.image = et_imageptr; 517 et_cursprite.mask = et_maskptr; 518 et_cursprite.cmap.red = et_sprred; 519 et_cursprite.cmap.green = et_sprgreen; 520 et_cursprite.cmap.blue = et_sprblue; 521 522 /* card specific initialisations */ 523 switch(ettype) { 524 case OMNIBUS: 525 etctype = et_getControllerType(gp); 526 etdtype = et_getDACType(gp); 527 break; 528 case MERLIN: 529 vgaw(ba, GREG_SEGMENTSELECT2, 0x00); 530 if (((vgar(ba, GREG_FEATURE_CONTROL_R) & 12) | 531 (vgar(ba, GREG_STATUS0_R) & 0x60)) == 0x24) { 532 WCrt(ba, CRT_ID_VIDEO_CONFIG2, 0x07); /* 1Mx4 RAM */ 533 et_fbsize = 0x400000; /* 4 MB */ 534 } 535 else { 536 /* check for 1MB or 2MB board (crest) */ 537 /* has there a 1MB Merlin ever been sold ??? */ 538 volatile unsigned long *et_fbtestaddr; 539 et_fbtestaddr = (volatile unsigned long *)gp->g_fbkva; 540 *et_fbtestaddr = 0x0; 541 vgaw(ba, GREG_SEGMENTSELECT2, 0x11); /* 1MB offset */ 542 *et_fbtestaddr = 0x12345678; 543 vgaw(ba, GREG_SEGMENTSELECT2, 0x00); 544 if (*et_fbtestaddr == 0x0) 545 et_fbsize = 0x200000; /* 2 MB */ 546 else 547 et_fbsize = 0x100000; /* 1 MB */ 548 } 549 /* ZorroII can map 2 MB max ... */ 550 if (!iszthreepa(gp->g_fbkva) && et_fbsize == 0x400000) 551 et_fbsize = 0x200000; 552 etctype = ETW32; 553 etdtype = MERLINDAC; 554 break; 555 case DOMINO: 556 etctype = ET4000; 557 etdtype = et_getDACType(gp); 558 break; 559 } 560 } 561 562 563 int 564 et_getvmode(gp, vm) 565 struct grf_softc *gp; 566 struct grfvideo_mode *vm; 567 { 568 struct grfvideo_mode *gv; 569 570 #ifdef TSENGCONSOLE 571 /* Handle grabbing console mode */ 572 if (vm->mode_num == 255) { 573 bcopy(&etconsole_mode, vm, sizeof(struct grfvideo_mode)); 574 /* XXX so grfconfig can tell us the correct text dimensions. */ 575 vm->depth = etconsole_mode.fy; 576 } else 577 #endif 578 { 579 if (vm->mode_num == 0) 580 vm->mode_num = (monitor_current - monitor_def) + 1; 581 if (vm->mode_num < 1 || vm->mode_num > monitor_def_max) 582 return (EINVAL); 583 gv = monitor_def + (vm->mode_num - 1); 584 if (gv->mode_num == 0) 585 return (EINVAL); 586 587 bcopy(gv, vm, sizeof(struct grfvideo_mode)); 588 } 589 590 /* adjust internal values to pixel values */ 591 592 vm->hblank_start *= 8; 593 vm->hblank_stop *= 8; 594 vm->hsync_start *= 8; 595 vm->hsync_stop *= 8; 596 vm->htotal *= 8; 597 598 return (0); 599 } 600 601 602 int 603 et_setvmode(gp, mode) 604 struct grf_softc *gp; 605 unsigned mode; 606 { 607 if (!mode || (mode > monitor_def_max) || 608 monitor_def[mode - 1].mode_num == 0) 609 return (EINVAL); 610 611 monitor_current = monitor_def + (mode - 1); 612 613 return (0); 614 } 615 616 617 #ifndef TSENGCONSOLE 618 void 619 et_off(gp) 620 struct grf_softc *gp; 621 { 622 char *ba = gp->g_regkva; 623 624 RegOnpass(ba); 625 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21); 626 } 627 #endif 628 629 630 int 631 et_blank(gp, on) 632 struct grf_softc *gp; 633 int *on; 634 { 635 WSeq(gp->g_regkva, SEQ_ID_CLOCKING_MODE, *on > 0 ? 0x01 : 0x21); 636 return(0); 637 } 638 639 640 /* 641 * Change the mode of the display. 642 * Return a UNIX error number or 0 for success. 643 */ 644 int 645 et_mode(gp, cmd, arg, a2, a3) 646 register struct grf_softc *gp; 647 u_long cmd; 648 void *arg; 649 u_long a2; 650 int a3; 651 { 652 int error; 653 654 switch (cmd) { 655 case GM_GRFON: 656 error = et_load_mon(gp, 657 (struct grfettext_mode *) monitor_current) ? 0 : EINVAL; 658 return (error); 659 660 case GM_GRFOFF: 661 #ifndef TSENGCONSOLE 662 et_off(gp); 663 #else 664 et_load_mon(gp, &etconsole_mode); 665 #endif 666 return (0); 667 668 case GM_GRFCONFIG: 669 return (0); 670 671 case GM_GRFGETVMODE: 672 return (et_getvmode(gp, (struct grfvideo_mode *) arg)); 673 674 case GM_GRFSETVMODE: 675 error = et_setvmode(gp, *(unsigned *) arg); 676 if (!error && (gp->g_flags & GF_GRFON)) 677 et_load_mon(gp, 678 (struct grfettext_mode *) monitor_current); 679 return (error); 680 681 case GM_GRFGETNUMVM: 682 *(int *) arg = monitor_def_max; 683 return (0); 684 685 case GM_GRFIOCTL: 686 return (et_ioctl(gp, a2, arg)); 687 688 default: 689 break; 690 } 691 692 return (EINVAL); 693 } 694 695 696 int 697 et_ioctl(gp, cmd, data) 698 register struct grf_softc *gp; 699 u_long cmd; 700 void *data; 701 { 702 switch (cmd) { 703 case GRFIOCGSPRITEPOS: 704 return (et_getmousepos(gp, (struct grf_position *) data)); 705 706 case GRFIOCSSPRITEPOS: 707 return (et_setmousepos(gp, (struct grf_position *) data)); 708 709 case GRFIOCSSPRITEINF: 710 return (et_setspriteinfo(gp, (struct grf_spriteinfo *) data)); 711 712 case GRFIOCGSPRITEINF: 713 return (et_getspriteinfo(gp, (struct grf_spriteinfo *) data)); 714 715 case GRFIOCGSPRITEMAX: 716 return (et_getspritemax(gp, (struct grf_position *) data)); 717 718 case GRFIOCGETCMAP: 719 return (et_getcmap(gp, (struct grf_colormap *) data)); 720 721 case GRFIOCPUTCMAP: 722 return (et_putcmap(gp, (struct grf_colormap *) data)); 723 724 case GRFIOCBITBLT: 725 break; 726 727 case GRFTOGGLE: 728 return (et_toggle(gp, 0)); 729 730 case GRFIOCSETMON: 731 return (et_setmonitor(gp, (struct grfvideo_mode *) data)); 732 733 case GRFIOCBLANK: 734 return (et_blank(gp, (int *)data)); 735 } 736 return (EINVAL); 737 } 738 739 740 int 741 et_getmousepos(gp, data) 742 struct grf_softc *gp; 743 struct grf_position *data; 744 { 745 data->x = et_cursprite.pos.x; 746 data->y = et_cursprite.pos.y; 747 748 return (0); 749 } 750 751 752 void 753 et_writesprpos(ba, x, y) 754 volatile char *ba; 755 short x; 756 short y; 757 { 758 } 759 760 761 int 762 et_setmousepos(gp, data) 763 struct grf_softc *gp; 764 struct grf_position *data; 765 { 766 volatile char *ba = gp->g_regkva; 767 short rx, ry, prx, pry; 768 769 /* no movement */ 770 if (et_cursprite.pos.x == data->x && et_cursprite.pos.y == data->y) 771 return (0); 772 773 /* current and previous real coordinates */ 774 rx = data->x - et_cursprite.hot.x; 775 ry = data->y - et_cursprite.hot.y; 776 prx = et_cursprite.pos.x - et_cursprite.hot.x; 777 pry = et_cursprite.pos.y - et_cursprite.hot.y; 778 779 /* if we are/were on an edge, create (un)shifted bitmap -- 780 * ripped out optimization (not extremely worthwhile, 781 * and kind of buggy anyhow). 782 */ 783 784 /* do movement, save position */ 785 et_writesprpos(ba, rx < 0 ? 0 : rx, ry < 0 ? 0 : ry); 786 et_cursprite.pos.x = data->x; 787 et_cursprite.pos.y = data->y; 788 789 return (0); 790 } 791 792 793 int 794 et_getspriteinfo(gp, data) 795 struct grf_softc *gp; 796 struct grf_spriteinfo *data; 797 { 798 799 return(EINVAL); 800 } 801 802 803 static int 804 et_setspriteinfo(gp, data) 805 struct grf_softc *gp; 806 struct grf_spriteinfo *data; 807 { 808 809 return(EINVAL); 810 } 811 812 813 static int 814 et_getspritemax(gp, data) 815 struct grf_softc *gp; 816 struct grf_position *data; 817 { 818 819 return(EINVAL); 820 } 821 822 823 int 824 et_setmonitor(gp, gv) 825 struct grf_softc *gp; 826 struct grfvideo_mode *gv; 827 { 828 struct grfvideo_mode *md; 829 830 if (!et_mondefok(gv)) 831 return(EINVAL); 832 833 #ifdef TSENGCONSOLE 834 /* handle interactive setting of console mode */ 835 if (gv->mode_num == 255) { 836 bcopy(gv, &etconsole_mode.gv, sizeof(struct grfvideo_mode)); 837 etconsole_mode.gv.hblank_start /= 8; 838 etconsole_mode.gv.hblank_stop /= 8; 839 etconsole_mode.gv.hsync_start /= 8; 840 etconsole_mode.gv.hsync_stop /= 8; 841 etconsole_mode.gv.htotal /= 8; 842 etconsole_mode.rows = gv->disp_height / etconsole_mode.fy; 843 etconsole_mode.cols = gv->disp_width / etconsole_mode.fx; 844 if (!(gp->g_flags & GF_GRFON)) 845 et_load_mon(gp, &etconsole_mode); 846 ite_reinit(gp->g_itedev); 847 return (0); 848 } 849 #endif 850 851 md = monitor_def + (gv->mode_num - 1); 852 bcopy(gv, md, sizeof(struct grfvideo_mode)); 853 854 /* adjust pixel oriented values to internal rep. */ 855 856 md->hblank_start /= 8; 857 md->hblank_stop /= 8; 858 md->hsync_start /= 8; 859 md->hsync_stop /= 8; 860 md->htotal /= 8; 861 862 return (0); 863 } 864 865 866 int 867 et_getcmap(gfp, cmap) 868 struct grf_softc *gfp; 869 struct grf_colormap *cmap; 870 { 871 volatile unsigned char *ba; 872 u_char red[256], green[256], blue[256], *rp, *gp, *bp; 873 short x; 874 int error; 875 876 if (cmap->count == 0 || cmap->index >= 256) 877 return 0; 878 879 if (cmap->index + cmap->count > 256) 880 cmap->count = 256 - cmap->index; 881 882 ba = gfp->g_regkva; 883 /* first read colors out of the chip, then copyout to userspace */ 884 x = cmap->count - 1; 885 886 rp = red + cmap->index; 887 gp = green + cmap->index; 888 bp = blue + cmap->index; 889 890 switch(ettype) { 891 case MERLIN: 892 vgaw(ba, MERLIN_VDAC_INDEX, cmap->index); 893 do { 894 *rp++ = vgar(ba, MERLIN_VDAC_COLORS); 895 *gp++ = vgar(ba, MERLIN_VDAC_COLORS); 896 *bp++ = vgar(ba, MERLIN_VDAC_COLORS); 897 } while (x-- > 0); 898 break; 899 default: 900 vgaw(ba, VDAC_ADDRESS_R+((ettype==DOMINO)?0x0fff:0), cmap->index); 901 do { 902 *rp++ = vgar(ba, VDAC_DATA+((ettype==DOMINO)?0x0fff:0)) << etcmap_shift; 903 *gp++ = vgar(ba, VDAC_DATA+((ettype==DOMINO)?0x0fff:0)) << etcmap_shift; 904 *bp++ = vgar(ba, VDAC_DATA+((ettype==DOMINO)?0x0fff:0)) << etcmap_shift; 905 } while (x-- > 0); 906 break; 907 } 908 909 error = copyout(red + cmap->index, cmap->red, cmap->count); 910 if (!error) 911 error = copyout(green + cmap->index, cmap->green, cmap->count); 912 if (!error) 913 error = copyout(blue + cmap->index, cmap->blue, cmap->count); 914 915 return (error); 916 } 917 918 919 int 920 et_putcmap(gfp, cmap) 921 struct grf_softc *gfp; 922 struct grf_colormap *cmap; 923 { 924 volatile unsigned char *ba; 925 u_char red[256], green[256], blue[256], *rp, *gp, *bp; 926 short x; 927 int error; 928 929 if (cmap->count == 0 || cmap->index >= 256) 930 return (0); 931 932 if (cmap->index + cmap->count > 256) 933 cmap->count = 256 - cmap->index; 934 935 /* first copy the colors into kernelspace */ 936 if ((error = copyin(cmap->red, red + cmap->index, cmap->count))) 937 return (error); 938 939 if ((error = copyin(cmap->green, green + cmap->index, cmap->count))) 940 return (error); 941 942 if ((error = copyin(cmap->blue, blue + cmap->index, cmap->count))) 943 return (error); 944 945 ba = gfp->g_regkva; 946 x = cmap->count - 1; 947 948 rp = red + cmap->index; 949 gp = green + cmap->index; 950 bp = blue + cmap->index; 951 952 switch(ettype){ 953 case MERLIN: 954 vgaw(ba, MERLIN_VDAC_INDEX, cmap->index); 955 do { 956 vgaw(ba, MERLIN_VDAC_COLORS, *rp++); 957 vgaw(ba, MERLIN_VDAC_COLORS, *gp++); 958 vgaw(ba, MERLIN_VDAC_COLORS, *bp++); 959 } while (x-- > 0); 960 break; 961 default: 962 vgaw(ba, VDAC_ADDRESS_W, cmap->index); 963 do { 964 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), 965 *rp++ >> etcmap_shift); 966 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), 967 *gp++ >> etcmap_shift); 968 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), 969 *bp++ >> etcmap_shift); 970 } while (x-- > 0); 971 break; 972 } 973 974 return (0); 975 } 976 977 978 int 979 et_toggle(gp, wopp) 980 struct grf_softc *gp; 981 unsigned short wopp; /* don't need that one yet, ill */ 982 { 983 volatile unsigned char *ba; 984 985 ba = gp->g_regkva; 986 987 if (pass_toggle) { 988 RegOffpass(ba); 989 } else { 990 RegOnpass(ba); 991 } 992 return (0); 993 } 994 995 996 #define ET_NUMCLOCKS 32 997 998 static u_char et_clocks[ET_NUMCLOCKS] = { 999 0, 1, 6, 2, 3, 7, 4, 5, 1000 0, 1, 6, 2, 3, 7, 4, 5, 1001 0, 1, 6, 2, 3, 7, 4, 5, 1002 0, 1, 6, 2, 3, 7, 4, 5 1003 }; 1004 1005 static u_char et_clockdividers[ET_NUMCLOCKS] = { 1006 3, 3, 3, 3, 3, 3, 3, 3, 1007 2, 2, 2, 2, 2, 2, 2, 2, 1008 1, 1, 1, 1, 1, 1, 1, 1, 1009 0, 0, 0, 0, 0, 0, 0, 0 1010 }; 1011 1012 static u_int et_clockfreqs[ET_NUMCLOCKS] = { 1013 6293750, 7080500, 7875000, 8125000, 1014 9000000, 9375000, 10000000, 11225000, 1015 12587500, 14161000, 15750000, 16250000, 1016 18000000, 18750000, 20000000, 22450000, 1017 25175000, 28322000, 31500000, 32500000, 1018 36000000, 37500000, 40000000, 44900000, 1019 50350000, 56644000, 63000000, 65000000, 1020 72000000, 75000000, 80000000, 89800000 1021 }; 1022 1023 1024 static void 1025 et_CompFQ(fq, num, denom) 1026 u_int fq; 1027 u_char *num; 1028 u_char *denom; 1029 { 1030 int i; 1031 1032 for (i=0; i < ET_NUMCLOCKS;) { 1033 if (fq <= et_clockfreqs[i++]) { 1034 break; 1035 } 1036 } 1037 1038 *num = et_clocks[--i]; 1039 *denom = et_clockdividers[i]; 1040 1041 return; 1042 } 1043 1044 1045 int 1046 et_mondefok(gv) 1047 struct grfvideo_mode *gv; 1048 { 1049 unsigned long maxpix; 1050 1051 if (gv->mode_num < 1 || gv->mode_num > monitor_def_max) 1052 if (gv->mode_num != 255 || gv->depth != 4) 1053 return(0); 1054 1055 switch (gv->depth) { 1056 case 4: 1057 if (gv->mode_num != 255) 1058 return(0); 1059 case 1: 1060 case 8: 1061 maxpix = 85000000; 1062 break; 1063 case 15: 1064 case 16: 1065 maxpix = 45000000; 1066 break; 1067 case 24: 1068 maxpix = 28000000; 1069 break; 1070 case 32: 1071 maxpix = 21000000; 1072 break; 1073 default: 1074 return (0); 1075 } 1076 if (gv->pixel_clock > maxpix) 1077 return (0); 1078 return (1); 1079 } 1080 1081 1082 int 1083 et_load_mon(gp, md) 1084 struct grf_softc *gp; 1085 struct grfettext_mode *md; 1086 { 1087 struct grfvideo_mode *gv; 1088 struct grfinfo *gi; 1089 volatile unsigned char *ba; 1090 unsigned char num0, denom0; 1091 unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS, 1092 VSE, VT; 1093 char LACE, DBLSCAN, TEXT; 1094 unsigned char seq; 1095 int uplim, lowlim; 1096 int hmul; 1097 1098 /* identity */ 1099 gv = &md->gv; 1100 TEXT = (gv->depth == 4); 1101 1102 if (!et_mondefok(gv)) { 1103 printf("mondef not ok\n"); 1104 return (0); 1105 } 1106 ba = gp->g_regkva; 1107 1108 /* provide all needed information in grf device-independant locations */ 1109 gp->g_data = (caddr_t) gv; 1110 gi = &gp->g_display; 1111 gi->gd_regaddr = (caddr_t) ztwopa(ba); 1112 gi->gd_regsize = 64 * 1024; 1113 gi->gd_fbaddr = (caddr_t) kvtop(gp->g_fbkva); 1114 gi->gd_fbsize = et_fbsize; 1115 gi->gd_colors = 1 << gv->depth; 1116 gi->gd_planes = gv->depth; 1117 gi->gd_fbwidth = gv->disp_width; 1118 gi->gd_fbheight = gv->disp_height; 1119 gi->gd_fbx = 0; 1120 gi->gd_fby = 0; 1121 if (TEXT) { 1122 gi->gd_dwidth = md->fx * md->cols; 1123 gi->gd_dheight = md->fy * md->rows; 1124 } else { 1125 gi->gd_dwidth = gv->disp_width; 1126 gi->gd_dheight = gv->disp_height; 1127 } 1128 gi->gd_dx = 0; 1129 gi->gd_dy = 0; 1130 1131 /* get display mode parameters */ 1132 1133 HBS = gv->hblank_start; 1134 HBE = gv->hblank_stop; 1135 HSS = gv->hsync_start; 1136 HSE = gv->hsync_stop; 1137 HT = gv->htotal; 1138 VBS = gv->vblank_start; 1139 VSS = gv->vsync_start; 1140 VSE = gv->vsync_stop; 1141 VBE = gv->vblank_stop; 1142 VT = gv->vtotal; 1143 1144 if (TEXT) 1145 HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1; 1146 else 1147 HDE = (gv->disp_width + 3) / 8 - 1; /* HBS; */ 1148 VDE = gv->disp_height - 1; 1149 1150 /* figure out whether lace or dblscan is needed */ 1151 1152 uplim = gv->disp_height + (gv->disp_height / 4); 1153 lowlim = gv->disp_height - (gv->disp_height / 4); 1154 LACE = (((VT * 2) > lowlim) && ((VT * 2) < uplim)) ? 1 : 0; 1155 DBLSCAN = (((VT / 2) > lowlim) && ((VT / 2) < uplim)) ? 1 : 0; 1156 1157 /* adjustments (crest) */ 1158 switch (gv->depth) { 1159 case 15: 1160 case 16: hmul = 2; 1161 break; 1162 case 24: hmul = 3; 1163 break; 1164 break; 1165 case 32: hmul = 4; 1166 break; 1167 default: hmul = 1; 1168 } 1169 1170 HDE *= hmul; 1171 HBS *= hmul; 1172 HSS *= hmul; 1173 HSE *= hmul; 1174 HBE *= hmul; 1175 HT *= hmul; 1176 1177 if (LACE) { 1178 VBS *= 2, 1179 VSS *= 2; 1180 VSE *= 2; 1181 VBE *= 2; 1182 VT = VT * 2 + 1; 1183 } 1184 1185 if (DBLSCAN) 1186 VDE *= 2; 1187 1188 WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e); 1189 1190 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00); 1191 WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff); 1192 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); 1193 1194 /* Set clock */ 1195 et_CompFQ( gv->pixel_clock * hmul, &num0, &denom0); 1196 1197 vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3 | ((num0 & 3) << 2)); 1198 WCrt(ba, CRT_ID_6845_COMPAT, (num0 & 4) ? 0x0a : 0x08); 1199 seq=RSeq(ba, SEQ_ID_CLOCKING_MODE); 1200 switch(denom0) { 1201 case 0: 1202 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xb4); 1203 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7); 1204 break; 1205 case 1: 1206 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf4); 1207 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7); 1208 break; 1209 case 2: 1210 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5); 1211 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7); 1212 break; 1213 case 3: 1214 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5); 1215 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq | 0x08); 1216 break; 1217 } 1218 1219 /* load display parameters into board */ 1220 WCrt(ba, CRT_ID_HOR_TOTAL, HT); 1221 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? HBS - 1 : HDE)); 1222 WCrt(ba, CRT_ID_START_HOR_BLANK, HBS); 1223 WCrt(ba, CRT_ID_END_HOR_BLANK, (HBE & 0x1f) | 0x80); 1224 WCrt(ba, CRT_ID_START_HOR_RETR, HSS); 1225 WCrt(ba, CRT_ID_END_HOR_RETR, 1226 (HSE & 0x1f) | 1227 ((HBE & 0x20) ? 0x80 : 0x00)); 1228 WCrt(ba, CRT_ID_VER_TOTAL, VT); 1229 WCrt(ba, CRT_ID_OVERFLOW, 1230 0x10 | 1231 ((VT & 0x100) ? 0x01 : 0x00) | 1232 ((VDE & 0x100) ? 0x02 : 0x00) | 1233 ((VSS & 0x100) ? 0x04 : 0x00) | 1234 ((VBS & 0x100) ? 0x08 : 0x00) | 1235 ((VT & 0x200) ? 0x20 : 0x00) | 1236 ((VDE & 0x200) ? 0x40 : 0x00) | 1237 ((VSS & 0x200) ? 0x80 : 0x00)); 1238 1239 WCrt(ba, CRT_ID_MAX_ROW_ADDRESS, 1240 0x40 | /* splitscreen not visible */ 1241 (DBLSCAN ? 0x80 : 0x00) | 1242 ((VBS & 0x200) ? 0x20 : 0x00) | 1243 (TEXT ? ((md->fy - 1) & 0x1f) : 0x00)); 1244 1245 WCrt(ba, CRT_ID_MODE_CONTROL, 1246 ((TEXT || (gv->depth == 1)) ? 0xc3 : 0xab)); 1247 1248 /* text cursor */ 1249 if (TEXT) { 1250 #if ET_ULCURSOR 1251 WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2); 1252 WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1); 1253 #else 1254 WCrt(ba, CRT_ID_CURSOR_START, 0x00); 1255 WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f); 1256 #endif 1257 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00); 1258 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00); 1259 } 1260 1261 WCrt(ba, CRT_ID_UNDERLINE_LOC, ((md->fy - 1) & 0x1f) 1262 | ((TEXT || (gv->depth == 1)) ? 0x00 : 0x60)); 1263 1264 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00); 1265 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00); 1266 1267 WCrt(ba, CRT_ID_START_VER_RETR, VSS); 1268 WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f) | 0x30); 1269 WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE); 1270 WCrt(ba, CRT_ID_START_VER_BLANK, VBS); 1271 WCrt(ba, CRT_ID_END_VER_BLANK, VBE); 1272 1273 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); 1274 1275 WCrt(ba, CRT_ID_OVERFLOW_HIGH, 1276 ((VBS & 0x400) ? 0x01 : 0x00) | 1277 ((VT & 0x400) ? 0x02 : 0x00) | 1278 ((VDE & 0x400) ? 0x04 : 0x00) | 1279 ((VSS & 0x400) ? 0x08 : 0x00) | 1280 0x10 | 1281 (LACE ? 0x80 : 0x00)); 1282 1283 WCrt(ba, CRT_ID_HOR_OVERFLOW, 1284 ((HT & 0x100) ? 0x01 : 0x00) | 1285 ((HBS & 0x100) ? 0x04 : 0x00) | 1286 ((HSS & 0x100) ? 0x10 : 0x00) 1287 ); 1288 1289 /* depth dependent stuff */ 1290 1291 WGfx(ba, GCT_ID_GRAPHICS_MODE, 1292 ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40)); 1293 WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01)); 1294 1295 vgaw(ba, VDAC_MASK, 0xff); 1296 vgar(ba, VDAC_MASK); 1297 vgar(ba, VDAC_MASK); 1298 vgar(ba, VDAC_MASK); 1299 vgar(ba, VDAC_MASK); 1300 switch (gv->depth) { 1301 case 1: 1302 case 4: /* text */ 1303 switch(etdtype) { 1304 case SIERRA11483: 1305 case SIERRA15025: 1306 case MUSICDAC: 1307 vgaw(ba, VDAC_MASK, 0); 1308 break; 1309 case ATT20C491: 1310 vgaw(ba, VDAC_MASK, 0x02); 1311 break; 1312 case MERLINDAC: 1313 setMerlinDACmode(ba, 0); 1314 break; 1315 } 1316 HDE = gv->disp_width / 16; 1317 break; 1318 case 8: 1319 switch(etdtype) { 1320 case SIERRA11483: 1321 case SIERRA15025: 1322 case MUSICDAC: 1323 vgaw(ba, VDAC_MASK, 0); 1324 break; 1325 case ATT20C491: 1326 vgaw(ba, VDAC_MASK, 0x02); 1327 break; 1328 case MERLINDAC: 1329 setMerlinDACmode(ba, 0); 1330 break; 1331 } 1332 HDE = gv->disp_width / 8; 1333 break; 1334 case 15: 1335 switch(etdtype) { 1336 case SIERRA11483: 1337 case SIERRA15025: 1338 case MUSICDAC: 1339 case ATT20C491: 1340 vgaw(ba, VDAC_MASK, 0xa0); 1341 break; 1342 case MERLINDAC: 1343 setMerlinDACmode(ba, 0xa0); 1344 break; 1345 } 1346 HDE = gv->disp_width / 4; 1347 break; 1348 case 16: 1349 switch(etdtype) { 1350 case SIERRA11483: 1351 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */ 1352 break; 1353 case SIERRA15025: 1354 vgaw(ba, VDAC_MASK, 0xe0); 1355 break; 1356 case MUSICDAC: 1357 case ATT20C491: 1358 vgaw(ba, VDAC_MASK, 0xc0); 1359 break; 1360 case MERLINDAC: 1361 setMerlinDACmode(ba, 0xe0); 1362 break; 1363 } 1364 HDE = gv->disp_width / 4; 1365 break; 1366 case 24: 1367 switch(etdtype) { 1368 case SIERRA11483: 1369 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */ 1370 break; 1371 case SIERRA15025: 1372 vgaw(ba, VDAC_MASK, 0xe1); 1373 break; 1374 case MUSICDAC: 1375 case ATT20C491: 1376 vgaw(ba, VDAC_MASK, 0xe0); 1377 break; 1378 case MERLINDAC: 1379 setMerlinDACmode(ba, 0xf0); 1380 break; 1381 } 1382 HDE = (gv->disp_width / 8) * 3; 1383 break; 1384 case 32: 1385 switch(etdtype) { 1386 case SIERRA11483: 1387 case MUSICDAC: 1388 case ATT20C491: 1389 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */ 1390 break; 1391 case SIERRA15025: 1392 vgaw(ba, VDAC_MASK, 0x61); 1393 break; 1394 case MERLINDAC: 1395 setMerlinDACmode(ba, 0xb0); 1396 break; 1397 } 1398 HDE = gv->disp_width / 2; 1399 break; 1400 } 1401 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x0a : 0x01)); 1402 WAttr(ba, 0x20 | ACT_ID_COLOR_PLANE_ENA, 1403 (gv->depth == 1) ? 0x01 : 0x0f); 1404 1405 WCrt(ba, CRT_ID_OFFSET, HDE); 1406 vgaw(ba, CRT_ADDRESS, CRT_ID_HOR_OVERFLOW); 1407 vgaw(ba, CRT_ADDRESS_W, 1408 (vgar(ba, CRT_ADDRESS_R) & 0x7f) 1409 | ((HDE & 0x100) ? 0x80: 0x00)); 1410 1411 /* text initialization */ 1412 if (TEXT) { 1413 et_inittextmode(gp); 1414 } 1415 1416 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01); 1417 1418 /* Pass-through */ 1419 RegOffpass(ba); 1420 1421 return (1); 1422 } 1423 1424 1425 void 1426 et_inittextmode(gp) 1427 struct grf_softc *gp; 1428 { 1429 struct grfettext_mode *tm = (struct grfettext_mode *) gp->g_data; 1430 volatile unsigned char *ba = gp->g_regkva; 1431 unsigned char *fb = gp->g_fbkva; 1432 unsigned char *c, *f, y; 1433 unsigned short z; 1434 1435 1436 /* 1437 * load text font into beginning of display memory. Each character 1438 * cell is 32 bytes long (enough for 4 planes) 1439 */ 1440 1441 SetTextPlane(ba, 0x02); 1442 et_memset(fb, 0, 256 * 32); 1443 c = (unsigned char *) (fb) + (32 * tm->fdstart); 1444 f = tm->fdata; 1445 for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy)) 1446 for (y = 0; y < tm->fy; y++) 1447 *c++ = *f++; 1448 1449 /* clear out text/attr planes (three screens worth) */ 1450 1451 SetTextPlane(ba, 0x01); 1452 et_memset(fb, 0x07, tm->cols * tm->rows * 3); 1453 SetTextPlane(ba, 0x00); 1454 et_memset(fb, 0x20, tm->cols * tm->rows * 3); 1455 1456 /* print out a little init msg */ 1457 1458 c = (unsigned char *) (fb) + (tm->cols - 16); 1459 strcpy(c, "TSENG"); 1460 c[5] = 0x20; 1461 1462 /* set colors (B&W) */ 1463 1464 switch(ettype) { 1465 case MERLIN: 1466 vgaw(ba, MERLIN_VDAC_INDEX, 0); 1467 for (z = 0; z < 256; z++) { 1468 y = (z & 1) ? ((z > 7) ? 2 : 1) : 0; 1469 1470 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][0]); 1471 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][1]); 1472 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][2]); 1473 } 1474 break; 1475 default: 1476 vgaw(ba, VDAC_ADDRESS_W, 0); 1477 for (z = 0; z < 256; z++) { 1478 y = (z & 1) ? ((z > 7) ? 2 : 1) : 0; 1479 1480 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), 1481 etconscolors[y][0] >> etcmap_shift); 1482 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), 1483 etconscolors[y][1] >> etcmap_shift); 1484 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), 1485 etconscolors[y][2] >> etcmap_shift); 1486 } 1487 break; 1488 } 1489 } 1490 1491 1492 void 1493 et_memset(d, c, l) 1494 unsigned char *d; 1495 unsigned char c; 1496 int l; 1497 { 1498 for (; l > 0; l--) 1499 *d++ = c; 1500 } 1501 1502 1503 static int 1504 et_getControllerType(gp) 1505 struct grf_softc * gp; 1506 { 1507 unsigned char *ba = gp->g_regkva; /* register base */ 1508 unsigned char *mem = gp->g_fbkva; /* memory base */ 1509 unsigned char *mmu = mem + MMU_APERTURE0; /* MMU aperture 0 base */ 1510 1511 *mem = 0; 1512 1513 /* make ACL visible */ 1514 if(ettype == MERLIN) { 1515 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xbb); 1516 } 1517 else { 1518 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xfb); 1519 } 1520 1521 WIma(ba, IMA_PORTCONTROL, 0x01); 1522 1523 *((unsigned long *)mmu) = 0; 1524 *(mem + 0x13) = 0x38; 1525 1526 *mmu = 0xff; 1527 1528 /* hide ACL */ 1529 WIma(ba, IMA_PORTCONTROL, 0x00); 1530 1531 if(ettype == MERLIN) { 1532 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0x93); 1533 } 1534 else { 1535 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xd3); 1536 } 1537 return((*mem == 0xff) ? ETW32 : ET4000); 1538 } 1539 1540 1541 static int 1542 et_getDACType(gp) 1543 struct grf_softc * gp; 1544 { 1545 unsigned char *ba = gp->g_regkva; 1546 union { 1547 int tt; 1548 char cc[4]; 1549 } check; 1550 1551 /* check for Sierra SC 15025 */ 1552 1553 /* We MUST do 4 HW reads to switch into command mode */ 1554 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); 1555 vgaw(ba, VDAC_COMMAND, 0x10); /* set ERPF */ 1556 1557 vgaw(ba, VDAC_XINDEX, 9); 1558 check.cc[0] = vgar(ba, VDAC_XDATA); 1559 vgaw(ba, VDAC_XINDEX, 10); 1560 check.cc[1] = vgar(ba, VDAC_XDATA); 1561 vgaw(ba, VDAC_XINDEX, 11); 1562 check.cc[2] = vgar(ba, VDAC_XDATA); 1563 vgaw(ba, VDAC_XINDEX, 12); 1564 check.cc[3] = vgar(ba, VDAC_XDATA); 1565 1566 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); 1567 vgaw(ba, VDAC_COMMAND, 0x00); /* clear ERPF */ 1568 1569 if (check.tt == 0x533ab141) { 1570 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); 1571 vgaw(ba, VDAC_COMMAND, 0x10); /* set ERPF */ 1572 1573 /* switch to 8 bits per color */ 1574 vgaw(ba, VDAC_XINDEX, 8); 1575 vgaw(ba, VDAC_XDATA, 1); 1576 /* do not shift color values */ 1577 etcmap_shift = 0; 1578 1579 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); 1580 vgaw(ba, VDAC_COMMAND, 0x00); /* clear ERPF */ 1581 1582 vgaw(ba, VDAC_MASK, 0xff); 1583 return (SIERRA15025); 1584 } 1585 1586 /* check for MUSIC DAC */ 1587 1588 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); 1589 vgaw(ba, VDAC_COMMAND, 0x02); /* set some strange MUSIC mode (???) */ 1590 1591 vgaw(ba, VDAC_XINDEX, 0x01); 1592 if (vgar(ba, VDAC_XDATA) == 0x01) { 1593 /* shift color values by 2 */ 1594 etcmap_shift = 2; 1595 1596 vgaw(ba, VDAC_MASK, 0xff); 1597 return (MUSICDAC); 1598 } 1599 1600 /* check for AT&T ATT20c491 DAC (crest) */ 1601 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); 1602 vgaw(ba, HDR, 0xff); 1603 vgaw(ba, VDAC_MASK, 0x01); 1604 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); 1605 if (vgar(ba, HDR) == 0xff) { 1606 /* do not shift color values */ 1607 etcmap_shift = 0; 1608 1609 vgaw(ba, VDAC_MASK, 0xff); 1610 return (ATT20C491); 1611 } 1612 1613 /* restore PowerUp settings (crest) */ 1614 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); 1615 vgaw(ba, HDR, 0x00); 1616 1617 /* 1618 * nothing else found, so let us pretend it is a stupid 1619 * Sierra SC 11483 1620 */ 1621 1622 /* shift color values by 2 */ 1623 etcmap_shift = 2; 1624 1625 vgaw(ba, VDAC_MASK, 0xff); 1626 return (SIERRA11483); 1627 } 1628 1629 #endif /* NGRFET */ 1630