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