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