1 /* $NetBSD: grf_et.c,v 1.7 1996/10/13 03:07:04 christos 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 > 0 ? 0x01 : 0x21); 603 return(0); 604 } 605 606 607 /* 608 * Change the mode of the display. 609 * Return a UNIX error number or 0 for success. 610 */ 611 int 612 et_mode(gp, cmd, arg, a2, a3) 613 register struct grf_softc *gp; 614 u_long cmd; 615 void *arg; 616 u_long a2; 617 int a3; 618 { 619 int error; 620 621 switch (cmd) { 622 case GM_GRFON: 623 error = et_load_mon(gp, 624 (struct grfettext_mode *) monitor_current) ? 0 : EINVAL; 625 return (error); 626 627 case GM_GRFOFF: 628 #ifndef TSENGCONSOLE 629 et_off(gp); 630 #else 631 et_load_mon(gp, &etconsole_mode); 632 #endif 633 return (0); 634 635 case GM_GRFCONFIG: 636 return (0); 637 638 case GM_GRFGETVMODE: 639 return (et_getvmode(gp, (struct grfvideo_mode *) arg)); 640 641 case GM_GRFSETVMODE: 642 error = et_setvmode(gp, *(unsigned *) arg); 643 if (!error && (gp->g_flags & GF_GRFON)) 644 et_load_mon(gp, 645 (struct grfettext_mode *) monitor_current); 646 return (error); 647 648 case GM_GRFGETNUMVM: 649 *(int *) arg = monitor_def_max; 650 return (0); 651 652 case GM_GRFIOCTL: 653 return (et_ioctl(gp, a2, arg)); 654 655 default: 656 break; 657 } 658 659 return (EINVAL); 660 } 661 662 663 int 664 et_ioctl(gp, cmd, data) 665 register struct grf_softc *gp; 666 u_long cmd; 667 void *data; 668 { 669 switch (cmd) { 670 case GRFIOCGSPRITEPOS: 671 return (et_getmousepos(gp, (struct grf_position *) data)); 672 673 case GRFIOCSSPRITEPOS: 674 return (et_setmousepos(gp, (struct grf_position *) data)); 675 676 case GRFIOCSSPRITEINF: 677 return (et_setspriteinfo(gp, (struct grf_spriteinfo *) data)); 678 679 case GRFIOCGSPRITEINF: 680 return (et_getspriteinfo(gp, (struct grf_spriteinfo *) data)); 681 682 case GRFIOCGSPRITEMAX: 683 return (et_getspritemax(gp, (struct grf_position *) data)); 684 685 case GRFIOCGETCMAP: 686 return (et_getcmap(gp, (struct grf_colormap *) data)); 687 688 case GRFIOCPUTCMAP: 689 return (et_putcmap(gp, (struct grf_colormap *) data)); 690 691 case GRFIOCBITBLT: 692 break; 693 694 case GRFTOGGLE: 695 return (et_toggle(gp, 0)); 696 697 case GRFIOCSETMON: 698 return (et_setmonitor(gp, (struct grfvideo_mode *) data)); 699 700 case GRFIOCBLANK: 701 return (et_blank(gp, (int *)data)); 702 } 703 return (EINVAL); 704 } 705 706 707 int 708 et_getmousepos(gp, data) 709 struct grf_softc *gp; 710 struct grf_position *data; 711 { 712 data->x = et_cursprite.pos.x; 713 data->y = et_cursprite.pos.y; 714 715 return (0); 716 } 717 718 719 void 720 et_writesprpos(ba, x, y) 721 volatile char *ba; 722 short x; 723 short y; 724 { 725 } 726 727 728 int 729 et_setmousepos(gp, data) 730 struct grf_softc *gp; 731 struct grf_position *data; 732 { 733 volatile char *ba = gp->g_regkva; 734 short rx, ry, prx, pry; 735 736 /* no movement */ 737 if (et_cursprite.pos.x == data->x && et_cursprite.pos.y == data->y) 738 return (0); 739 740 /* current and previous real coordinates */ 741 rx = data->x - et_cursprite.hot.x; 742 ry = data->y - et_cursprite.hot.y; 743 prx = et_cursprite.pos.x - et_cursprite.hot.x; 744 pry = et_cursprite.pos.y - et_cursprite.hot.y; 745 746 /* if we are/were on an edge, create (un)shifted bitmap -- 747 * ripped out optimization (not extremely worthwhile, 748 * and kind of buggy anyhow). 749 */ 750 751 /* do movement, save position */ 752 et_writesprpos(ba, rx < 0 ? 0 : rx, ry < 0 ? 0 : ry); 753 et_cursprite.pos.x = data->x; 754 et_cursprite.pos.y = data->y; 755 756 return (0); 757 } 758 759 760 int 761 et_getspriteinfo(gp, data) 762 struct grf_softc *gp; 763 struct grf_spriteinfo *data; 764 { 765 766 return(EINVAL); 767 } 768 769 770 static int 771 et_setspriteinfo(gp, data) 772 struct grf_softc *gp; 773 struct grf_spriteinfo *data; 774 { 775 776 return(EINVAL); 777 } 778 779 780 static int 781 et_getspritemax(gp, data) 782 struct grf_softc *gp; 783 struct grf_position *data; 784 { 785 786 return(EINVAL); 787 } 788 789 790 int 791 et_setmonitor(gp, gv) 792 struct grf_softc *gp; 793 struct grfvideo_mode *gv; 794 { 795 struct grfvideo_mode *md; 796 797 if (!et_mondefok(gv)) 798 return(EINVAL); 799 800 #ifdef TSENGCONSOLE 801 /* handle interactive setting of console mode */ 802 if (gv->mode_num == 255) { 803 bcopy(gv, &etconsole_mode.gv, sizeof(struct grfvideo_mode)); 804 etconsole_mode.gv.hblank_start /= 8; 805 etconsole_mode.gv.hblank_stop /= 8; 806 etconsole_mode.gv.hsync_start /= 8; 807 etconsole_mode.gv.hsync_stop /= 8; 808 etconsole_mode.gv.htotal /= 8; 809 etconsole_mode.rows = gv->disp_height / etconsole_mode.fy; 810 etconsole_mode.cols = gv->disp_width / etconsole_mode.fx; 811 if (!(gp->g_flags & GF_GRFON)) 812 et_load_mon(gp, &etconsole_mode); 813 ite_reinit(gp->g_itedev); 814 return (0); 815 } 816 #endif 817 818 md = monitor_def + (gv->mode_num - 1); 819 bcopy(gv, md, sizeof(struct grfvideo_mode)); 820 821 /* adjust pixel oriented values to internal rep. */ 822 823 md->hblank_start /= 8; 824 md->hblank_stop /= 8; 825 md->hsync_start /= 8; 826 md->hsync_stop /= 8; 827 md->htotal /= 8; 828 829 return (0); 830 } 831 832 833 int 834 et_getcmap(gfp, cmap) 835 struct grf_softc *gfp; 836 struct grf_colormap *cmap; 837 { 838 volatile unsigned char *ba; 839 u_char red[256], green[256], blue[256], *rp, *gp, *bp; 840 short x; 841 int error; 842 843 if (cmap->count == 0 || cmap->index >= 256) 844 return 0; 845 846 if (cmap->index + cmap->count > 256) 847 cmap->count = 256 - cmap->index; 848 849 ba = gfp->g_regkva; 850 /* first read colors out of the chip, then copyout to userspace */ 851 x = cmap->count - 1; 852 853 rp = red + cmap->index; 854 gp = green + cmap->index; 855 bp = blue + cmap->index; 856 857 switch(ettype) { 858 case MERLIN: 859 vgaw(ba, MERLIN_VDAC_INDEX, cmap->index); 860 do { 861 *rp++ = vgar(ba, MERLIN_VDAC_COLORS); 862 *gp++ = vgar(ba, MERLIN_VDAC_COLORS); 863 *bp++ = vgar(ba, MERLIN_VDAC_COLORS); 864 } while (x-- > 0); 865 break; 866 default: 867 vgaw(ba, VDAC_ADDRESS_R+((ettype==DOMINO)?0x0fff:0), cmap->index); 868 do { 869 *rp++ = vgar(ba, VDAC_DATA+((ettype==DOMINO)?0x0fff:0)) << etcmap_shift; 870 *gp++ = vgar(ba, VDAC_DATA+((ettype==DOMINO)?0x0fff:0)) << etcmap_shift; 871 *bp++ = vgar(ba, VDAC_DATA+((ettype==DOMINO)?0x0fff:0)) << etcmap_shift; 872 } while (x-- > 0); 873 break; 874 } 875 876 error = copyout(red + cmap->index, cmap->red, cmap->count); 877 if (!error) 878 error = copyout(green + cmap->index, cmap->green, cmap->count); 879 if (!error) 880 error = copyout(blue + cmap->index, cmap->blue, cmap->count); 881 882 return (error); 883 } 884 885 886 int 887 et_putcmap(gfp, cmap) 888 struct grf_softc *gfp; 889 struct grf_colormap *cmap; 890 { 891 volatile unsigned char *ba; 892 u_char red[256], green[256], blue[256], *rp, *gp, *bp; 893 short x; 894 int error; 895 896 if (cmap->count == 0 || cmap->index >= 256) 897 return (0); 898 899 if (cmap->index + cmap->count > 256) 900 cmap->count = 256 - cmap->index; 901 902 /* first copy the colors into kernelspace */ 903 if ((error = copyin(cmap->red, red + cmap->index, cmap->count))) 904 return (error); 905 906 if ((error = copyin(cmap->green, green + cmap->index, cmap->count))) 907 return (error); 908 909 if ((error = copyin(cmap->blue, blue + cmap->index, cmap->count))) 910 return (error); 911 912 ba = gfp->g_regkva; 913 x = cmap->count - 1; 914 915 rp = red + cmap->index; 916 gp = green + cmap->index; 917 bp = blue + cmap->index; 918 919 switch(ettype){ 920 case MERLIN: 921 vgaw(ba, MERLIN_VDAC_INDEX, cmap->index); 922 do { 923 vgaw(ba, MERLIN_VDAC_COLORS, *rp++); 924 vgaw(ba, MERLIN_VDAC_COLORS, *gp++); 925 vgaw(ba, MERLIN_VDAC_COLORS, *bp++); 926 } while (x-- > 0); 927 break; 928 default: 929 vgaw(ba, VDAC_ADDRESS_W, cmap->index); 930 do { 931 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), 932 *rp++ >> etcmap_shift); 933 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), 934 *gp++ >> etcmap_shift); 935 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), 936 *bp++ >> etcmap_shift); 937 } while (x-- > 0); 938 break; 939 } 940 941 return (0); 942 } 943 944 945 int 946 et_toggle(gp, wopp) 947 struct grf_softc *gp; 948 unsigned short wopp; /* don't need that one yet, ill */ 949 { 950 volatile unsigned char *ba; 951 952 ba = gp->g_regkva; 953 954 if (pass_toggle) { 955 RegOffpass(ba); 956 } else { 957 RegOnpass(ba); 958 } 959 return (0); 960 } 961 962 963 #define ET_NUMCLOCKS 32 964 965 static u_char et_clocks[ET_NUMCLOCKS] = { 966 0, 1, 6, 2, 3, 7, 4, 5, 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 }; 971 972 static u_char et_clockdividers[ET_NUMCLOCKS] = { 973 3, 3, 3, 3, 3, 3, 3, 3, 974 2, 2, 2, 2, 2, 2, 2, 2, 975 1, 1, 1, 1, 1, 1, 1, 1, 976 0, 0, 0, 0, 0, 0, 0, 0 977 }; 978 979 static u_int et_clockfreqs[ET_NUMCLOCKS] = { 980 6293750, 7080500, 7875000, 8125000, 981 9000000, 9375000, 10000000, 11225000, 982 12587500, 14161000, 15750000, 16250000, 983 18000000, 18750000, 20000000, 22450000, 984 25175000, 28322000, 31500000, 32500000, 985 36000000, 37500000, 40000000, 44900000, 986 50350000, 56644000, 63000000, 65000000, 987 72000000, 75000000, 80000000, 89800000 988 }; 989 990 991 static void 992 et_CompFQ(fq, num, denom) 993 u_int fq; 994 u_char *num; 995 u_char *denom; 996 { 997 int i; 998 999 for (i=0; i < ET_NUMCLOCKS;) { 1000 if (fq <= et_clockfreqs[i++]) { 1001 break; 1002 } 1003 } 1004 1005 *num = et_clocks[--i]; 1006 *denom = et_clockdividers[i]; 1007 1008 return; 1009 } 1010 1011 1012 int 1013 et_mondefok(gv) 1014 struct grfvideo_mode *gv; 1015 { 1016 1017 if (gv->mode_num < 1 || gv->mode_num > monitor_def_max) 1018 if (gv->mode_num != 255 || gv->depth != 4) 1019 return(0); 1020 1021 switch (gv->depth) { 1022 case 4: 1023 if (gv->mode_num != 255) 1024 return(0); 1025 case 1: 1026 case 8: 1027 case 15: 1028 case 16: 1029 case 24: 1030 break; 1031 default: 1032 return (0); 1033 } 1034 return (1); 1035 } 1036 1037 1038 int 1039 et_load_mon(gp, md) 1040 struct grf_softc *gp; 1041 struct grfettext_mode *md; 1042 { 1043 struct grfvideo_mode *gv; 1044 struct grfinfo *gi; 1045 volatile unsigned char *ba; 1046 unsigned char num0, denom0; 1047 unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS, 1048 VSE, VT; 1049 char LACE, DBLSCAN, TEXT; 1050 unsigned char seq; 1051 int uplim, lowlim; 1052 1053 /* identity */ 1054 gv = &md->gv; 1055 TEXT = (gv->depth == 4); 1056 1057 if (!et_mondefok(gv)) { 1058 printf("mondef not ok\n"); 1059 return (0); 1060 } 1061 ba = gp->g_regkva; 1062 1063 /* provide all needed information in grf device-independant locations */ 1064 gp->g_data = (caddr_t) gv; 1065 gi = &gp->g_display; 1066 gi->gd_regaddr = (caddr_t) ztwopa(ba); 1067 gi->gd_regsize = 64 * 1024; 1068 gi->gd_fbaddr = (caddr_t) kvtop(gp->g_fbkva); 1069 gi->gd_fbsize = et_fbsize; 1070 gi->gd_colors = 1 << gv->depth; 1071 gi->gd_planes = gv->depth; 1072 gi->gd_fbwidth = gv->disp_width; 1073 gi->gd_fbheight = gv->disp_height; 1074 gi->gd_fbx = 0; 1075 gi->gd_fby = 0; 1076 if (TEXT) { 1077 gi->gd_dwidth = md->fx * md->cols; 1078 gi->gd_dheight = md->fy * md->rows; 1079 } else { 1080 gi->gd_dwidth = gv->disp_width; 1081 gi->gd_dheight = gv->disp_height; 1082 } 1083 gi->gd_dx = 0; 1084 gi->gd_dy = 0; 1085 1086 /* get display mode parameters */ 1087 1088 HBS = gv->hblank_start; 1089 HBE = gv->hblank_stop; 1090 HSS = gv->hsync_start; 1091 HSE = gv->hsync_stop; 1092 HT = gv->htotal; 1093 VBS = gv->vblank_start; 1094 VSS = gv->vsync_start; 1095 VSE = gv->vsync_stop; 1096 VBE = gv->vblank_stop; 1097 VT = gv->vtotal; 1098 1099 if (TEXT) 1100 HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1; 1101 else 1102 HDE = (gv->disp_width + 3) / 8 - 1; /* HBS; */ 1103 VDE = gv->disp_height - 1; 1104 1105 /* figure out whether lace or dblscan is needed */ 1106 1107 uplim = gv->disp_height + (gv->disp_height / 4); 1108 lowlim = gv->disp_height - (gv->disp_height / 4); 1109 LACE = (((VT * 2) > lowlim) && ((VT * 2) < uplim)) ? 1 : 0; 1110 DBLSCAN = (((VT / 2) > lowlim) && ((VT / 2) < uplim)) ? 1 : 0; 1111 1112 /* adjustments */ 1113 1114 if (LACE) 1115 VDE /= 2; 1116 1117 WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e); 1118 1119 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00); 1120 WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff); 1121 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); 1122 1123 /* Set clock */ 1124 1125 et_CompFQ( gv->pixel_clock, &num0, &denom0); 1126 1127 vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3 | ((num0 & 3) << 2)); 1128 WCrt(ba, CRT_ID_6845_COMPAT, (num0 & 4) ? 0x0a : 0x08); 1129 seq=RSeq(ba, SEQ_ID_CLOCKING_MODE); 1130 switch(denom0) { 1131 case 0: 1132 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xb4); 1133 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7); 1134 break; 1135 case 1: 1136 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf4); 1137 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7); 1138 break; 1139 case 2: 1140 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5); 1141 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7); 1142 break; 1143 case 3: 1144 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5); 1145 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq | 0x08); 1146 break; 1147 } 1148 /* load display parameters into board */ 1149 1150 WCrt(ba, CRT_ID_HOR_TOTAL, HT); 1151 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? HBS - 1 : HDE)); 1152 WCrt(ba, CRT_ID_START_HOR_BLANK, HBS); 1153 WCrt(ba, CRT_ID_END_HOR_BLANK, (HBE & 0x1f) | 0x80); /* | 0x80? */ 1154 WCrt(ba, CRT_ID_START_HOR_RETR, HSS); 1155 WCrt(ba, CRT_ID_END_HOR_RETR, 1156 (HSE & 0x1f) | 1157 ((HBE & 0x20) ? 0x80 : 0x00)); 1158 WCrt(ba, CRT_ID_VER_TOTAL, VT); 1159 WCrt(ba, CRT_ID_OVERFLOW, 1160 0x10 | 1161 ((VT & 0x100) ? 0x01 : 0x00) | 1162 ((VDE & 0x100) ? 0x02 : 0x00) | 1163 ((VSS & 0x100) ? 0x04 : 0x00) | 1164 ((VBS & 0x100) ? 0x08 : 0x00) | 1165 ((VT & 0x200) ? 0x20 : 0x00) | 1166 ((VDE & 0x200) ? 0x40 : 0x00) | 1167 ((VSS & 0x200) ? 0x80 : 0x00)); 1168 1169 WCrt(ba, CRT_ID_MAX_ROW_ADDRESS, 1170 0x40 | /* TEXT ? 0x00 ??? */ 1171 (DBLSCAN ? 0x80 : 0x00) | 1172 ((VBS & 0x200) ? 0x20 : 0x00) | 1173 (TEXT ? ((md->fy - 1) & 0x1f) : 0x00)); 1174 1175 WCrt(ba, CRT_ID_MODE_CONTROL, 1176 ((TEXT || (gv->depth == 1)) ? 0xc3 : 0xab)); 1177 1178 /* text cursor */ 1179 1180 if (TEXT) { 1181 #if ET_ULCURSOR 1182 WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2); 1183 WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1); 1184 #else 1185 WCrt(ba, CRT_ID_CURSOR_START, 0x00); 1186 WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f); 1187 #endif 1188 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00); 1189 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00); 1190 } 1191 1192 WCrt(ba, CRT_ID_UNDERLINE_LOC, ((md->fy - 1) & 0x1f) 1193 | ((TEXT || (gv->depth == 1)) ? 0x00 : 0x60)); 1194 1195 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00); 1196 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00); 1197 1198 WCrt(ba, CRT_ID_START_VER_RETR, VSS); 1199 WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f) | 0x30); 1200 WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE); 1201 WCrt(ba, CRT_ID_START_VER_BLANK, VBS); 1202 WCrt(ba, CRT_ID_END_VER_BLANK, VBE); 1203 1204 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); 1205 1206 WCrt(ba, CRT_ID_OVERFLOW_HIGH, 1207 ((VBS & 0x400) ? 0x01 : 0x00) | 1208 ((VT & 0x400) ? 0x02 : 0x00) | 1209 ((VDE & 0x400) ? 0x04 : 0x00) | 1210 ((VSS & 0x400) ? 0x08 : 0x00) | 1211 0x10 | 1212 (LACE ? 0x80 : 0x00)); 1213 1214 WCrt(ba, CRT_ID_HOR_OVERFLOW, 1215 ((HT & 0x100) ? 0x01 : 0x00) | 1216 ((HBS & 0x100) ? 0x04 : 0x00) | 1217 ((HSS & 0x100) ? 0x10 : 0x00) 1218 ); 1219 1220 /* depth dependent stuff */ 1221 1222 WGfx(ba, GCT_ID_GRAPHICS_MODE, 1223 ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40)); 1224 WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01)); 1225 1226 vgaw(ba, VDAC_MASK, 0xff); 1227 vgar(ba, VDAC_MASK); 1228 vgar(ba, VDAC_MASK); 1229 vgar(ba, VDAC_MASK); 1230 vgar(ba, VDAC_MASK); 1231 switch (gv->depth) { 1232 case 1: 1233 case 4: /* text */ 1234 switch(etdtype) { 1235 case SIERRA11483: 1236 case SIERRA15025: 1237 case MUSICDAC: 1238 vgaw(ba, VDAC_MASK, 0); 1239 break; 1240 case MERLINDAC: 1241 setMerlinDACmode(ba, 0); 1242 break; 1243 } 1244 HDE = gv->disp_width / 16; 1245 break; 1246 case 8: 1247 switch(etdtype) { 1248 case SIERRA11483: 1249 case SIERRA15025: 1250 case MUSICDAC: 1251 vgaw(ba, VDAC_MASK, 0); 1252 break; 1253 case MERLINDAC: 1254 setMerlinDACmode(ba, 0); 1255 break; 1256 } 1257 HDE = gv->disp_width / 8; 1258 break; 1259 case 15: 1260 switch(etdtype) { 1261 case SIERRA11483: 1262 case SIERRA15025: 1263 case MUSICDAC: 1264 vgaw(ba, VDAC_MASK, 0xa0); 1265 break; 1266 case MERLINDAC: 1267 setMerlinDACmode(ba, 0xa0); 1268 break; 1269 } 1270 HDE = gv->disp_width / 4; 1271 break; 1272 case 16: 1273 switch(etdtype) { 1274 case SIERRA11483: 1275 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */ 1276 break; 1277 case SIERRA15025: 1278 vgaw(ba, VDAC_MASK, 0xe0); 1279 break; 1280 case MUSICDAC: 1281 vgaw(ba, VDAC_MASK, 0xc0); 1282 break; 1283 case MERLINDAC: 1284 setMerlinDACmode(ba, 0xe0); 1285 break; 1286 } 1287 HDE = gv->disp_width / 4; 1288 break; 1289 case 24: 1290 switch(etdtype) { 1291 case SIERRA11483: 1292 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */ 1293 break; 1294 case SIERRA15025: 1295 vgaw(ba, VDAC_MASK, 0xe1); 1296 break; 1297 case MUSICDAC: 1298 vgaw(ba, VDAC_MASK, 0xe0); 1299 break; 1300 case MERLINDAC: 1301 setMerlinDACmode(ba, 0xf0); 1302 break; 1303 } 1304 HDE = (gv->disp_width / 8) * 3; 1305 break; 1306 case 32: 1307 switch(etdtype) { 1308 case SIERRA11483: 1309 case MUSICDAC: 1310 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */ 1311 break; 1312 case SIERRA15025: 1313 vgaw(ba, VDAC_MASK, 0x61); 1314 break; 1315 case MERLINDAC: 1316 setMerlinDACmode(ba, 0xb0); 1317 break; 1318 } 1319 HDE = gv->disp_width / 2; 1320 break; 1321 } 1322 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x0a : 0x01)); 1323 WAttr(ba, 0x20 | ACT_ID_COLOR_PLANE_ENA, 1324 (gv->depth == 1) ? 0x01 : 0x0f); 1325 1326 WCrt(ba, CRT_ID_OFFSET, HDE); 1327 1328 /* text initialization */ 1329 if (TEXT) { 1330 et_inittextmode(gp); 1331 } 1332 1333 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01); 1334 1335 /* Pass-through */ 1336 RegOffpass(ba); 1337 1338 return (1); 1339 } 1340 1341 1342 void 1343 et_inittextmode(gp) 1344 struct grf_softc *gp; 1345 { 1346 struct grfettext_mode *tm = (struct grfettext_mode *) gp->g_data; 1347 volatile unsigned char *ba = gp->g_regkva; 1348 unsigned char *fb = gp->g_fbkva; 1349 unsigned char *c, *f, y; 1350 unsigned short z; 1351 1352 1353 /* 1354 * load text font into beginning of display memory. Each character 1355 * cell is 32 bytes long (enough for 4 planes) 1356 */ 1357 1358 SetTextPlane(ba, 0x02); 1359 et_memset(fb, 0, 256 * 32); 1360 c = (unsigned char *) (fb) + (32 * tm->fdstart); 1361 f = tm->fdata; 1362 for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy)) 1363 for (y = 0; y < tm->fy; y++) 1364 *c++ = *f++; 1365 1366 /* clear out text/attr planes (three screens worth) */ 1367 1368 SetTextPlane(ba, 0x01); 1369 et_memset(fb, 0x07, tm->cols * tm->rows * 3); 1370 SetTextPlane(ba, 0x00); 1371 et_memset(fb, 0x20, tm->cols * tm->rows * 3); 1372 1373 /* print out a little init msg */ 1374 1375 c = (unsigned char *) (fb) + (tm->cols - 16); 1376 strcpy(c, "TSENG"); 1377 c[6] = 0x20; 1378 1379 /* set colors (B&W) */ 1380 1381 switch(ettype) { 1382 case MERLIN: 1383 vgaw(ba, MERLIN_VDAC_INDEX, 0); 1384 for (z = 0; z < 256; z++) { 1385 y = (z & 1) ? ((z > 7) ? 2 : 1) : 0; 1386 1387 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][0]); 1388 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][1]); 1389 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][2]); 1390 } 1391 break; 1392 default: 1393 vgaw(ba, VDAC_ADDRESS_W, 0); 1394 for (z = 0; z < 256; z++) { 1395 y = (z & 1) ? ((z > 7) ? 2 : 1) : 0; 1396 1397 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), 1398 etconscolors[y][0] >> etcmap_shift); 1399 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), 1400 etconscolors[y][1] >> etcmap_shift); 1401 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), 1402 etconscolors[y][2] >> etcmap_shift); 1403 } 1404 break; 1405 } 1406 } 1407 1408 1409 void 1410 et_memset(d, c, l) 1411 unsigned char *d; 1412 unsigned char c; 1413 int l; 1414 { 1415 for (; l > 0; l--) 1416 *d++ = c; 1417 } 1418 1419 1420 static int 1421 et_getControllerType(gp) 1422 struct grf_softc * gp; 1423 { 1424 unsigned char *ba = gp->g_regkva; /* register base */ 1425 unsigned char *mem = gp->g_fbkva; /* memory base */ 1426 unsigned char *mmu = mem + MMU_APERTURE0; /* MMU aperture 0 base */ 1427 1428 *mem = 0; 1429 1430 /* make ACL visible */ 1431 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xfb); 1432 WIma(ba, IMA_PORTCONTROL, 0x01); 1433 1434 *((unsigned long *)mmu) = 0; 1435 *(mem + 0x13) = 0x38; 1436 1437 *mmu = 0xff; 1438 1439 /* hide ACL */ 1440 WIma(ba, IMA_PORTCONTROL, 0x00); 1441 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xd3); 1442 1443 return((*mem == 0xff) ? ETW32 : ET4000); 1444 } 1445 1446 1447 static int 1448 et_getDACType(gp) 1449 struct grf_softc * gp; 1450 { 1451 unsigned char *ba = gp->g_regkva; 1452 union { 1453 int tt; 1454 char cc[4]; 1455 } check; 1456 1457 /* check for Sierra SC 15025 */ 1458 1459 /* We MUST do 4 HW reads to switch into command mode */ 1460 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); 1461 vgaw(ba, VDAC_COMMAND, 0x10); /* set ERPF */ 1462 1463 vgaw(ba, VDAC_XINDEX, 9); 1464 check.cc[0] = vgar(ba, VDAC_XDATA); 1465 vgaw(ba, VDAC_XINDEX, 10); 1466 check.cc[1] = vgar(ba, VDAC_XDATA); 1467 vgaw(ba, VDAC_XINDEX, 11); 1468 check.cc[2] = vgar(ba, VDAC_XDATA); 1469 vgaw(ba, VDAC_XINDEX, 12); 1470 check.cc[3] = vgar(ba, VDAC_XDATA); 1471 1472 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); 1473 vgaw(ba, VDAC_COMMAND, 0x00); /* clear ERPF */ 1474 1475 if (check.tt == 0x533ab141) { 1476 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); 1477 vgaw(ba, VDAC_COMMAND, 0x10); /* set ERPF */ 1478 1479 /* switch to 8 bits per color */ 1480 vgaw(ba, VDAC_XINDEX, 8); 1481 vgaw(ba, VDAC_XDATA, 1); 1482 /* do not shift color values */ 1483 etcmap_shift = 0; 1484 1485 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); 1486 vgaw(ba, VDAC_COMMAND, 0x00); /* clear ERPF */ 1487 1488 vgaw(ba, VDAC_MASK, 0xff); 1489 return (SIERRA15025); 1490 } 1491 1492 /* check for MUSIC DAC */ 1493 1494 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); 1495 vgaw(ba, VDAC_COMMAND, 0x02); /* set some strange MUSIC mode (???) */ 1496 1497 vgaw(ba, VDAC_XINDEX, 0x01); 1498 if (vgar(ba, VDAC_XDATA) == 0x01) { 1499 /* shift color values by 2 */ 1500 etcmap_shift = 2; 1501 1502 vgaw(ba, VDAC_MASK, 0xff); 1503 return (MUSICDAC); 1504 } 1505 1506 /* 1507 * nothing else found, so let us pretend it is a stupid 1508 * Sierra SC 11483 1509 */ 1510 1511 /* shift color values by 2 */ 1512 etcmap_shift = 2; 1513 1514 vgaw(ba, VDAC_MASK, 0xff); 1515 return (SIERRA11483); 1516 } 1517 1518 #endif /* NGRFET */ 1519