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