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