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