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