1 /* $NetBSD: grf_et.c,v 1.33 2016/11/04 18:06:08 phx 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.33 2016/11/04 18:06:08 phx Exp $"); 41 42 #include "grfet.h" 43 #include "ite.h" 44 #include "wsdisplay.h" 45 #if NGRFET > 0 46 47 /* 48 * Graphics routines for Tseng ET4000 (&W32) boards, 49 * 50 * This code offers low-level routines to access Tseng ET4000 51 * graphics-boards from within NetBSD for the Amiga. 52 * No warranties for any kind of function at all - this 53 * code may crash your hardware and scratch your harddisk. Use at your 54 * own risk. Freely distributable. 55 * 56 * Modified for Tseng ET4000 from 57 * Kari Mettinen's Cirrus driver by Tobias Abt 58 * 59 * Fixed Merlin in Z-III, fixed LACE and DBLSCAN, added Domino16M proto 60 * and AT&T ATT20c491 DAC, added memory-size detection by Klaus Burkert. 61 * 62 * 63 * TODO: 64 * 65 */ 66 67 #include <sys/param.h> 68 #include <sys/systm.h> 69 #include <sys/errno.h> 70 #include <sys/ioctl.h> 71 #include <sys/device.h> 72 #include <sys/malloc.h> 73 74 #include <machine/cpu.h> 75 #include <dev/cons.h> 76 #if NWSDISPLAY > 0 77 #include <dev/wscons/wsconsio.h> 78 #include <dev/wscons/wsdisplayvar.h> 79 #include <dev/rasops/rasops.h> 80 #include <dev/wscons/wsdisplay_vconsvar.h> 81 #endif 82 #ifdef TSENGCONSOLE 83 #include <amiga/dev/itevar.h> 84 #endif 85 #include <amiga/amiga/device.h> 86 #include <amiga/dev/grfioctl.h> 87 #include <amiga/dev/grfvar.h> 88 #include <amiga/dev/grf_etreg.h> 89 #include <amiga/dev/zbusvar.h> 90 91 int et_mondefok(struct grfvideo_mode *); 92 void et_boardinit(struct grf_softc *); 93 static void et_CompFQ(u_int fq, u_char *, u_char *); 94 int et_getvmode(struct grf_softc *, struct grfvideo_mode *); 95 int et_setvmode(struct grf_softc *, unsigned int); 96 int et_toggle(struct grf_softc *, unsigned short); 97 int et_getcmap(struct grf_softc *, struct grf_colormap *); 98 int et_putcmap(struct grf_softc *, struct grf_colormap *); 99 #ifndef TSENGCONSOLE 100 void et_off(struct grf_softc *); 101 #endif 102 void et_inittextmode(struct grf_softc *); 103 int et_ioctl(register struct grf_softc *, u_long cmd, void *); 104 int et_getmousepos(struct grf_softc *, struct grf_position *); 105 void et_writesprpos(volatile char *ba, short, short); 106 int et_setmousepos(struct grf_softc *, struct grf_position *); 107 static int et_setspriteinfo(struct grf_softc *, struct grf_spriteinfo *); 108 int et_getspriteinfo(struct grf_softc *, struct grf_spriteinfo *); 109 static int et_getspritemax(struct grf_softc *, struct grf_position *); 110 int et_setmonitor(struct grf_softc *, struct grfvideo_mode *); 111 int et_blank(struct grf_softc *, int); 112 int et_isblank(struct grf_softc *); 113 static int et_getControllerType(struct grf_softc *); 114 static int et_getDACType(struct grf_softc *); 115 116 int grfetmatch(device_t, cfdata_t, void *); 117 void grfetattach(device_t, device_t, void *); 118 int grfetprint(void *, const char *); 119 void et_memset(volatile unsigned char *, unsigned char, int); 120 121 #if NWSDISPLAY > 0 122 /* wsdisplay acessops, emulops */ 123 static int et_wsioctl(void *, void *, u_long, void *, int, struct lwp *); 124 static int et_get_fbinfo(struct grf_softc *, struct wsdisplayio_fbinfo *); 125 126 static void et_wscursor(void *, int, int, int); 127 static void et_wsputchar(void *, int, int, u_int, long); 128 static void et_wscopycols(void *, int, int, int, int); 129 static void et_wserasecols(void *, int, int, int, long); 130 static void et_wscopyrows(void *, int, int, int); 131 static void et_wseraserows(void *, int, int, long); 132 static int et_wsallocattr(void *, int, int, int, long *); 133 static int et_wsmapchar(void *, int, unsigned int *); 134 #endif /* NWSDISPLAY > 0 */ 135 136 /* 137 * Graphics display definitions. 138 * These are filled by 'grfconfig' using GRFIOCSETMON. 139 */ 140 #define monitor_def_max 24 141 static struct grfvideo_mode monitor_def[24] = { 142 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, 143 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, 144 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0} 145 }; 146 static struct grfvideo_mode *monitor_current = &monitor_def[0]; 147 148 /* Console display definition. 149 * Default hardcoded text mode. This grf_et is set up to 150 * use one text mode only, and this is it. You may use 151 * grfconfig to change the mode after boot. 152 */ 153 /* Console font */ 154 #ifdef KFONT_8X11 155 #define TSENGFONT kernel_font_8x11 156 #define TSENGFONTY 11 157 #else 158 #define TSENGFONT kernel_font_8x8 159 #define TSENGFONTY 8 160 #endif 161 extern unsigned char TSENGFONT[]; 162 163 struct grfettext_mode etconsole_mode = { 164 {255, "", 25000000, 640, 480, 4, 640/8, 680/8, 768/8, 800/8, 165 481, 491, 493, 525, 0}, 166 8, TSENGFONTY, 640 / 8, 480 / TSENGFONTY, TSENGFONT, 32, 255 167 }; 168 169 /* Console colors */ 170 unsigned char etconscolors[3][3] = { /* background, foreground, hilite */ 171 {0, 0x40, 0x50}, {152, 152, 152}, {255, 255, 255} 172 }; 173 174 int ettype = 0; /* oMniBus, Domino or Merlin */ 175 int etctype = 0; /* ET4000 or ETW32 */ 176 int etdtype = 0; /* Type of DAC (see grf_etregs.h) */ 177 178 char etcmap_shift = 0; /* 6 or 8 bit cmap entries */ 179 unsigned char pass_toggle; /* passthru status tracker */ 180 181 unsigned char Merlin_switch = 0; 182 183 /* 184 * Because all Tseng-boards have 2 configdev entries, one for 185 * framebuffer mem and the other for regs, we have to hold onto 186 * the pointers globally until we match on both. This and 'ettype' 187 * are the primary obsticles to multiple board support, but if you 188 * have multiple boards you have bigger problems than grf_et. 189 */ 190 static void *et_fbaddr = 0; /* framebuffer */ 191 static void *et_regaddr = 0; /* registers */ 192 static int et_fbsize; /* framebuffer size */ 193 194 /* current sprite info, if you add support for multiple boards 195 * make this an array or something 196 */ 197 struct grf_spriteinfo et_cursprite; 198 199 /* sprite bitmaps in kernel stack, you'll need to arrayize these too if 200 * you add multiple board support 201 */ 202 static unsigned char et_imageptr[8 * 64], et_maskptr[8 * 64]; 203 static unsigned char et_sprred[2], et_sprgreen[2], et_sprblue[2]; 204 205 #if NWSDISPLAY > 0 206 static struct wsdisplay_accessops et_accessops = { 207 .ioctl = et_wsioctl, 208 .mmap = grf_wsmmap 209 }; 210 211 static struct wsdisplay_emulops et_textops = { 212 .cursor = et_wscursor, 213 .mapchar = et_wsmapchar, 214 .putchar = et_wsputchar, 215 .copycols = et_wscopycols, 216 .erasecols = et_wserasecols, 217 .copyrows = et_wscopyrows, 218 .eraserows = et_wseraserows, 219 .allocattr = et_wsallocattr 220 }; 221 222 static struct wsscreen_descr et_defaultscreen = { 223 .name = "default", 224 .textops = &et_textops, 225 .fontwidth = 8, 226 .fontheight = TSENGFONTY, 227 .capabilities = WSSCREEN_HILIT | WSSCREEN_BLINK | 228 WSSCREEN_REVERSE | WSSCREEN_UNDERLINE 229 }; 230 231 static const struct wsscreen_descr *et_screens[] = { 232 &et_defaultscreen, 233 }; 234 235 static struct wsscreen_list et_screenlist = { 236 sizeof(et_screens) / sizeof(struct wsscreen_descr *), et_screens 237 }; 238 #endif /* NWSDISPLAY > 0 */ 239 240 /* standard driver stuff */ 241 CFATTACH_DECL_NEW(grfet, sizeof(struct grf_softc), 242 grfetmatch, grfetattach, NULL, NULL); 243 244 static struct cfdata *cfdata; 245 246 int 247 grfetmatch(device_t parent, cfdata_t cf, void *aux) 248 { 249 struct zbus_args *zap; 250 static int regprod, regprod2 = 0, fbprod; 251 252 zap = aux; 253 254 #ifndef TSENGCONSOLE 255 if (amiga_realconfig == 0) 256 return (0); 257 #endif 258 259 /* Grab the first board we encounter as the preferred one. This will 260 * allow one board to work in a multiple Tseng board system, but not 261 * multiple boards at the same time. */ 262 if (ettype == 0) { 263 switch (zap->manid) { 264 case OMNIBUS: 265 if (zap->prodid != 0) 266 return (0); 267 regprod = 0; 268 fbprod = 0; 269 break; 270 case DOMINO: 271 /* 2167/3 is Domino16M proto (crest) */ 272 if (zap->prodid != 3 && zap->prodid != 2 && zap->prodid != 1) 273 return (0); 274 regprod = 2; 275 regprod2 = 3; 276 fbprod = 1; 277 break; 278 case MERLIN: 279 if (zap->prodid != 3 && zap->prodid != 4) 280 return (0); 281 regprod = 4; 282 fbprod = 3; 283 break; 284 default: 285 return (0); 286 } 287 ettype = zap->manid; 288 } else { 289 if (ettype != zap->manid) { 290 return (0); 291 } 292 } 293 294 /* Configure either registers or framebuffer in any order */ 295 /* as said before, oMniBus does not support ProdID */ 296 if (ettype == OMNIBUS) { 297 if (zap->size == 64 * 1024) { 298 /* register area */ 299 et_regaddr = zap->va; 300 } else { 301 /* memory area */ 302 et_fbaddr = zap->va; 303 et_fbsize = zap->size; 304 } 305 } else { 306 if (zap->prodid == regprod || zap->prodid == regprod2) { 307 et_regaddr = zap->va; 308 } else { 309 if (zap->prodid == fbprod) { 310 et_fbaddr = zap->va; 311 et_fbsize = zap->size; 312 } else { 313 return (0); 314 } 315 } 316 } 317 318 #ifdef TSENGCONSOLE 319 if (amiga_realconfig == 0) { 320 cfdata = cf; 321 } 322 #endif 323 324 return (1); 325 } 326 327 328 void 329 grfetattach(device_t parent, device_t self, void *aux) 330 { 331 static struct grf_softc congrf; 332 static char attachflag = 0; 333 struct device temp; 334 struct grf_softc *gp; 335 336 printf("\n"); 337 338 /* make sure both halves have matched */ 339 if (!et_regaddr || !et_fbaddr) 340 return; 341 342 /* do all that messy console/grf stuff */ 343 if (self == NULL) { 344 gp = &congrf; 345 gp->g_device = &temp; 346 temp.dv_private = gp; 347 } else { 348 gp = device_private(self); 349 gp->g_device = self; 350 } 351 352 if (self != NULL && congrf.g_regkva != 0) { 353 /* 354 * inited earlier, just copy (not device struct) 355 */ 356 memcpy(&gp->g_display, &congrf.g_display, 357 (char *) &gp[1] - (char *) &gp->g_display); 358 } else { 359 gp->g_regkva = (volatile void *) et_regaddr; 360 gp->g_fbkva = (volatile void *) et_fbaddr; 361 362 gp->g_unit = GRF_ET4000_UNIT; 363 gp->g_mode = et_mode; 364 #if NITE > 0 365 gp->g_conpri = grfet_cnprobe(); 366 #endif 367 gp->g_flags = GF_ALIVE; 368 369 /* wakeup the board */ 370 et_boardinit(gp); 371 372 #ifdef TSENGCONSOLE 373 #if NWSDISPLAY > 0 374 gp->g_accessops = &et_accessops; 375 gp->g_emulops = &et_textops; 376 gp->g_defaultscr = &et_defaultscreen; 377 gp->g_scrlist = &et_screenlist; 378 #else 379 #if NITE > 0 380 grfet_iteinit(gp); 381 #endif 382 #endif /* NWSDISPLAY > 0 */ 383 (void) et_load_mon(gp, &etconsole_mode); 384 #endif 385 } 386 387 /* 388 * attach grf (once) 389 */ 390 if (amiga_config_found(cfdata, gp->g_device, gp, grfetprint)) { 391 attachflag = 1; 392 printf("grfet: %dMB ", et_fbsize / 0x100000); 393 switch (ettype) { 394 case OMNIBUS: 395 printf("oMniBus"); 396 break; 397 case DOMINO: 398 printf("Domino"); 399 break; 400 case MERLIN: 401 printf("Merlin"); 402 break; 403 } 404 printf(" with "); 405 switch (etctype) { 406 case ET4000: 407 printf("Tseng ET4000"); 408 break; 409 case ETW32: 410 printf("Tseng ETW32"); 411 break; 412 } 413 printf(" and "); 414 switch (etdtype) { 415 case SIERRA11483: 416 printf("Sierra SC11483 DAC"); 417 break; 418 case SIERRA15025: 419 printf("Sierra SC15025 DAC"); 420 break; 421 case MUSICDAC: 422 printf("MUSIC DAC"); 423 break; 424 case MERLINDAC: 425 printf("BrookTree Bt482 DAC"); 426 break; 427 case ATT20C491: 428 printf("AT&T ATT20c491 DAC"); 429 break; 430 } 431 printf(" being used\n"); 432 } else { 433 if (!attachflag) 434 printf("grfet unattached!!\n"); 435 } 436 } 437 438 439 int 440 grfetprint(void *aux, const char *pnp) 441 { 442 if (pnp) 443 aprint_normal("ite at %s: ", pnp); 444 return (UNCONF); 445 } 446 447 448 void 449 et_boardinit(struct grf_softc *gp) 450 { 451 volatile unsigned char *ba = gp->g_regkva; 452 int x; 453 454 /* wakeup board and flip passthru OFF */ 455 456 RegWakeup(ba); 457 RegOnpass(ba); 458 459 if (ettype == MERLIN) { 460 /* Merlin needs some special initialisations */ 461 vgaw(ba, MERLIN_SWITCH_REG, 0); 462 delay(20000); 463 vgaw(ba, MERLIN_SWITCH_REG, 8); 464 delay(20000); 465 vgaw(ba, MERLIN_SWITCH_REG, 0); 466 delay(20000); 467 vgaw(ba, MERLIN_VDAC_DATA, 1); 468 469 vgaw(ba, MERLIN_VDAC_INDEX, 0x00); 470 vgaw(ba, MERLIN_VDAC_SPRITE, 0xff); 471 vgaw(ba, MERLIN_VDAC_INDEX, 0x01); 472 vgaw(ba, MERLIN_VDAC_SPRITE, 0x0f); 473 vgaw(ba, MERLIN_VDAC_INDEX, 0x02); 474 vgaw(ba, MERLIN_VDAC_SPRITE, 0x42); 475 vgaw(ba, MERLIN_VDAC_INDEX, 0x03); 476 vgaw(ba, MERLIN_VDAC_SPRITE, 0x00); 477 478 vgaw(ba, MERLIN_VDAC_DATA, 0); 479 } 480 481 482 /* setup initial unchanging parameters */ 483 484 vgaw(ba, GREG_HERCULESCOMPAT + ((ettype == DOMINO) ? 0x0fff : 0), 0x03); 485 vgaw(ba, GREG_DISPMODECONTROL, 0xa0); 486 vgaw(ba, GREG_MISC_OUTPUT_W, 0x63); 487 488 if (ettype == DOMINO) 489 { 490 vgaw(ba, CRT_ADDRESS, CRT_ID_VIDEO_CONFIG1); 491 vgaw(ba, CRT_ADDRESS_W + 0x0fff, 492 0xc0 | vgar(ba, CRT_ADDRESS_R + 0x0fff)); 493 } 494 495 WSeq(ba, SEQ_ID_RESET, 0x03); 496 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21); /* 8 dot, Display off */ 497 WSeq(ba, SEQ_ID_MAP_MASK, 0x0f); 498 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); 499 WSeq(ba, SEQ_ID_MEMORY_MODE, 0x0e); 500 WSeq(ba, SEQ_ID_STATE_CONTROL, 0x00); 501 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf4); 502 503 WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00); 504 WCrt(ba, CRT_ID_CURSOR_START, 0x00); 505 WCrt(ba, CRT_ID_CURSOR_END, 0x08); 506 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00); 507 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00); 508 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00); 509 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00); 510 511 WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x67); 512 WCrt(ba, CRT_ID_MODE_CONTROL, 0xc3); 513 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); 514 515 /* ET4000 special */ 516 WCrt(ba, CRT_ID_RASCAS_CONFIG, 0x28); 517 WCrt(ba, CRT_ID_EXT_START, 0x00); 518 WCrt(ba, CRT_ID_6845_COMPAT, 0x08); 519 520 /* ET4000/W32 special (currently only for Merlin (crest) */ 521 if (ettype == MERLIN) { 522 WCrt(ba, CRT_ID_SEGMENT_COMP, 0x1c); 523 WCrt(ba, CRT_ID_GENERAL_PURPOSE, 0x00); 524 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0x93); 525 } 526 else { 527 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xd3); 528 } 529 530 WCrt(ba, CRT_ID_VIDEO_CONFIG2, 0x0f); 531 WCrt(ba, CRT_ID_HOR_OVERFLOW, 0x00); 532 533 vgaw(ba, GREG_SEGMENTSELECT, 0x00); 534 535 WGfx(ba, GCT_ID_SET_RESET, 0x00); 536 WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00); 537 WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00); 538 WGfx(ba, GCT_ID_DATA_ROTATE, 0x00); 539 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00); 540 WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x40); 541 WGfx(ba, GCT_ID_MISC, 0x01); 542 WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f); 543 WGfx(ba, GCT_ID_BITMASK, 0xff); 544 545 for (x = 0; x < 0x10; x++) 546 WAttr(ba, x, x); 547 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x01); 548 WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00); 549 WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f); 550 WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00); 551 WAttr(ba, ACT_ID_COLOR_SELECT, 0x00); 552 WAttr(ba, ACT_ID_MISCELLANEOUS, 0x00); 553 554 vgaw(ba, VDAC_MASK, 0xff); 555 delay(200000); 556 vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3); 557 558 /* colors initially set to greyscale */ 559 switch(ettype) { 560 case MERLIN: 561 vgaw(ba, MERLIN_VDAC_INDEX, 0); 562 for (x = 255; x >= 0; x--) { 563 vgaw(ba, MERLIN_VDAC_COLORS, x); 564 vgaw(ba, MERLIN_VDAC_COLORS, x); 565 vgaw(ba, MERLIN_VDAC_COLORS, x); 566 } 567 break; 568 default: 569 vgaw(ba, VDAC_ADDRESS_W, 0); 570 for (x = 255; x >= 0; x--) { 571 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), x); 572 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), x); 573 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), x); 574 } 575 break; 576 } 577 /* set sprite bitmap pointers */ 578 /* should work like that */ 579 et_cursprite.image = et_imageptr; 580 et_cursprite.mask = et_maskptr; 581 et_cursprite.cmap.red = et_sprred; 582 et_cursprite.cmap.green = et_sprgreen; 583 et_cursprite.cmap.blue = et_sprblue; 584 585 /* card specific initialisations */ 586 switch(ettype) { 587 case OMNIBUS: 588 etctype = et_getControllerType(gp); 589 etdtype = et_getDACType(gp); 590 break; 591 case MERLIN: 592 vgaw(ba, GREG_SEGMENTSELECT2, 0x00); 593 if (((vgar(ba, GREG_FEATURE_CONTROL_R) & 12) | 594 (vgar(ba, GREG_STATUS0_R) & 0x60)) == 0x24) { 595 WCrt(ba, CRT_ID_VIDEO_CONFIG2, 0x07); /* 1Mx4 RAM */ 596 et_fbsize = 0x400000; /* 4 MB */ 597 } 598 else { 599 /* check for 1MB or 2MB board (crest) */ 600 /* has there a 1MB Merlin ever been sold ??? */ 601 volatile unsigned long *et_fbtestaddr; 602 et_fbtestaddr = (volatile unsigned long *)gp->g_fbkva; 603 *et_fbtestaddr = 0x0; 604 vgaw(ba, GREG_SEGMENTSELECT2, 0x11); /* 1MB offset */ 605 *et_fbtestaddr = 0x12345678; 606 vgaw(ba, GREG_SEGMENTSELECT2, 0x00); 607 if (*et_fbtestaddr == 0x0) 608 et_fbsize = 0x200000; /* 2 MB */ 609 else 610 et_fbsize = 0x100000; /* 1 MB */ 611 } 612 /* ZorroII can map 2 MB max ... */ 613 if (!iszthreepa(kvtop(__UNVOLATILE(gp->g_fbkva))) && 614 et_fbsize == 0x400000) 615 et_fbsize = 0x200000; 616 etctype = ETW32; 617 etdtype = MERLINDAC; 618 break; 619 case DOMINO: 620 etctype = ET4000; 621 etdtype = et_getDACType(gp); 622 break; 623 } 624 } 625 626 627 int 628 et_getvmode(struct grf_softc *gp, struct grfvideo_mode *vm) 629 { 630 struct grfvideo_mode *gv; 631 632 #ifdef TSENGCONSOLE 633 /* Handle grabbing console mode */ 634 if (vm->mode_num == 255) { 635 memcpy(vm, &etconsole_mode, sizeof(struct grfvideo_mode)); 636 /* XXX so grfconfig can tell us the correct text dimensions. */ 637 vm->depth = etconsole_mode.fy; 638 } else 639 #endif 640 { 641 if (vm->mode_num == 0) 642 vm->mode_num = (monitor_current - monitor_def) + 1; 643 if (vm->mode_num < 1 || vm->mode_num > monitor_def_max) 644 return (EINVAL); 645 gv = monitor_def + (vm->mode_num - 1); 646 if (gv->mode_num == 0) 647 return (EINVAL); 648 649 memcpy(vm, gv, sizeof(struct grfvideo_mode)); 650 } 651 652 /* adjust internal values to pixel values */ 653 654 vm->hblank_start *= 8; 655 vm->hsync_start *= 8; 656 vm->hsync_stop *= 8; 657 vm->htotal *= 8; 658 659 return (0); 660 } 661 662 663 int 664 et_setvmode(struct grf_softc *gp, unsigned mode) 665 { 666 if (!mode || (mode > monitor_def_max) || 667 monitor_def[mode - 1].mode_num == 0) 668 return (EINVAL); 669 670 monitor_current = monitor_def + (mode - 1); 671 672 return (0); 673 } 674 675 676 #ifndef TSENGCONSOLE 677 void 678 et_off(struct grf_softc *gp) 679 { 680 char *ba = gp->g_regkva; 681 682 RegOnpass(ba); 683 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21); 684 } 685 #endif 686 687 688 int 689 et_blank(struct grf_softc *gp, int on) 690 { 691 692 WSeq(gp->g_regkva, SEQ_ID_CLOCKING_MODE, on > 0 ? 0x01 : 0x21); 693 return 0; 694 } 695 696 697 int 698 et_isblank(struct grf_softc *gp) 699 { 700 int r; 701 702 r = RSeq(gp->g_regkva, SEQ_ID_CLOCKING_MODE); 703 return (r & 0x20) != 0; 704 } 705 706 707 /* 708 * Change the mode of the display. 709 * Return a UNIX error number or 0 for success. 710 */ 711 int 712 et_mode(register struct grf_softc *gp, u_long cmd, void *arg, u_long a2, 713 int a3) 714 { 715 int error; 716 717 switch (cmd) { 718 case GM_GRFON: 719 error = et_load_mon(gp, 720 (struct grfettext_mode *) monitor_current) ? 0 : EINVAL; 721 return (error); 722 723 case GM_GRFOFF: 724 #ifndef TSENGCONSOLE 725 et_off(gp); 726 #else 727 et_load_mon(gp, &etconsole_mode); 728 #endif 729 return (0); 730 731 case GM_GRFCONFIG: 732 return (0); 733 734 case GM_GRFGETVMODE: 735 return (et_getvmode(gp, (struct grfvideo_mode *) arg)); 736 737 case GM_GRFSETVMODE: 738 error = et_setvmode(gp, *(unsigned *) arg); 739 if (!error && (gp->g_flags & GF_GRFON)) 740 et_load_mon(gp, 741 (struct grfettext_mode *) monitor_current); 742 return (error); 743 744 case GM_GRFGETNUMVM: 745 *(int *) arg = monitor_def_max; 746 return (0); 747 748 case GM_GRFIOCTL: 749 return (et_ioctl(gp, a2, arg)); 750 751 default: 752 break; 753 } 754 755 return (EPASSTHROUGH); 756 } 757 758 759 int 760 et_ioctl(register struct grf_softc *gp, u_long cmd, void *data) 761 { 762 switch (cmd) { 763 case GRFIOCGSPRITEPOS: 764 return (et_getmousepos(gp, (struct grf_position *) data)); 765 766 case GRFIOCSSPRITEPOS: 767 return (et_setmousepos(gp, (struct grf_position *) data)); 768 769 case GRFIOCSSPRITEINF: 770 return (et_setspriteinfo(gp, (struct grf_spriteinfo *) data)); 771 772 case GRFIOCGSPRITEINF: 773 return (et_getspriteinfo(gp, (struct grf_spriteinfo *) data)); 774 775 case GRFIOCGSPRITEMAX: 776 return (et_getspritemax(gp, (struct grf_position *) data)); 777 778 case GRFIOCGETCMAP: 779 return (et_getcmap(gp, (struct grf_colormap *) data)); 780 781 case GRFIOCPUTCMAP: 782 return (et_putcmap(gp, (struct grf_colormap *) data)); 783 784 case GRFIOCBITBLT: 785 break; 786 787 case GRFTOGGLE: 788 return (et_toggle(gp, 0)); 789 790 case GRFIOCSETMON: 791 return (et_setmonitor(gp, (struct grfvideo_mode *) data)); 792 793 case GRFIOCBLANK: 794 return (et_blank(gp, *(int *)data)); 795 } 796 return (EPASSTHROUGH); 797 } 798 799 800 int 801 et_getmousepos(struct grf_softc *gp, struct grf_position *data) 802 { 803 data->x = et_cursprite.pos.x; 804 data->y = et_cursprite.pos.y; 805 806 return (0); 807 } 808 809 810 void 811 et_writesprpos(volatile char *ba, short x, short y) 812 { 813 } 814 815 816 int 817 et_setmousepos(struct grf_softc *gp, struct grf_position *data) 818 { 819 volatile char *ba = gp->g_regkva; 820 short rx, ry; 821 822 /* no movement */ 823 if (et_cursprite.pos.x == data->x && et_cursprite.pos.y == data->y) 824 return (0); 825 826 /* current and previous real coordinates */ 827 rx = data->x - et_cursprite.hot.x; 828 ry = data->y - et_cursprite.hot.y; 829 830 /* if we are/were on an edge, create (un)shifted bitmap -- 831 * ripped out optimization (not extremely worthwhile, 832 * and kind of buggy anyhow). 833 */ 834 835 /* do movement, save position */ 836 et_writesprpos(ba, rx < 0 ? 0 : rx, ry < 0 ? 0 : ry); 837 et_cursprite.pos.x = data->x; 838 et_cursprite.pos.y = data->y; 839 840 return (0); 841 } 842 843 844 int 845 et_getspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *data) 846 { 847 848 return(EINVAL); 849 } 850 851 852 static int 853 et_setspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *data) 854 { 855 856 return(EINVAL); 857 } 858 859 860 static int 861 et_getspritemax(struct grf_softc *gp, struct grf_position *data) 862 { 863 864 return(EINVAL); 865 } 866 867 868 int 869 et_setmonitor(struct grf_softc *gp, struct grfvideo_mode *gv) 870 { 871 struct grfvideo_mode *md; 872 873 if (!et_mondefok(gv)) 874 return(EINVAL); 875 876 #ifdef TSENGCONSOLE 877 /* handle interactive setting of console mode */ 878 if (gv->mode_num == 255) { 879 memcpy(&etconsole_mode.gv, gv, sizeof(struct grfvideo_mode)); 880 etconsole_mode.gv.hblank_start /= 8; 881 etconsole_mode.gv.hsync_start /= 8; 882 etconsole_mode.gv.hsync_stop /= 8; 883 etconsole_mode.gv.htotal /= 8; 884 etconsole_mode.rows = gv->disp_height / etconsole_mode.fy; 885 etconsole_mode.cols = gv->disp_width / etconsole_mode.fx; 886 if (!(gp->g_flags & GF_GRFON)) 887 et_load_mon(gp, &etconsole_mode); 888 #if NITE > 0 889 ite_reinit(gp->g_itedev); 890 #endif 891 return (0); 892 } 893 #endif 894 895 md = monitor_def + (gv->mode_num - 1); 896 memcpy(md, gv, sizeof(struct grfvideo_mode)); 897 898 /* adjust pixel oriented values to internal rep. */ 899 900 md->hblank_start /= 8; 901 md->hsync_start /= 8; 902 md->hsync_stop /= 8; 903 md->htotal /= 8; 904 905 return (0); 906 } 907 908 909 int 910 et_getcmap(struct grf_softc *gfp, struct grf_colormap *cmap) 911 { 912 volatile unsigned char *ba; 913 u_char red[256], green[256], blue[256], *rp, *gp, *bp; 914 short x; 915 int error; 916 917 if (cmap->count == 0 || cmap->index >= 256) 918 return 0; 919 920 if (cmap->count > 256 - cmap->index) 921 cmap->count = 256 - cmap->index; 922 923 ba = gfp->g_regkva; 924 /* first read colors out of the chip, then copyout to userspace */ 925 x = cmap->count - 1; 926 927 rp = red + cmap->index; 928 gp = green + cmap->index; 929 bp = blue + cmap->index; 930 931 switch(ettype) { 932 case MERLIN: 933 vgaw(ba, MERLIN_VDAC_INDEX, cmap->index); 934 do { 935 *rp++ = vgar(ba, MERLIN_VDAC_COLORS); 936 *gp++ = vgar(ba, MERLIN_VDAC_COLORS); 937 *bp++ = vgar(ba, MERLIN_VDAC_COLORS); 938 } while (x-- > 0); 939 break; 940 default: 941 vgaw(ba, VDAC_ADDRESS_R+((ettype==DOMINO)?0x0fff:0), cmap->index); 942 do { 943 *rp++ = vgar(ba, VDAC_DATA+((ettype==DOMINO)?0x0fff:0)) << etcmap_shift; 944 *gp++ = vgar(ba, VDAC_DATA+((ettype==DOMINO)?0x0fff:0)) << etcmap_shift; 945 *bp++ = vgar(ba, VDAC_DATA+((ettype==DOMINO)?0x0fff:0)) << etcmap_shift; 946 } while (x-- > 0); 947 break; 948 } 949 950 error = copyout(red + cmap->index, cmap->red, cmap->count); 951 if (!error) 952 error = copyout(green + cmap->index, cmap->green, cmap->count); 953 if (!error) 954 error = copyout(blue + cmap->index, cmap->blue, cmap->count); 955 956 return (error); 957 } 958 959 960 int 961 et_putcmap(struct grf_softc *gfp, struct grf_colormap *cmap) 962 { 963 volatile unsigned char *ba; 964 u_char red[256], green[256], blue[256], *rp, *gp, *bp; 965 short x; 966 int error; 967 968 if (cmap->count == 0 || cmap->index >= 256) 969 return (0); 970 971 if (cmap->count > 256 - cmap->index) 972 cmap->count = 256 - cmap->index; 973 974 /* first copy the colors into kernelspace */ 975 if ((error = copyin(cmap->red, red + cmap->index, cmap->count))) 976 return (error); 977 978 if ((error = copyin(cmap->green, green + cmap->index, cmap->count))) 979 return (error); 980 981 if ((error = copyin(cmap->blue, blue + cmap->index, cmap->count))) 982 return (error); 983 984 ba = gfp->g_regkva; 985 x = cmap->count - 1; 986 987 rp = red + cmap->index; 988 gp = green + cmap->index; 989 bp = blue + cmap->index; 990 991 switch(ettype){ 992 case MERLIN: 993 vgaw(ba, MERLIN_VDAC_INDEX, cmap->index); 994 do { 995 vgaw(ba, MERLIN_VDAC_COLORS, *rp++); 996 vgaw(ba, MERLIN_VDAC_COLORS, *gp++); 997 vgaw(ba, MERLIN_VDAC_COLORS, *bp++); 998 } while (x-- > 0); 999 break; 1000 default: 1001 vgaw(ba, VDAC_ADDRESS_W, cmap->index); 1002 do { 1003 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), 1004 *rp++ >> etcmap_shift); 1005 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), 1006 *gp++ >> etcmap_shift); 1007 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), 1008 *bp++ >> etcmap_shift); 1009 } while (x-- > 0); 1010 break; 1011 } 1012 1013 return (0); 1014 } 1015 1016 1017 int 1018 et_toggle(struct grf_softc *gp, unsigned short wopp) 1019 /* (variable wopp) don't need that one yet, ill */ 1020 { 1021 volatile unsigned char *ba; 1022 1023 ba = gp->g_regkva; 1024 1025 if (pass_toggle) { 1026 RegOffpass(ba); 1027 } else { 1028 RegOnpass(ba); 1029 } 1030 return (0); 1031 } 1032 1033 1034 #define ET_NUMCLOCKS 32 1035 1036 static u_char et_clocks[ET_NUMCLOCKS] = { 1037 0, 1, 6, 2, 3, 7, 4, 5, 1038 0, 1, 6, 2, 3, 7, 4, 5, 1039 0, 1, 6, 2, 3, 7, 4, 5, 1040 0, 1, 6, 2, 3, 7, 4, 5 1041 }; 1042 1043 static u_char et_clockdividers[ET_NUMCLOCKS] = { 1044 3, 3, 3, 3, 3, 3, 3, 3, 1045 2, 2, 2, 2, 2, 2, 2, 2, 1046 1, 1, 1, 1, 1, 1, 1, 1, 1047 0, 0, 0, 0, 0, 0, 0, 0 1048 }; 1049 1050 static u_int et_clockfreqs[ET_NUMCLOCKS] = { 1051 6293750, 7080500, 7875000, 8125000, 1052 9000000, 9375000, 10000000, 11225000, 1053 12587500, 14161000, 15750000, 16250000, 1054 18000000, 18750000, 20000000, 22450000, 1055 25175000, 28322000, 31500000, 32500000, 1056 36000000, 37500000, 40000000, 44900000, 1057 50350000, 56644000, 63000000, 65000000, 1058 72000000, 75000000, 80000000, 89800000 1059 }; 1060 1061 1062 static void 1063 et_CompFQ(u_int fq, u_char *num, u_char *denom) 1064 { 1065 int i; 1066 1067 for (i=0; i < ET_NUMCLOCKS;) { 1068 if (fq <= et_clockfreqs[i++]) { 1069 break; 1070 } 1071 } 1072 1073 *num = et_clocks[--i]; 1074 *denom = et_clockdividers[i]; 1075 1076 return; 1077 } 1078 1079 1080 int 1081 et_mondefok(struct grfvideo_mode *gv) 1082 { 1083 unsigned long maxpix; 1084 1085 if (gv->mode_num < 1 || gv->mode_num > monitor_def_max) 1086 if (gv->mode_num != 255 || gv->depth != 4) 1087 return(0); 1088 1089 switch (gv->depth) { 1090 case 4: 1091 if (gv->mode_num != 255) 1092 return(0); 1093 case 1: 1094 case 8: 1095 maxpix = 85000000; 1096 break; 1097 case 15: 1098 case 16: 1099 maxpix = 45000000; 1100 break; 1101 case 24: 1102 maxpix = 28000000; 1103 break; 1104 case 32: 1105 maxpix = 21000000; 1106 break; 1107 default: 1108 printf("grfet: Illegal depth in mode %d\n", 1109 (int) gv->mode_num); 1110 return (0); 1111 } 1112 1113 if (gv->pixel_clock > maxpix) { 1114 printf("grfet: Pixelclock too high in mode %d\n", 1115 (int) gv->mode_num); 1116 return (0); 1117 } 1118 1119 if (gv->disp_flags & GRF_FLAGS_SYNC_ON_GREEN) { 1120 printf("grfet: sync-on-green is not supported\n"); 1121 return (0); 1122 } 1123 1124 return (1); 1125 } 1126 1127 1128 int 1129 et_load_mon(struct grf_softc *gp, struct grfettext_mode *md) 1130 { 1131 struct grfvideo_mode *gv; 1132 struct grfinfo *gi; 1133 volatile unsigned char *ba; 1134 unsigned char num0, denom0; 1135 unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS, 1136 VSE, VT; 1137 unsigned char hvsync_pulse, seq; 1138 char TEXT; 1139 int hmul; 1140 1141 /* identity */ 1142 gv = &md->gv; 1143 TEXT = (gv->depth == 4); 1144 1145 if (!et_mondefok(gv)) { 1146 printf("grfet: Monitor definition not ok\n"); 1147 return (0); 1148 } 1149 1150 ba = gp->g_regkva; 1151 1152 /* provide all needed information in grf device-independent locations */ 1153 gp->g_data = (void *) gv; 1154 gi = &gp->g_display; 1155 gi->gd_regaddr = ztwopa(__UNVOLATILE(ba)); 1156 gi->gd_regsize = 64 * 1024; 1157 gi->gd_fbaddr = (void *) kvtop(__UNVOLATILE(gp->g_fbkva)); 1158 gi->gd_fbsize = et_fbsize; 1159 gi->gd_colors = 1 << gv->depth; 1160 gi->gd_planes = gv->depth; 1161 gi->gd_fbwidth = gv->disp_width; 1162 gi->gd_fbheight = gv->disp_height; 1163 gi->gd_fbx = 0; 1164 gi->gd_fby = 0; 1165 if (TEXT) { 1166 gi->gd_dwidth = md->fx * md->cols; 1167 gi->gd_dheight = md->fy * md->rows; 1168 } else { 1169 gi->gd_dwidth = gv->disp_width; 1170 gi->gd_dheight = gv->disp_height; 1171 } 1172 gi->gd_dx = 0; 1173 gi->gd_dy = 0; 1174 1175 /* get display mode parameters */ 1176 1177 HBS = gv->hblank_start; 1178 HSS = gv->hsync_start; 1179 HSE = gv->hsync_stop; 1180 HBE = gv->htotal - 1; 1181 HT = gv->htotal; 1182 VBS = gv->vblank_start; 1183 VSS = gv->vsync_start; 1184 VSE = gv->vsync_stop; 1185 VBE = gv->vtotal - 1; 1186 VT = gv->vtotal; 1187 1188 if (TEXT) 1189 HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1; 1190 else 1191 HDE = (gv->disp_width + 3) / 8 - 1; /* HBS; */ 1192 VDE = gv->disp_height - 1; 1193 1194 /* adjustments (crest) */ 1195 switch (gv->depth) { 1196 case 15: 1197 case 16: 1198 hmul = 2; 1199 break; 1200 case 24: 1201 hmul = 3; 1202 break; 1203 case 32: 1204 hmul = 4; 1205 break; 1206 default: 1207 hmul = 1; 1208 break; 1209 } 1210 1211 HDE *= hmul; 1212 HBS *= hmul; 1213 HSS *= hmul; 1214 HSE *= hmul; 1215 HBE *= hmul; 1216 HT *= hmul; 1217 1218 if (gv->disp_flags & GRF_FLAGS_LACE) { 1219 VDE /= 2; 1220 VT = VT + 1; 1221 } 1222 1223 if (gv->disp_flags & GRF_FLAGS_DBLSCAN) { 1224 VDE *= 2; 1225 VBS *= 2; 1226 VSS *= 2; 1227 VSE *= 2; 1228 VBE *= 2; 1229 VT *= 2; 1230 } 1231 1232 WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e); 1233 1234 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00); 1235 WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff); 1236 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); 1237 1238 /* Set clock */ 1239 et_CompFQ( gv->pixel_clock * hmul, &num0, &denom0); 1240 1241 /* Horizontal/Vertical Sync Pulse */ 1242 hvsync_pulse = 0xe3; 1243 if (gv->disp_flags & GRF_FLAGS_PHSYNC) 1244 hvsync_pulse &= ~0x40; 1245 else 1246 hvsync_pulse |= 0x40; 1247 if (gv->disp_flags & GRF_FLAGS_PVSYNC) 1248 hvsync_pulse &= ~0x80; 1249 else 1250 hvsync_pulse |= 0x80; 1251 1252 vgaw(ba, GREG_MISC_OUTPUT_W, hvsync_pulse | ((num0 & 3) << 2)); 1253 WCrt(ba, CRT_ID_6845_COMPAT, (num0 & 4) ? 0x0a : 0x08); 1254 seq = RSeq(ba, SEQ_ID_CLOCKING_MODE); 1255 switch(denom0) { 1256 case 0: 1257 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xb4); 1258 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7); 1259 break; 1260 case 1: 1261 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf4); 1262 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7); 1263 break; 1264 case 2: 1265 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5); 1266 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7); 1267 break; 1268 case 3: 1269 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5); 1270 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq | 0x08); 1271 break; 1272 } 1273 1274 /* load display parameters into board */ 1275 WCrt(ba, CRT_ID_HOR_TOTAL, HT); 1276 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? HBS - 1 : HDE)); 1277 WCrt(ba, CRT_ID_START_HOR_BLANK, HBS); 1278 WCrt(ba, CRT_ID_END_HOR_BLANK, (HBE & 0x1f) | 0x80); 1279 WCrt(ba, CRT_ID_START_HOR_RETR, HSS); 1280 WCrt(ba, CRT_ID_END_HOR_RETR, 1281 (HSE & 0x1f) | 1282 ((HBE & 0x20) ? 0x80 : 0x00)); 1283 WCrt(ba, CRT_ID_VER_TOTAL, VT); 1284 WCrt(ba, CRT_ID_OVERFLOW, 1285 0x10 | 1286 ((VT & 0x100) ? 0x01 : 0x00) | 1287 ((VDE & 0x100) ? 0x02 : 0x00) | 1288 ((VSS & 0x100) ? 0x04 : 0x00) | 1289 ((VBS & 0x100) ? 0x08 : 0x00) | 1290 ((VT & 0x200) ? 0x20 : 0x00) | 1291 ((VDE & 0x200) ? 0x40 : 0x00) | 1292 ((VSS & 0x200) ? 0x80 : 0x00)); 1293 1294 WCrt(ba, CRT_ID_MAX_ROW_ADDRESS, 1295 0x40 | /* splitscreen not visible */ 1296 ((gv->disp_flags & GRF_FLAGS_DBLSCAN) ? 0x80 : 0x00) | 1297 ((VBS & 0x200) ? 0x20 : 0x00) | 1298 (TEXT ? ((md->fy - 1) & 0x1f) : 0x00)); 1299 1300 WCrt(ba, CRT_ID_MODE_CONTROL, 1301 ((TEXT || (gv->depth == 1)) ? 0xc3 : 0xab)); 1302 1303 /* text cursor */ 1304 if (TEXT) { 1305 #if ET_ULCURSOR 1306 WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2); 1307 WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1); 1308 #else 1309 WCrt(ba, CRT_ID_CURSOR_START, 0x00); 1310 WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f); 1311 #endif 1312 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00); 1313 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00); 1314 } 1315 1316 WCrt(ba, CRT_ID_UNDERLINE_LOC, ((md->fy - 1) & 0x1f) 1317 | ((TEXT || (gv->depth == 1)) ? 0x00 : 0x60)); 1318 1319 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00); 1320 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00); 1321 1322 WCrt(ba, CRT_ID_START_VER_RETR, VSS); 1323 WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f) | 0x30); 1324 WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE); 1325 WCrt(ba, CRT_ID_START_VER_BLANK, VBS); 1326 WCrt(ba, CRT_ID_END_VER_BLANK, VBE); 1327 1328 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); 1329 1330 WCrt(ba, CRT_ID_OVERFLOW_HIGH, 1331 ((VBS & 0x400) ? 0x01 : 0x00) | 1332 ((VT & 0x400) ? 0x02 : 0x00) | 1333 ((VDE & 0x400) ? 0x04 : 0x00) | 1334 ((VSS & 0x400) ? 0x08 : 0x00) | 1335 0x10 | 1336 ((gv->disp_flags & GRF_FLAGS_LACE) ? 0x80 : 0x00)); 1337 1338 WCrt(ba, CRT_ID_HOR_OVERFLOW, 1339 ((HT & 0x100) ? 0x01 : 0x00) | 1340 ((HBS & 0x100) ? 0x04 : 0x00) | 1341 ((HSS & 0x100) ? 0x10 : 0x00) 1342 ); 1343 1344 /* depth dependent stuff */ 1345 1346 WGfx(ba, GCT_ID_GRAPHICS_MODE, 1347 ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40)); 1348 WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01)); 1349 1350 vgaw(ba, VDAC_MASK, 0xff); 1351 vgar(ba, VDAC_MASK); 1352 vgar(ba, VDAC_MASK); 1353 vgar(ba, VDAC_MASK); 1354 vgar(ba, VDAC_MASK); 1355 switch (gv->depth) { 1356 case 1: 1357 case 4: /* text */ 1358 switch(etdtype) { 1359 case SIERRA11483: 1360 case SIERRA15025: 1361 case MUSICDAC: 1362 vgaw(ba, VDAC_MASK, 0); 1363 break; 1364 case ATT20C491: 1365 vgaw(ba, VDAC_MASK, 0x02); 1366 break; 1367 case MERLINDAC: 1368 setMerlinDACmode(ba, 0); 1369 break; 1370 } 1371 HDE = gv->disp_width / 16; 1372 break; 1373 case 8: 1374 switch(etdtype) { 1375 case SIERRA11483: 1376 case SIERRA15025: 1377 case MUSICDAC: 1378 vgaw(ba, VDAC_MASK, 0); 1379 break; 1380 case ATT20C491: 1381 vgaw(ba, VDAC_MASK, 0x02); 1382 break; 1383 case MERLINDAC: 1384 setMerlinDACmode(ba, 0); 1385 break; 1386 } 1387 HDE = gv->disp_width / 8; 1388 break; 1389 case 15: 1390 switch(etdtype) { 1391 case SIERRA11483: 1392 case SIERRA15025: 1393 case MUSICDAC: 1394 case ATT20C491: 1395 vgaw(ba, VDAC_MASK, 0xa0); 1396 break; 1397 case MERLINDAC: 1398 setMerlinDACmode(ba, 0xa0); 1399 break; 1400 } 1401 HDE = gv->disp_width / 4; 1402 break; 1403 case 16: 1404 switch(etdtype) { 1405 case SIERRA11483: 1406 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */ 1407 break; 1408 case SIERRA15025: 1409 vgaw(ba, VDAC_MASK, 0xe0); 1410 break; 1411 case MUSICDAC: 1412 case ATT20C491: 1413 vgaw(ba, VDAC_MASK, 0xc0); 1414 break; 1415 case MERLINDAC: 1416 setMerlinDACmode(ba, 0xe0); 1417 break; 1418 } 1419 HDE = gv->disp_width / 4; 1420 break; 1421 case 24: 1422 switch(etdtype) { 1423 case SIERRA11483: 1424 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */ 1425 break; 1426 case SIERRA15025: 1427 vgaw(ba, VDAC_MASK, 0xe1); 1428 break; 1429 case MUSICDAC: 1430 case ATT20C491: 1431 vgaw(ba, VDAC_MASK, 0xe0); 1432 break; 1433 case MERLINDAC: 1434 setMerlinDACmode(ba, 0xf0); 1435 break; 1436 } 1437 HDE = (gv->disp_width / 8) * 3; 1438 break; 1439 case 32: 1440 switch(etdtype) { 1441 case SIERRA11483: 1442 case MUSICDAC: 1443 case ATT20C491: 1444 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */ 1445 break; 1446 case SIERRA15025: 1447 vgaw(ba, VDAC_MASK, 0x61); 1448 break; 1449 case MERLINDAC: 1450 setMerlinDACmode(ba, 0xb0); 1451 break; 1452 } 1453 HDE = gv->disp_width / 2; 1454 break; 1455 } 1456 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x0a : 0x01)); 1457 WAttr(ba, 0x20 | ACT_ID_COLOR_PLANE_ENA, 1458 (gv->depth == 1) ? 0x01 : 0x0f); 1459 1460 WCrt(ba, CRT_ID_OFFSET, HDE); 1461 vgaw(ba, CRT_ADDRESS, CRT_ID_HOR_OVERFLOW); 1462 vgaw(ba, CRT_ADDRESS_W, 1463 (vgar(ba, CRT_ADDRESS_R) & 0x7f) 1464 | ((HDE & 0x100) ? 0x80: 0x00)); 1465 1466 /* text initialization */ 1467 if (TEXT) { 1468 et_inittextmode(gp); 1469 } 1470 1471 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01); 1472 1473 /* Pass-through */ 1474 RegOffpass(ba); 1475 1476 return (1); 1477 } 1478 1479 1480 void 1481 et_inittextmode(struct grf_softc *gp) 1482 { 1483 struct grfettext_mode *tm = (struct grfettext_mode *) gp->g_data; 1484 volatile unsigned char *ba = gp->g_regkva; 1485 volatile unsigned char *fb = gp->g_fbkva; 1486 volatile unsigned char *c; 1487 unsigned char *f, y; 1488 unsigned short z; 1489 1490 1491 /* 1492 * load text font into beginning of display memory. Each character 1493 * cell is 32 bytes long (enough for 4 planes) 1494 */ 1495 1496 SetTextPlane(ba, 0x02); 1497 et_memset(fb, 0, 256 * 32); 1498 c = fb + (32 * tm->fdstart); 1499 f = tm->fdata; 1500 for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy)) 1501 for (y = 0; y < tm->fy; y++) 1502 *c++ = *f++; 1503 1504 /* clear out text/attr planes (three screens worth) */ 1505 1506 SetTextPlane(ba, 0x01); 1507 et_memset(fb, 0x07, tm->cols * tm->rows * 3); 1508 SetTextPlane(ba, 0x00); 1509 et_memset(fb, 0x20, tm->cols * tm->rows * 3); 1510 1511 /* print out a little init msg */ 1512 1513 c = fb + (tm->cols - 16); 1514 strcpy(__UNVOLATILE(c), "TSENG"); 1515 c[5] = 0x20; 1516 1517 /* set colors (B&W) */ 1518 1519 switch(ettype) { 1520 case MERLIN: 1521 vgaw(ba, MERLIN_VDAC_INDEX, 0); 1522 for (z = 0; z < 256; z++) { 1523 y = (z & 1) ? ((z > 7) ? 2 : 1) : 0; 1524 1525 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][0]); 1526 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][1]); 1527 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][2]); 1528 } 1529 break; 1530 default: 1531 vgaw(ba, VDAC_ADDRESS_W, 0); 1532 for (z = 0; z < 256; z++) { 1533 y = (z & 1) ? ((z > 7) ? 2 : 1) : 0; 1534 1535 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), 1536 etconscolors[y][0] >> etcmap_shift); 1537 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), 1538 etconscolors[y][1] >> etcmap_shift); 1539 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), 1540 etconscolors[y][2] >> etcmap_shift); 1541 } 1542 break; 1543 } 1544 } 1545 1546 1547 void 1548 et_memset(volatile unsigned char *d, unsigned char c, int l) 1549 { 1550 for (; l > 0; l--) 1551 *d++ = c; 1552 } 1553 1554 1555 static int 1556 et_getControllerType(struct grf_softc *gp) 1557 { 1558 volatile unsigned char *ba = gp->g_regkva; /* register base */ 1559 volatile unsigned char *mem = gp->g_fbkva; /* memory base */ 1560 volatile unsigned char *mmu = mem + MMU_APERTURE0; /* MMU aperture 0 base */ 1561 1562 *mem = 0; 1563 1564 /* make ACL visible */ 1565 if (ettype == MERLIN) { 1566 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xbb); 1567 } else { 1568 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xfb); 1569 } 1570 1571 WIma(ba, IMA_PORTCONTROL, 0x01); 1572 1573 *((volatile unsigned long *)mmu) = 0; 1574 *(mem + 0x13) = 0x38; 1575 1576 *mmu = 0xff; 1577 1578 /* hide ACL */ 1579 WIma(ba, IMA_PORTCONTROL, 0x00); 1580 1581 if (ettype == MERLIN) { 1582 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0x93); 1583 } else { 1584 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xd3); 1585 } 1586 return ((*mem == 0xff) ? ETW32 : ET4000); 1587 } 1588 1589 1590 static int 1591 et_getDACType(struct grf_softc *gp) 1592 { 1593 volatile unsigned char *ba = gp->g_regkva; 1594 union { 1595 int tt; 1596 char cc[4]; 1597 } check; 1598 1599 /* check for Sierra SC 15025 */ 1600 1601 /* We MUST do 4 HW reads to switch into command mode */ 1602 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); 1603 vgaw(ba, VDAC_COMMAND, 0x10); /* set ERPF */ 1604 1605 vgaw(ba, VDAC_XINDEX, 9); 1606 check.cc[0] = vgar(ba, VDAC_XDATA); 1607 vgaw(ba, VDAC_XINDEX, 10); 1608 check.cc[1] = vgar(ba, VDAC_XDATA); 1609 vgaw(ba, VDAC_XINDEX, 11); 1610 check.cc[2] = vgar(ba, VDAC_XDATA); 1611 vgaw(ba, VDAC_XINDEX, 12); 1612 check.cc[3] = vgar(ba, VDAC_XDATA); 1613 1614 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); 1615 vgaw(ba, VDAC_COMMAND, 0x00); /* clear ERPF */ 1616 1617 if (check.tt == 0x533ab141) { 1618 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); 1619 vgaw(ba, VDAC_COMMAND, 0x10); /* set ERPF */ 1620 1621 /* switch to 8 bits per color */ 1622 vgaw(ba, VDAC_XINDEX, 8); 1623 vgaw(ba, VDAC_XDATA, 1); 1624 /* do not shift color values */ 1625 etcmap_shift = 0; 1626 1627 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); 1628 vgaw(ba, VDAC_COMMAND, 0x00); /* clear ERPF */ 1629 1630 vgaw(ba, VDAC_MASK, 0xff); 1631 return (SIERRA15025); 1632 } 1633 1634 /* check for MUSIC DAC */ 1635 1636 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); 1637 vgaw(ba, VDAC_COMMAND, 0x02); /* set some strange MUSIC mode (???) */ 1638 1639 vgaw(ba, VDAC_XINDEX, 0x01); 1640 if (vgar(ba, VDAC_XDATA) == 0x01) { 1641 /* shift color values by 2 */ 1642 etcmap_shift = 2; 1643 1644 vgaw(ba, VDAC_MASK, 0xff); 1645 return (MUSICDAC); 1646 } 1647 1648 /* check for AT&T ATT20c491 DAC (crest) */ 1649 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); 1650 vgaw(ba, HDR, 0xff); 1651 vgaw(ba, VDAC_MASK, 0x01); 1652 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); 1653 if (vgar(ba, HDR) == 0xff) { 1654 /* do not shift color values */ 1655 etcmap_shift = 0; 1656 1657 vgaw(ba, VDAC_MASK, 0xff); 1658 return (ATT20C491); 1659 } 1660 1661 /* restore PowerUp settings (crest) */ 1662 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); 1663 vgaw(ba, HDR, 0x00); 1664 1665 /* 1666 * nothing else found, so let us pretend it is a stupid 1667 * Sierra SC 11483 1668 */ 1669 1670 /* shift color values by 2 */ 1671 etcmap_shift = 2; 1672 1673 vgaw(ba, VDAC_MASK, 0xff); 1674 return (SIERRA11483); 1675 } 1676 1677 1678 #if NWSDISPLAY > 0 1679 static void 1680 et_wscursor(void *c, int on, int row, int col) 1681 { 1682 struct rasops_info *ri; 1683 struct vcons_screen *scr; 1684 struct grf_softc *gp; 1685 volatile void *ba; 1686 int offs; 1687 1688 ri = c; 1689 scr = ri->ri_hw; 1690 gp = scr->scr_cookie; 1691 ba = gp->g_regkva; 1692 1693 if ((ri->ri_flg & RI_CURSOR) && !on) { 1694 /* cursor was visible, but we want to remove it */ 1695 /*WCrt(ba, CRT_ID_CURSOR_START, | 0x20);*/ 1696 ri->ri_flg &= ~RI_CURSOR; 1697 } 1698 1699 ri->ri_crow = row; 1700 ri->ri_ccol = col; 1701 1702 if (on) { 1703 /* move cursor to new location */ 1704 if (!(ri->ri_flg & RI_CURSOR)) { 1705 /*WCrt(ba, CRT_ID_CURSOR_START, | 0x20);*/ 1706 ri->ri_flg |= RI_CURSOR; 1707 } 1708 offs = gp->g_rowoffset[row] + col; 1709 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, offs & 0xff); 1710 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, (offs >> 8) & 0xff); 1711 WCrt(ba, CRT_ID_EXT_START, (offs >> (16-2)) & 0x0c); 1712 } 1713 } 1714 1715 static void 1716 et_wsputchar(void *c, int row, int col, u_int ch, long attr) 1717 { 1718 struct rasops_info *ri; 1719 struct vcons_screen *scr; 1720 struct grf_softc *gp; 1721 volatile unsigned char *ba, *cp; 1722 1723 ri = c; 1724 scr = ri->ri_hw; 1725 gp = scr->scr_cookie; 1726 ba = gp->g_regkva; 1727 cp = gp->g_fbkva; 1728 1729 cp += gp->g_rowoffset[row] + col; 1730 SetTextPlane(ba, 0x00); 1731 *cp = ch; 1732 SetTextPlane(ba, 0x01); 1733 *cp = attr; 1734 } 1735 1736 static void 1737 et_wscopycols(void *c, int row, int srccol, int dstcol, int ncols) 1738 { 1739 volatile unsigned char *ba, *dst, *src; 1740 struct rasops_info *ri; 1741 struct vcons_screen *scr; 1742 struct grf_softc *gp; 1743 int i; 1744 1745 KASSERT(ncols > 0); 1746 ri = c; 1747 scr = ri->ri_hw; 1748 gp = scr->scr_cookie; 1749 ba = gp->g_regkva; 1750 src = gp->g_fbkva; 1751 1752 src += gp->g_rowoffset[row]; 1753 dst = src; 1754 src += srccol; 1755 dst += dstcol; 1756 if (srccol < dstcol) { 1757 /* need to copy backwards */ 1758 src += ncols; 1759 dst += ncols; 1760 SetTextPlane(ba, 0x00); 1761 for (i = 0; i < ncols; i++) 1762 *(--dst) = *(--src); 1763 src += ncols; 1764 dst += ncols; 1765 SetTextPlane(ba, 0x01); 1766 for (i = 0; i < ncols; i++) 1767 *(--dst) = *(--src); 1768 } else { 1769 SetTextPlane(ba, 0x00); 1770 for (i = 0; i < ncols; i++) 1771 *dst++ = *src++; 1772 src -= ncols; 1773 dst -= ncols; 1774 SetTextPlane(ba, 0x01); 1775 for (i = 0; i < ncols; i++) 1776 *dst++ = *src++; 1777 } 1778 } 1779 1780 static void 1781 et_wserasecols(void *c, int row, int startcol, int ncols, long fillattr) 1782 { 1783 volatile unsigned char *ba, *cp; 1784 struct rasops_info *ri; 1785 struct vcons_screen *scr; 1786 struct grf_softc *gp; 1787 int i; 1788 1789 ri = c; 1790 scr = ri->ri_hw; 1791 gp = scr->scr_cookie; 1792 ba = gp->g_regkva; 1793 cp = gp->g_fbkva; 1794 1795 cp += gp->g_rowoffset[row] + startcol; 1796 SetTextPlane(ba, 0x00); 1797 for (i = 0; i < ncols; i++) 1798 *cp++ = 0x20; 1799 cp -= ncols; 1800 SetTextPlane(ba, 0x01); 1801 for (i = 0; i < ncols; i++) 1802 *cp++ = 0x07; 1803 } 1804 1805 static void 1806 et_wscopyrows(void *c, int srcrow, int dstrow, int nrows) 1807 { 1808 volatile unsigned char *ba, *dst, *src; 1809 struct rasops_info *ri; 1810 struct vcons_screen *scr; 1811 struct grf_softc *gp; 1812 int i, n; 1813 1814 KASSERT(nrows > 0); 1815 ri = c; 1816 scr = ri->ri_hw; 1817 gp = scr->scr_cookie; 1818 ba = gp->g_regkva; 1819 src = dst = gp->g_fbkva; 1820 n = ri->ri_cols * nrows; 1821 1822 if (srcrow < dstrow) { 1823 /* need to copy backwards */ 1824 src += gp->g_rowoffset[srcrow + nrows]; 1825 dst += gp->g_rowoffset[dstrow + nrows]; 1826 SetTextPlane(ba, 0x00); 1827 for (i = 0; i < n; i++) 1828 *(--dst) = *(--src); 1829 src += n; 1830 dst += n; 1831 SetTextPlane(ba, 0x01); 1832 for (i = 0; i < n; i++) 1833 *(--dst) = *(--src); 1834 } else { 1835 src += gp->g_rowoffset[srcrow]; 1836 dst += gp->g_rowoffset[dstrow]; 1837 SetTextPlane(ba, 0x00); 1838 for (i = 0; i < n; i++) 1839 *dst++ = *src++; 1840 src -= n; 1841 dst -= n; 1842 SetTextPlane(ba, 0x01); 1843 for (i = 0; i < n; i++) 1844 *dst++ = *src++; 1845 } 1846 } 1847 1848 static void 1849 et_wseraserows(void *c, int row, int nrows, long fillattr) 1850 { 1851 volatile unsigned char *ba, *cp; 1852 struct rasops_info *ri; 1853 struct vcons_screen *scr; 1854 struct grf_softc *gp; 1855 int i, n; 1856 1857 ri = c; 1858 scr = ri->ri_hw; 1859 gp = scr->scr_cookie; 1860 ba = gp->g_regkva; 1861 cp = gp->g_fbkva; 1862 1863 cp += gp->g_rowoffset[row]; 1864 n = ri->ri_cols * nrows; 1865 SetTextPlane(ba, 0x00); 1866 for (i = 0; i < n; i++) 1867 *cp++ = 0x20; 1868 cp -= n; 1869 SetTextPlane(ba, 0x01); 1870 for (i = 0; i < n; i++) 1871 *cp++ = 0x07; 1872 } 1873 1874 static int 1875 et_wsallocattr(void *c, int fg, int bg, int flg, long *attr) 1876 { 1877 1878 /* XXX color support? */ 1879 *attr = (flg & WSATTR_REVERSE) ? 0x70 : 0x07; 1880 if (flg & WSATTR_UNDERLINE) *attr = 0x01; 1881 if (flg & WSATTR_HILIT) *attr |= 0x08; 1882 if (flg & WSATTR_BLINK) *attr |= 0x80; 1883 return 0; 1884 } 1885 1886 /* our font does not support unicode extensions */ 1887 static int 1888 et_wsmapchar(void *c, int ch, unsigned int *cp) 1889 { 1890 1891 if (ch > 0 && ch < 256) { 1892 *cp = ch; 1893 return 5; 1894 } 1895 *cp = ' '; 1896 return 0; 1897 } 1898 1899 static int 1900 et_wsioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l) 1901 { 1902 struct vcons_data *vd; 1903 struct grf_softc *gp; 1904 1905 vd = v; 1906 gp = vd->cookie; 1907 1908 switch (cmd) { 1909 case WSDISPLAYIO_GETCMAP: 1910 /* Note: wsdisplay_cmap and grf_colormap have same format */ 1911 if (gp->g_display.gd_planes == 8) 1912 return et_getcmap(gp, (struct grf_colormap *)data); 1913 return EINVAL; 1914 1915 case WSDISPLAYIO_PUTCMAP: 1916 /* Note: wsdisplay_cmap and grf_colormap have same format */ 1917 if (gp->g_display.gd_planes == 8) 1918 return et_putcmap(gp, (struct grf_colormap *)data); 1919 return EINVAL; 1920 1921 case WSDISPLAYIO_GVIDEO: 1922 if (et_isblank(gp)) 1923 *(u_int *)data = WSDISPLAYIO_VIDEO_OFF; 1924 else 1925 *(u_int *)data = WSDISPLAYIO_VIDEO_ON; 1926 return 0; 1927 1928 case WSDISPLAYIO_SVIDEO: 1929 return et_blank(gp, *(u_int *)data == WSDISPLAYIO_VIDEO_ON); 1930 1931 case WSDISPLAYIO_SMODE: 1932 if ((*(int *)data) != gp->g_wsmode) { 1933 if (*(int *)data == WSDISPLAYIO_MODE_EMUL) { 1934 /* load console text mode, redraw screen */ 1935 (void)et_load_mon(gp, &etconsole_mode); 1936 if (vd->active != NULL) 1937 vcons_redraw_screen(vd->active); 1938 } else { 1939 /* switch to current graphics mode */ 1940 if (!et_load_mon(gp, 1941 (struct grfettext_mode *)monitor_current)) 1942 return EINVAL; 1943 } 1944 gp->g_wsmode = *(int *)data; 1945 } 1946 return 0; 1947 1948 case WSDISPLAYIO_GET_FBINFO: 1949 return et_get_fbinfo(gp, data); 1950 } 1951 1952 /* handle this command hw-independant in grf(4) */ 1953 return grf_wsioctl(v, vs, cmd, data, flag, l); 1954 } 1955 1956 /* 1957 * Fill the wsdisplayio_fbinfo structure with information from the current 1958 * graphics mode. Even when text mode is active. 1959 */ 1960 static int 1961 et_get_fbinfo(struct grf_softc *gp, struct wsdisplayio_fbinfo *fbi) 1962 { 1963 struct grfvideo_mode *md; 1964 uint32_t rbits, gbits, bbits; 1965 1966 md = monitor_current; 1967 1968 switch (md->depth) { 1969 case 8: 1970 fbi->fbi_bitsperpixel = 8; 1971 rbits = gbits = bbits = 6; /* keep gcc happy */ 1972 break; 1973 case 15: 1974 fbi->fbi_bitsperpixel = 16; 1975 rbits = gbits = bbits = 5; 1976 break; 1977 case 16: 1978 fbi->fbi_bitsperpixel = 16; 1979 rbits = bbits = 5; 1980 gbits = 6; 1981 break; 1982 case 24: 1983 fbi->fbi_bitsperpixel = 24; 1984 rbits = gbits = bbits = 8; 1985 break; 1986 default: 1987 return EINVAL; 1988 } 1989 1990 fbi->fbi_stride = (fbi->fbi_bitsperpixel / 8) * md->disp_width; 1991 fbi->fbi_width = md->disp_width; 1992 fbi->fbi_height = md->disp_height; 1993 1994 if (md->depth > 8) { 1995 fbi->fbi_pixeltype = WSFB_RGB; 1996 fbi->fbi_subtype.fbi_rgbmasks.red_offset = bbits + gbits; 1997 fbi->fbi_subtype.fbi_rgbmasks.red_size = rbits; 1998 fbi->fbi_subtype.fbi_rgbmasks.green_offset = bbits; 1999 fbi->fbi_subtype.fbi_rgbmasks.green_size = gbits; 2000 fbi->fbi_subtype.fbi_rgbmasks.blue_offset = 0; 2001 fbi->fbi_subtype.fbi_rgbmasks.blue_size = bbits; 2002 fbi->fbi_subtype.fbi_rgbmasks.alpha_offset = 0; 2003 fbi->fbi_subtype.fbi_rgbmasks.alpha_size = 0; 2004 } else { 2005 fbi->fbi_pixeltype = WSFB_CI; 2006 fbi->fbi_subtype.fbi_cmapinfo.cmap_entries = 1 << md->depth; 2007 } 2008 2009 fbi->fbi_flags = 0; 2010 fbi->fbi_fbsize = fbi->fbi_stride * fbi->fbi_height; 2011 fbi->fbi_fboffset = 0; 2012 return 0; 2013 } 2014 #endif /* NWSDISPLAY > 0 */ 2015 2016 #endif /* NGRFET */ 2017