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