summaryrefslogtreecommitdiff
path: root/sys/arch/amiga/dev/grf_et.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/amiga/dev/grf_et.c')
-rw-r--r--sys/arch/amiga/dev/grf_et.c1545
1 files changed, 1545 insertions, 0 deletions
diff --git a/sys/arch/amiga/dev/grf_et.c b/sys/arch/amiga/dev/grf_et.c
new file mode 100644
index 00000000000..411a974b915
--- /dev/null
+++ b/sys/arch/amiga/dev/grf_et.c
@@ -0,0 +1,1545 @@
+/* $NetBSD: grf_et.c,v 1.1 1996/05/19 21:05:32 veego Exp $ */
+
+/*
+ * Copyright (c) 1996 Tobias Abt
+ * Copyright (c) 1995 Ezra Story
+ * Copyright (c) 1995 Kari Mettinen
+ * Copyright (c) 1994 Markus Wild
+ * Copyright (c) 1994 Lutz Vieweg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Lutz Vieweg.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "grfet.h"
+#if NGRFET > 0
+
+/*
+ * Graphics routines for Tseng ET4000 (&W32) boards,
+ *
+ * This code offers low-level routines to access Tseng ET4000
+ * graphics-boards from within NetBSD for the Amiga.
+ * No warranties for any kind of function at all - this
+ * code may crash your hardware and scratch your harddisk. Use at your
+ * own risk. Freely distributable.
+ *
+ * Modified for Tseng ET4000 from
+ * Kari Mettinen's Cirrus driver by Tobias Abt
+ *
+ *
+ * TODO:
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <machine/cpu.h>
+#include <dev/cons.h>
+#ifdef TSENGCONSOLE
+#include <amiga/dev/itevar.h>
+#endif
+#include <amiga/amiga/device.h>
+#include <amiga/dev/grfioctl.h>
+#include <amiga/dev/grfvar.h>
+#include <amiga/dev/grf_etreg.h>
+#include <amiga/dev/zbusvar.h>
+
+int et_mondefok __P((struct grfvideo_mode * gv));
+void et_boardinit __P((struct grf_softc * gp));
+static void et_CompFQ __P((u_int fq, u_char * num, u_char * denom));
+int et_getvmode __P((struct grf_softc * gp, struct grfvideo_mode * vm));
+int et_setvmode __P((struct grf_softc * gp, unsigned int mode));
+int et_toggle __P((struct grf_softc * gp, unsigned short));
+int et_getcmap __P((struct grf_softc * gfp, struct grf_colormap * cmap));
+int et_putcmap __P((struct grf_softc * gfp, struct grf_colormap * cmap));
+#ifndef TSENGCONSOLE
+void et_off __P((struct grf_softc * gp));
+#endif
+void et_inittextmode __P((struct grf_softc * gp));
+int et_ioctl __P((register struct grf_softc * gp, u_long cmd, void *data));
+int et_getmousepos __P((struct grf_softc * gp, struct grf_position * data));
+void et_writesprpos __P((volatile char *ba, short x, short y));
+#ifdef notyet
+void et_writeshifted __P((unsigned char *to, char shiftx, char shifty));
+#endif
+int et_setmousepos __P((struct grf_softc * gp, struct grf_position * data));
+static int et_setspriteinfo __P((struct grf_softc * gp, struct grf_spriteinfo * data));
+int et_getspriteinfo __P((struct grf_softc * gp, struct grf_spriteinfo * data));
+static int et_getspritemax __P((struct grf_softc * gp, struct grf_position * data));
+int et_setmonitor __P((struct grf_softc * gp, struct grfvideo_mode * gv));
+int et_blank __P((struct grf_softc * gp, int * on));
+static int et_getControllerType __P((struct grf_softc * gp));
+static int et_getDACType __P((struct grf_softc * gp));
+
+int grfetmatch __P((struct device *, void *, void *));
+void grfetattach __P((struct device *, struct device *, void *));
+int grfetprint __P((void *, char *));
+void et_memset __P((unsigned char *d, unsigned char c, int l));
+
+/* Graphics display definitions.
+ * These are filled by 'grfconfig' using GRFIOCSETMON.
+ */
+#define monitor_def_max 8
+static struct grfvideo_mode monitor_def[8] = {
+ {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}
+};
+static struct grfvideo_mode *monitor_current = &monitor_def[0];
+
+/* Console display definition.
+ * Default hardcoded text mode. This grf_et is set up to
+ * use one text mode only, and this is it. You may use
+ * grfconfig to change the mode after boot.
+ */
+/* Console font */
+#ifdef KFONT_8X11
+#define TSENGFONT kernel_font_8x11
+#define TSENGFONTY 11
+#else
+#define TSENGFONT kernel_font_8x8
+#define TSENGFONTY 8
+#endif
+extern unsigned char TSENGFONT[];
+
+struct grfettext_mode etconsole_mode = {
+ {255, "", 25000000, 640, 480, 4, 640/8, 784/8, 680/8, 768/8, 800/8,
+ 481, 521, 491, 493, 525},
+ 8, TSENGFONTY, 640 / 8, 480 / TSENGFONTY, TSENGFONT, 32, 255
+};
+
+/* some modes
+# 640x480 256colors 41kHz 79Hz active
+x 31500000 640 480 8 640 752 672 768 728 487 505 488 490 512
+# 31500000 640 480 8 80 94 84 96 91 487 505 488 490 512
+# 640x512 256colors 42kHz 76Hz active
+x 32500000 640 512 8 640 760 664 760 736 519 536 520 522 543
+# 32500000 640 512 8 80 95 83 95 92 519 536 520 522 543
+# 720x540 256colors 43kHz 74Hz active
+x 37500000 720 540 8 720 856 744 840 832 547 565 548 550 572
+# 37500000 720 540 8 90 107 93 105 104 547 565 548 550 572
+# 800x600 256colors 48kHz 73Hz active
+x 50350000 800 600 8 792 1048 864 960 1016 599 648 615 617 647
+# 50350000 800 600 8 99 131 108 120 127 599 648 615 617 647
+# 912x684 256colors 57kHz 78Hz active
+x 65000000 912 684 8 904 1136 944 1040 1104 683 725 693 695 724
+# 65000000 912 684 8 113 142 118 130 138 683 725 693 695 724
+# 1024x768 256colors 61kHz 75Hz active
+x 80000000 1024 768 8 1024 1288 1072 1168 1264 775 806 780 782 813
+# 80000000 1024 768 8 128 161 134 146 158 775 806 780 782 813
+# 1120x832 256colors 56kHz 64Hz active
+x 80000000 1120 832 8 1120 1424 1152 1248 1400 839 848 833 835 855
+# 80000000 1120 832 8 140 178 144 156 175 839 848 833 835 855
+*/
+
+/* Console colors */
+unsigned char etconscolors[3][3] = { /* background, foreground, hilite */
+ {0, 0x40, 0x50}, {152, 152, 152}, {255, 255, 255}
+};
+
+int ettype = 0; /* oMniBus, Domino or Merlin */
+int etctype = 0; /* ET4000 or ETW32 */
+int etdtype = 0; /* Type of DAC (see grf_etregs.h) */
+
+char etcmap_shift = 0; /* 6 or 8 bit cmap entries */
+unsigned char pass_toggle; /* passthru status tracker */
+
+unsigned char Merlin_switch = 0;
+
+/* because all Tseng-boards have 2 configdev entries, one for
+ * framebuffer mem and the other for regs, we have to hold onto
+ * the pointers globally until we match on both. This and 'ettype'
+ * are the primary obsticles to multiple board support, but if you
+ * have multiple boards you have bigger problems than grf_et.
+ */
+static void *et_fbaddr = 0; /* framebuffer */
+static void *et_regaddr = 0; /* registers */
+static int et_fbsize; /* framebuffer size */
+
+/* current sprite info, if you add support for multiple boards
+ * make this an array or something
+ */
+struct grf_spriteinfo et_cursprite;
+
+/* sprite bitmaps in kernel stack, you'll need to arrayize these too if
+ * you add multiple board support
+ */
+static unsigned char et_imageptr[8 * 64], et_maskptr[8 * 64];
+static unsigned char et_sprred[2], et_sprgreen[2], et_sprblue[2];
+
+/* standard driver stuff */
+struct cfattach grfet_ca = {
+ sizeof(struct grf_softc), grfetmatch, grfetattach
+};
+
+struct cfdriver grfet_cd = {
+ NULL, "grfet", DV_DULL, NULL, 0
+};
+static struct cfdata *cfdata;
+
+
+int
+grfetmatch(pdp, match, auxp)
+ struct device *pdp;
+ void *match, *auxp;
+{
+#ifdef TSENGCONSOLE
+ struct cfdata *cfp = match;
+#endif
+ struct zbus_args *zap;
+ static int regprod, fbprod;
+
+ zap = auxp;
+
+#ifndef TSENGCONSOLE
+ if (amiga_realconfig == 0)
+ return (0);
+#endif
+
+ /* Grab the first board we encounter as the preferred one. This will
+ * allow one board to work in a multiple Tseng board system, but not
+ * multiple boards at the same time. */
+ if (ettype == 0) {
+ switch (zap->manid) {
+ case OMNIBUS:
+ if (zap->prodid != 0)
+ return (0);
+ regprod = 0;
+ fbprod = 0;
+ break;
+ case DOMINO:
+ if (zap->prodid != 2 && zap->prodid != 1)
+ return (0);
+ regprod = 2;
+ fbprod = 1;
+ break;
+ case MERLIN:
+ if (zap->prodid != 3 && zap->prodid != 4)
+ return (0);
+ regprod = 4;
+ fbprod = 3;
+ /*
+ * This card works only in ZorroII mode.
+ * ZorroIII needs different initialisations,
+ * which will be implemented later.
+ */
+ if iszthreepa(zap->pa)
+ return (0);
+ break;
+ default:
+ return (0);
+ }
+ ettype = zap->manid;
+ } else {
+ if (ettype != zap->manid) {
+ return (0);
+ }
+ }
+
+ /* Configure either registers or framebuffer in any order */
+ /* as said before, oMniBus does not support ProdID */
+ if (ettype == OMNIBUS) {
+ if (zap->size == 64 * 1024) {
+ /* register area */
+ et_regaddr = zap->va;
+ } else {
+ /* memory area */
+ et_fbaddr = zap->va;
+ et_fbsize = zap->size;
+ }
+ } else {
+ if (zap->prodid == regprod) {
+ et_regaddr = zap->va;
+ } else {
+ if (zap->prodid == fbprod) {
+ et_fbaddr = zap->va;
+ et_fbsize = zap->size;
+ } else {
+ return (0);
+ }
+ }
+ }
+
+#ifdef TSENGCONSOLE
+ if (amiga_realconfig == 0) {
+ cfdata = cfp;
+ }
+#endif
+
+ return (1);
+}
+
+
+void
+grfetattach(pdp, dp, auxp)
+ struct device *pdp, *dp;
+ void *auxp;
+{
+ static struct grf_softc congrf;
+ struct zbus_args *zap;
+ struct grf_softc *gp;
+ static char attachflag = 0;
+
+ zap = auxp;
+
+ printf("\n");
+
+ /* make sure both halves have matched */
+ if (!et_regaddr || !et_fbaddr)
+ return;
+
+ if (zap->manid == MERLIN && iszthreepa(zap->pa)) {
+ printf("grfet: WARNING: It is not possible to use the Merlin in ZorroIII mode.\n");
+ printf("grfet: Switch the Jumper to use it in ZorroII mode.\n");
+ printf("grfet unattached!!\n");
+ return;
+ }
+
+ /* do all that messy console/grf stuff */
+ if (dp == NULL)
+ gp = &congrf;
+ else
+ gp = (struct grf_softc *) dp;
+
+ if (dp != NULL && congrf.g_regkva != 0) {
+ /*
+ * inited earlier, just copy (not device struct)
+ */
+ bcopy(&congrf.g_display, &gp->g_display,
+ (char *) &gp[1] - (char *) &gp->g_display);
+ } else {
+ gp->g_regkva = (volatile caddr_t) et_regaddr;
+ gp->g_fbkva = (volatile caddr_t) et_fbaddr;
+
+ gp->g_unit = GRF_ET4000_UNIT;
+ gp->g_mode = et_mode;
+ gp->g_conpri = grfet_cnprobe();
+ gp->g_flags = GF_ALIVE;
+
+ /* wakeup the board */
+ et_boardinit(gp);
+
+#ifdef TSENGCONSOLE
+ grfet_iteinit(gp);
+ (void) et_load_mon(gp, &etconsole_mode);
+#endif
+ }
+
+ /*
+ * attach grf (once)
+ */
+ if (amiga_config_found(cfdata, &gp->g_device, gp, grfetprint)) {
+ attachflag = 1;
+ printf("grfet: %dMB ", et_fbsize / 0x100000);
+ switch (ettype) {
+ case OMNIBUS:
+ printf("oMniBus");
+ break;
+ case DOMINO:
+ printf("Domino");
+ break;
+ case MERLIN:
+ printf("Merlin");
+ break;
+ }
+ printf(" with ");
+ switch (etctype) {
+ case ET4000:
+ printf("Tseng ET4000");
+ break;
+ case ETW32:
+ printf("Tseng ETW32");
+ break;
+ }
+ printf(" and ");
+ switch (etdtype) {
+ case SIERRA11483:
+ printf("Sierra SC11483 DAC");
+ break;
+ case SIERRA15025:
+ printf("Sierra SC15025 DAC");
+ break;
+ case MUSICDAC:
+ printf("MUSIC DAC");
+ break;
+ case MERLINDAC:
+ printf("BrookTree DAC");
+ break;
+ }
+ printf(" being used\n");
+ } else {
+ if (!attachflag)
+ printf("grfet unattached!!\n");
+ }
+}
+
+
+int
+grfetprint(auxp, pnp)
+ void *auxp;
+ char *pnp;
+{
+ if (pnp)
+ printf("ite at %s: ", pnp);
+ return (UNCONF);
+}
+
+
+void
+et_boardinit(gp)
+ struct grf_softc *gp;
+{
+ unsigned char *ba = gp->g_regkva;
+ int x;
+
+ /* wakeup board and flip passthru OFF */
+
+ RegWakeup(ba);
+ RegOnpass(ba);
+
+ if (ettype == MERLIN) {
+ /* Merlin needs some special initialisations */
+ vgaw(ba, MERLIN_SWITCH_REG, 0);
+ delay(20000);
+ vgaw(ba, MERLIN_SWITCH_REG, 8);
+ delay(20000);
+ vgaw(ba, MERLIN_SWITCH_REG, 0);
+ delay(20000);
+ vgaw(ba, MERLIN_VDAC_DATA, 1);
+
+ vgaw(ba, MERLIN_VDAC_INDEX, 0x00);
+ vgaw(ba, MERLIN_VDAC_SPRITE, 0xff);
+ vgaw(ba, MERLIN_VDAC_INDEX, 0x01);
+ vgaw(ba, MERLIN_VDAC_SPRITE, 0x0f);
+ vgaw(ba, MERLIN_VDAC_INDEX, 0x02);
+ vgaw(ba, MERLIN_VDAC_SPRITE, 0x42);
+ vgaw(ba, MERLIN_VDAC_INDEX, 0x03);
+ vgaw(ba, MERLIN_VDAC_SPRITE, 0x00);
+
+ vgaw(ba, MERLIN_VDAC_DATA, 0);
+ }
+
+
+ /* setup initial unchanging parameters */
+
+ vgaw(ba, GREG_HERCULESCOMPAT, 0x03);
+ vgaw(ba, GREG_DISPMODECONTROL, 0xa0);
+ vgaw(ba, GREG_MISC_OUTPUT_W, 0x63);
+
+ WSeq(ba, SEQ_ID_RESET, 0x03);
+ WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21); /* 8 dot, Display off */
+ WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
+ WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
+ WSeq(ba, SEQ_ID_MEMORY_MODE, 0x0e);
+/* WSeq(ba, SEQ_ID_TS_STATE_CONTROL, 0x00); */
+ WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf4);
+
+ WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00);
+ WCrt(ba, CRT_ID_CURSOR_START, 0x00);
+ WCrt(ba, CRT_ID_CURSOR_END, 0x08);
+ WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
+ WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
+ WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
+ WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
+
+ WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x07);
+ WCrt(ba, CRT_ID_MODE_CONTROL, 0xa3); /* c3 */
+ WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); /* ff */
+/*
+ WCrt(ba, CRT_ID_EXT_DISP_CNTL, 0x22);
+*/
+/* ET4000 special */
+ WCrt(ba, CRT_ID_RASCAS_CONFIG, 0x28);
+ WCrt(ba, CTR_ID_EXT_START, 0x00);
+ WCrt(ba, CRT_ID_6845_COMPAT, 0x08);
+ WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xd3);
+ WCrt(ba, CRT_ID_VIDEO_CONFIG2, 0x0f);
+ WCrt(ba, CRT_ID_HOR_OVERFLOW, 0x00);
+
+ WGfx(ba, GCT_ID_SET_RESET, 0x00);
+ WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
+ WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00);
+ WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
+ WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
+ WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x00);
+ WGfx(ba, GCT_ID_MISC, 0x01);
+ WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f);
+ WGfx(ba, GCT_ID_BITMASK, 0xff);
+
+ vgaw(ba, GREG_SEGMENTSELECT, 0x00);
+
+ for (x = 0; x < 0x10; x++)
+ WAttr(ba, x, x);
+ WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x01);
+ WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00);
+ WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
+ WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
+ WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
+ WAttr(ba, ACT_ID_MISCELLANEOUS, 0x00);
+
+ vgaw(ba, VDAC_MASK, 0xff);
+ delay(200000);
+ vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3); /* c3 */
+
+ /* colors initially set to greyscale */
+
+ switch(ettype) {
+ case MERLIN:
+ vgaw(ba, MERLIN_VDAC_INDEX, 0);
+ for (x = 255; x >= 0; x--) {
+ vgaw(ba, MERLIN_VDAC_COLORS, x);
+ vgaw(ba, MERLIN_VDAC_COLORS, x);
+ vgaw(ba, MERLIN_VDAC_COLORS, x);
+ }
+ break;
+ default:
+ vgaw(ba, VDAC_ADDRESS_W, 0);
+ for (x = 255; x >= 0; x--) {
+ vgaw(ba, VDAC_DATA, x);
+ vgaw(ba, VDAC_DATA, x);
+ vgaw(ba, VDAC_DATA, x);
+ }
+ break;
+ }
+ /* set sprite bitmap pointers */
+ /* should work like that */
+ et_cursprite.image = et_imageptr;
+ et_cursprite.mask = et_maskptr;
+ et_cursprite.cmap.red = et_sprred;
+ et_cursprite.cmap.green = et_sprgreen;
+ et_cursprite.cmap.blue = et_sprblue;
+
+ /* card spezific initialisations */
+ switch(ettype) {
+ case OMNIBUS:
+ etctype = et_getControllerType(gp);
+ etdtype = et_getDACType(gp);
+ break;
+ case MERLIN:
+ etctype = ETW32;
+ etdtype = MERLINDAC;
+ break;
+ case DOMINO:
+ etctype = ET4000;
+ etdtype = SIERRA11483;
+ break;
+ }
+}
+
+
+int
+et_getvmode(gp, vm)
+ struct grf_softc *gp;
+ struct grfvideo_mode *vm;
+{
+ struct grfvideo_mode *gv;
+
+#ifdef TSENGCONSOLE
+ /* Handle grabbing console mode */
+ if (vm->mode_num == 255) {
+ bcopy(&etconsole_mode, vm, sizeof(struct grfvideo_mode));
+ /* XXX so grfconfig can tell us the correct text dimensions. */
+ vm->depth = etconsole_mode.fy;
+ } else
+#endif
+ {
+ if (vm->mode_num == 0)
+ vm->mode_num = (monitor_current - monitor_def) + 1;
+ if (vm->mode_num < 1 || vm->mode_num > monitor_def_max)
+ return (EINVAL);
+ gv = monitor_def + (vm->mode_num - 1);
+ if (gv->mode_num == 0)
+ return (EINVAL);
+
+ bcopy(gv, vm, sizeof(struct grfvideo_mode));
+ }
+
+ /* adjust internal values to pixel values */
+
+ vm->hblank_start *= 8;
+ vm->hblank_stop *= 8;
+ vm->hsync_start *= 8;
+ vm->hsync_stop *= 8;
+ vm->htotal *= 8;
+
+ return (0);
+}
+
+
+int
+et_setvmode(gp, mode)
+ struct grf_softc *gp;
+ unsigned mode;
+{
+ if (!mode || (mode > monitor_def_max) ||
+ monitor_def[mode - 1].mode_num == 0)
+ return (EINVAL);
+
+ monitor_current = monitor_def + (mode - 1);
+
+ return (0);
+}
+
+
+#ifndef TSENGCONSOLE
+void
+et_off(gp)
+ struct grf_softc *gp;
+{
+ char *ba = gp->g_regkva;
+
+ /* we'll put the pass-through on for cc ite and set Full Bandwidth bit
+ * on just in case it didn't work...but then it doesn't matter does
+ * it? =) */
+ RegOnpass(ba);
+ WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21);
+}
+#endif
+
+
+int
+et_blank(gp, on)
+ struct grf_softc *gp;
+ int *on;
+{
+ WSeq(gp->g_regkva, SEQ_ID_CLOCKING_MODE, *on ? 0x21 : 0x01);
+ return(0);
+}
+
+
+/*
+ * Change the mode of the display.
+ * Return a UNIX error number or 0 for success.
+ */
+int
+et_mode(gp, cmd, arg, a2, a3)
+ register struct grf_softc *gp;
+ u_long cmd;
+ void *arg;
+ u_long a2;
+ int a3;
+{
+ int error;
+
+ switch (cmd) {
+ case GM_GRFON:
+ error = et_load_mon(gp,
+ (struct grfettext_mode *) monitor_current) ? 0 : EINVAL;
+ return (error);
+
+ case GM_GRFOFF:
+#ifndef TSENGCONSOLE
+ et_off(gp);
+#else
+ et_load_mon(gp, &etconsole_mode);
+#endif
+ return (0);
+
+ case GM_GRFCONFIG:
+ return (0);
+
+ case GM_GRFGETVMODE:
+ return (et_getvmode(gp, (struct grfvideo_mode *) arg));
+
+ case GM_GRFSETVMODE:
+ error = et_setvmode(gp, *(unsigned *) arg);
+ if (!error && (gp->g_flags & GF_GRFON))
+ et_load_mon(gp,
+ (struct grfettext_mode *) monitor_current);
+ return (error);
+
+ case GM_GRFGETNUMVM:
+ *(int *) arg = monitor_def_max;
+ return (0);
+
+ case GM_GRFIOCTL:
+ return (et_ioctl(gp, a2, arg));
+
+ default:
+ break;
+ }
+
+ return (EINVAL);
+}
+
+int
+et_ioctl(gp, cmd, data)
+ register struct grf_softc *gp;
+ u_long cmd;
+ void *data;
+{
+ switch (cmd) {
+ case GRFIOCGSPRITEPOS:
+ return (et_getmousepos(gp, (struct grf_position *) data));
+
+ case GRFIOCSSPRITEPOS:
+ return (et_setmousepos(gp, (struct grf_position *) data));
+
+ case GRFIOCSSPRITEINF:
+ return (et_setspriteinfo(gp, (struct grf_spriteinfo *) data));
+
+ case GRFIOCGSPRITEINF:
+ return (et_getspriteinfo(gp, (struct grf_spriteinfo *) data));
+
+ case GRFIOCGSPRITEMAX:
+ return (et_getspritemax(gp, (struct grf_position *) data));
+
+ case GRFIOCGETCMAP:
+ return (et_getcmap(gp, (struct grf_colormap *) data));
+
+ case GRFIOCPUTCMAP:
+ return (et_putcmap(gp, (struct grf_colormap *) data));
+
+ case GRFIOCBITBLT:
+ break;
+
+ case GRFTOGGLE:
+ return (et_toggle(gp, 0));
+
+ case GRFIOCSETMON:
+ return (et_setmonitor(gp, (struct grfvideo_mode *) data));
+
+ case GRFIOCBLANK:
+ return (et_blank(gp, (int *)data));
+ }
+ return (EINVAL);
+}
+
+
+int
+et_getmousepos(gp, data)
+ struct grf_softc *gp;
+ struct grf_position *data;
+{
+ data->x = et_cursprite.pos.x;
+ data->y = et_cursprite.pos.y;
+ return (0);
+}
+
+
+void
+et_writesprpos(ba, x, y)
+ volatile char *ba;
+ short x;
+ short y;
+{
+}
+
+
+#ifdef notyet
+void
+et_writeshifted(to, shiftx, shifty)
+ unsigned char *to;
+ char shiftx;
+ char shifty;
+{
+}
+#endif
+
+
+int
+et_setmousepos(gp, data)
+ struct grf_softc *gp;
+ struct grf_position *data;
+{
+ volatile char *ba = gp->g_regkva;
+#if 0
+ volatile char *fb = gp->g_fbkva;
+ volatile char *sprite = fb + (et_fbsize - 1024);
+#endif
+ short rx, ry, prx, pry;
+
+ /* no movement */
+ if (et_cursprite.pos.x == data->x && et_cursprite.pos.y == data->y)
+ return (0);
+
+ /* current and previous real coordinates */
+ rx = data->x - et_cursprite.hot.x;
+ ry = data->y - et_cursprite.hot.y;
+ prx = et_cursprite.pos.x - et_cursprite.hot.x;
+ pry = et_cursprite.pos.y - et_cursprite.hot.y;
+
+ /* if we are/were on an edge, create (un)shifted bitmap --
+ * ripped out optimization (not extremely worthwhile,
+ * and kind of buggy anyhow).
+ */
+#ifdef notyet
+ if (rx < 0 || ry < 0 || prx < 0 || pry < 0) {
+ et_writeshifted(sprite, rx < 0 ? -rx : 0, ry < 0 ? -ry : 0);
+ }
+#endif
+
+ /* do movement, save position */
+ et_writesprpos(ba, rx < 0 ? 0 : rx, ry < 0 ? 0 : ry);
+ et_cursprite.pos.x = data->x;
+ et_cursprite.pos.y = data->y;
+
+ return (0);
+}
+
+
+int
+et_getspriteinfo(gp, data)
+ struct grf_softc *gp;
+ struct grf_spriteinfo *data;
+{
+
+ return(EINVAL);
+}
+
+
+static int
+et_setspriteinfo(gp, data)
+ struct grf_softc *gp;
+ struct grf_spriteinfo *data;
+{
+
+ return(EINVAL);
+}
+
+
+static int
+et_getspritemax(gp, data)
+ struct grf_softc *gp;
+ struct grf_position *data;
+{
+
+ return(EINVAL);
+}
+
+
+int
+et_setmonitor(gp, gv)
+ struct grf_softc *gp;
+ struct grfvideo_mode *gv;
+{
+ struct grfvideo_mode *md;
+
+ if (!et_mondefok(gv))
+ return(EINVAL);
+
+#ifdef TSENGCONSOLE
+ /* handle interactive setting of console mode */
+ if (gv->mode_num == 255) {
+ bcopy(gv, &etconsole_mode.gv, sizeof(struct grfvideo_mode));
+ etconsole_mode.gv.hblank_start /= 8;
+ etconsole_mode.gv.hblank_stop /= 8;
+ etconsole_mode.gv.hsync_start /= 8;
+ etconsole_mode.gv.hsync_stop /= 8;
+ etconsole_mode.gv.htotal /= 8;
+ etconsole_mode.rows = gv->disp_height / etconsole_mode.fy;
+ etconsole_mode.cols = gv->disp_width / etconsole_mode.fx;
+ if (!(gp->g_flags & GF_GRFON))
+ et_load_mon(gp, &etconsole_mode);
+ ite_reinit(gp->g_itedev);
+ return (0);
+ }
+#endif
+
+ md = monitor_def + (gv->mode_num - 1);
+ bcopy(gv, md, sizeof(struct grfvideo_mode));
+
+ /* adjust pixel oriented values to internal rep. */
+
+ md->hblank_start /= 8;
+ md->hblank_stop /= 8;
+ md->hsync_start /= 8;
+ md->hsync_stop /= 8;
+ md->htotal /= 8;
+
+ return (0);
+}
+
+
+int
+et_getcmap(gfp, cmap)
+ struct grf_softc *gfp;
+ struct grf_colormap *cmap;
+{
+ volatile unsigned char *ba;
+ u_char red[256], green[256], blue[256], *rp, *gp, *bp;
+ short x;
+ int error;
+
+ if (cmap->count == 0 || cmap->index >= 256)
+ return 0;
+
+ if (cmap->index + cmap->count > 256)
+ cmap->count = 256 - cmap->index;
+
+ ba = gfp->g_regkva;
+ /* first read colors out of the chip, then copyout to userspace */
+ x = cmap->count - 1;
+
+ rp = red + cmap->index;
+ gp = green + cmap->index;
+ bp = blue + cmap->index;
+
+ switch(ettype) {
+ case MERLIN:
+ vgaw(ba, MERLIN_VDAC_INDEX, cmap->index);
+ do {
+ *rp++ = vgar(ba, MERLIN_VDAC_COLORS);
+ *gp++ = vgar(ba, MERLIN_VDAC_COLORS);
+ *bp++ = vgar(ba, MERLIN_VDAC_COLORS);
+ } while (x-- > 0);
+ break;
+ default:
+ vgaw(ba, VDAC_ADDRESS_W, cmap->index);
+ do {
+ *rp++ = vgar(ba, VDAC_DATA) << etcmap_shift;
+ *gp++ = vgar(ba, VDAC_DATA) << etcmap_shift;
+ *bp++ = vgar(ba, VDAC_DATA) << etcmap_shift;
+ } while (x-- > 0);
+ break;
+ }
+
+ if (!(error = copyout(red + cmap->index, cmap->red, cmap->count))
+ && !(error = copyout(green + cmap->index, cmap->green, cmap->count))
+ && !(error = copyout(blue + cmap->index, cmap->blue, cmap->count)))
+ return (0);
+
+ return (error);
+}
+
+
+int
+et_putcmap(gfp, cmap)
+ struct grf_softc *gfp;
+ struct grf_colormap *cmap;
+{
+ volatile unsigned char *ba;
+ u_char red[256], green[256], blue[256], *rp, *gp, *bp;
+ short x;
+ int error;
+
+ if (cmap->count == 0 || cmap->index >= 256)
+ return (0);
+
+ if (cmap->index + cmap->count > 256)
+ cmap->count = 256 - cmap->index;
+
+ /* first copy the colors into kernelspace */
+ if (!(error = copyin(cmap->red, red + cmap->index, cmap->count))
+ && !(error = copyin(cmap->green, green + cmap->index, cmap->count))
+ && !(error = copyin(cmap->blue, blue + cmap->index, cmap->count))) {
+ ba = gfp->g_regkva;
+ x = cmap->count - 1;
+
+ rp = red + cmap->index;
+ gp = green + cmap->index;
+ bp = blue + cmap->index;
+
+ switch(ettype){
+ case MERLIN:
+ vgaw(ba, MERLIN_VDAC_INDEX, cmap->index);
+ do {
+ vgaw(ba, MERLIN_VDAC_COLORS, *rp++);
+ vgaw(ba, MERLIN_VDAC_COLORS, *gp++);
+ vgaw(ba, MERLIN_VDAC_COLORS, *bp++);
+ } while (x-- > 0);
+ break;
+ default:
+ vgaw(ba, VDAC_ADDRESS_W, cmap->index);
+ do {
+ vgaw(ba, VDAC_DATA, *rp++ >> etcmap_shift);
+ vgaw(ba, VDAC_DATA, *gp++ >> etcmap_shift);
+ vgaw(ba, VDAC_DATA, *bp++ >> etcmap_shift);
+ } while (x-- > 0);
+ break;
+ }
+
+ return (0);
+ } else
+ return (error);
+}
+
+
+int
+et_toggle(gp, wopp)
+ struct grf_softc *gp;
+ unsigned short wopp; /* don't need that one yet, ill */
+{
+ volatile unsigned char *ba;
+
+ ba = gp->g_regkva;
+
+ if (pass_toggle) {
+ RegOffpass(ba);
+ } else {
+ RegOnpass(ba);
+ }
+ return (0);
+}
+
+#define ET_NUMCLOCKS 32
+
+static u_char et_clocks[ET_NUMCLOCKS] = {
+ 0, 1, 6, 2, 3, 7, 4, 5,
+ 0, 1, 6, 2, 3, 7, 4, 5,
+ 0, 1, 6, 2, 3, 7, 4, 5,
+ 0, 1, 6, 2, 3, 7, 4, 5
+};
+
+static u_char et_clockdividers[ET_NUMCLOCKS] = {
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static u_int et_clockfreqs[ET_NUMCLOCKS] = {
+ 6293750, 7080500, 7875000, 8125000,
+ 9000000, 9375000, 10000000, 11225000,
+ 12587500, 14161000, 15750000, 16250000,
+ 18000000, 18750000, 20000000, 22450000,
+ 25175000, 28322000, 31500000, 32500000,
+ 36000000, 37500000, 40000000, 44900000,
+ 50350000, 56644000, 63000000, 65000000,
+ 72000000, 75000000, 80000000, 89800000
+};
+
+
+static void
+et_CompFQ(fq, num, denom)
+ u_int fq;
+ u_char *num;
+ u_char *denom;
+{
+ int i;
+
+ for (i=0; i < ET_NUMCLOCKS;) {
+ if (fq <= et_clockfreqs[i++]) {
+ break;
+ }
+ }
+
+ *num = et_clocks[--i];
+ *denom = et_clockdividers[i];
+
+ return;
+}
+
+
+int
+et_mondefok(gv)
+ struct grfvideo_mode *gv;
+{
+
+ if (gv->mode_num < 1 || gv->mode_num > monitor_def_max)
+ if (gv->mode_num != 255 || gv->depth != 4)
+ return(0);
+
+ switch (gv->depth) {
+ case 4:
+ if (gv->mode_num != 255)
+ return(0);
+ case 1:
+ case 8:
+ case 15:
+ case 16:
+ case 24:
+ break;
+ default:
+ return (0);
+ }
+ return (1);
+}
+
+
+int
+et_load_mon(gp, md)
+ struct grf_softc *gp;
+ struct grfettext_mode *md;
+{
+ struct grfvideo_mode *gv;
+ struct grfinfo *gi;
+ volatile unsigned char *ba;
+ unsigned char num0, denom0;
+ unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS,
+ VSE, VT;
+ char LACE, DBLSCAN, TEXT;
+ unsigned char seq;
+ int uplim, lowlim;
+
+ /* identity */
+ gv = &md->gv;
+ TEXT = (gv->depth == 4);
+
+ if (!et_mondefok(gv)) {
+ printf("mondef not ok\n");
+ return (0);
+ }
+ ba = gp->g_regkva;
+
+ /* provide all needed information in grf device-independant locations */
+ gp->g_data = (caddr_t) gv;
+ gi = &gp->g_display;
+ gi->gd_regaddr = (caddr_t) ztwopa(ba);
+ gi->gd_regsize = 64 * 1024;
+ gi->gd_fbaddr = (caddr_t) kvtop(gp->g_fbkva);
+ gi->gd_fbsize = et_fbsize;
+ gi->gd_colors = 1 << gv->depth;
+ gi->gd_planes = gv->depth;
+ gi->gd_fbwidth = gv->disp_width;
+ gi->gd_fbheight = gv->disp_height;
+ gi->gd_fbx = 0;
+ gi->gd_fby = 0;
+ if (TEXT) {
+ gi->gd_dwidth = md->fx * md->cols;
+ gi->gd_dheight = md->fy * md->rows;
+ } else {
+ gi->gd_dwidth = gv->disp_width;
+ gi->gd_dheight = gv->disp_height;
+ }
+ gi->gd_dx = 0;
+ gi->gd_dy = 0;
+
+ /* get display mode parameters */
+
+ HBS = gv->hblank_start;
+ HBE = gv->hblank_stop;
+ HSS = gv->hsync_start;
+ HSE = gv->hsync_stop;
+ HT = gv->htotal;
+ VBS = gv->vblank_start;
+ VSS = gv->vsync_start;
+ VSE = gv->vsync_stop;
+ VBE = gv->vblank_stop;
+ VT = gv->vtotal;
+
+ if (TEXT)
+ HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1;
+ else
+ HDE = (gv->disp_width + 3) / 8 - 1; /* HBS; */
+ VDE = gv->disp_height - 1;
+
+ /* figure out whether lace or dblscan is needed */
+
+ uplim = gv->disp_height + (gv->disp_height / 4);
+ lowlim = gv->disp_height - (gv->disp_height / 4);
+ LACE = (((VT * 2) > lowlim) && ((VT * 2) < uplim)) ? 1 : 0;
+ DBLSCAN = (((VT / 2) > lowlim) && ((VT / 2) < uplim)) ? 1 : 0;
+
+ /* adjustments */
+
+ if (LACE)
+ VDE /= 2;
+
+ WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e);
+
+ WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
+ WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff);
+ WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
+
+ /* Set clock */
+
+ et_CompFQ( gv->pixel_clock, &num0, &denom0);
+
+ vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3 | ((num0 & 3) << 2));
+ WCrt(ba, CRT_ID_6845_COMPAT, (num0 & 4) ? 0x0a : 0x08);
+ seq=RSeq(ba, SEQ_ID_CLOCKING_MODE);
+ switch(denom0) {
+ case 0:
+ WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xb4);
+ WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
+ break;
+ case 1:
+ WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf4);
+ WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
+ break;
+ case 2:
+ WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5);
+ WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
+ break;
+ case 3:
+ WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5);
+ WSeq(ba, SEQ_ID_CLOCKING_MODE, seq | 0x08);
+ break;
+ }
+ /* load display parameters into board */
+
+ WCrt(ba, CRT_ID_HOR_TOTAL, HT);
+ WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? HBS - 1 : HDE));
+ WCrt(ba, CRT_ID_START_HOR_BLANK, HBS);
+ WCrt(ba, CRT_ID_END_HOR_BLANK, (HBE & 0x1f) | 0x80); /* | 0x80? */
+ WCrt(ba, CRT_ID_START_HOR_RETR, HSS);
+ WCrt(ba, CRT_ID_END_HOR_RETR,
+ (HSE & 0x1f) |
+ ((HBE & 0x20) ? 0x80 : 0x00));
+ WCrt(ba, CRT_ID_VER_TOTAL, VT);
+ WCrt(ba, CRT_ID_OVERFLOW,
+ 0x10 |
+ ((VT & 0x100) ? 0x01 : 0x00) |
+ ((VDE & 0x100) ? 0x02 : 0x00) |
+ ((VSS & 0x100) ? 0x04 : 0x00) |
+ ((VBS & 0x100) ? 0x08 : 0x00) |
+ ((VT & 0x200) ? 0x20 : 0x00) |
+ ((VDE & 0x200) ? 0x40 : 0x00) |
+ ((VSS & 0x200) ? 0x80 : 0x00));
+
+ WCrt(ba, CRT_ID_MAX_ROW_ADDRESS,
+ 0x40 | /* TEXT ? 0x00 ??? */
+ (DBLSCAN ? 0x80 : 0x00) |
+ ((VBS & 0x200) ? 0x20 : 0x00) |
+ (TEXT ? ((md->fy - 1) & 0x1f) : 0x00));
+
+ WCrt(ba, CRT_ID_MODE_CONTROL,
+ ((TEXT || (gv->depth == 1)) ? 0xc3 : 0xab));
+
+ /* text cursor */
+
+ if (TEXT) {
+#if ET_ULCURSOR
+ WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2);
+ WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1);
+#else
+ WCrt(ba, CRT_ID_CURSOR_START, 0x00);
+ WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f);
+#endif
+ WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
+ WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
+ }
+
+ WCrt(ba, CRT_ID_UNDERLINE_LOC, ((md->fy - 1) & 0x1f)
+ | ((TEXT || (gv->depth == 1)) ? 0x00 : 0x60));
+
+ WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
+ WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
+
+ WCrt(ba, CRT_ID_START_VER_RETR, VSS);
+ WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f) | 0x30);
+ WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE);
+ WCrt(ba, CRT_ID_START_VER_BLANK, VBS);
+ WCrt(ba, CRT_ID_END_VER_BLANK, VBE);
+
+ WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
+
+ WCrt(ba, CRT_ID_OVERFLOW_HIGH,
+ ((VBS & 0x400) ? 0x01 : 0x00) |
+ ((VT & 0x400) ? 0x02 : 0x00) |
+ ((VDE & 0x400) ? 0x04 : 0x00) |
+ ((VSS & 0x400) ? 0x08 : 0x00) |
+ 0x10 |
+ (LACE ? 0x80 : 0x00));
+
+ WCrt(ba, CRT_ID_HOR_OVERFLOW,
+ ((HT & 0x100) ? 0x01 : 0x00) |
+ ((HBS & 0x100) ? 0x04 : 0x00) |
+ ((HSS & 0x100) ? 0x10 : 0x00)
+ );
+
+ /* depth dependent stuff */
+
+ WGfx(ba, GCT_ID_GRAPHICS_MODE,
+ ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40));
+ WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
+
+ vgaw(ba, VDAC_MASK, 0xff);
+ vgar(ba, VDAC_MASK);
+ vgar(ba, VDAC_MASK);
+ vgar(ba, VDAC_MASK);
+ vgar(ba, VDAC_MASK);
+ switch (gv->depth) {
+ case 1:
+ case 4: /* text */
+ switch(etdtype) {
+ case SIERRA11483:
+ case SIERRA15025:
+ case MUSICDAC:
+ vgaw(ba, VDAC_MASK, 0);
+ break;
+ case MERLINDAC:
+ setMerlinDACmode(ba, 0);
+ break;
+ }
+ HDE = gv->disp_width / 16;
+ break;
+ case 8:
+ switch(etdtype) {
+ case SIERRA11483:
+ case SIERRA15025:
+ case MUSICDAC:
+ vgaw(ba, VDAC_MASK, 0);
+ break;
+ case MERLINDAC:
+ setMerlinDACmode(ba, 0);
+ break;
+ }
+ HDE = gv->disp_width / 8;
+ break;
+ case 15:
+ switch(etdtype) {
+ case SIERRA11483:
+ case SIERRA15025:
+ case MUSICDAC:
+ vgaw(ba, VDAC_MASK, 0xa0);
+ break;
+ case MERLINDAC:
+ setMerlinDACmode(ba, 0xa0);
+ break;
+ }
+ HDE = gv->disp_width / 4;
+ break;
+ case 16:
+ switch(etdtype) {
+ case SIERRA11483:
+ vgaw(ba, VDAC_MASK, 0); /* illegal mode! */
+ break;
+ case SIERRA15025:
+ vgaw(ba, VDAC_MASK, 0xe0);
+ break;
+ case MUSICDAC:
+ vgaw(ba, VDAC_MASK, 0xc0);
+ break;
+ case MERLINDAC:
+ setMerlinDACmode(ba, 0xe0);
+ break;
+ }
+ HDE = gv->disp_width / 4;
+ break;
+ case 24:
+ switch(etdtype) {
+ case SIERRA11483:
+ vgaw(ba, VDAC_MASK, 0); /* illegal mode! */
+ break;
+ case SIERRA15025:
+ vgaw(ba, VDAC_MASK, 0xe1);
+ break;
+ case MUSICDAC:
+ vgaw(ba, VDAC_MASK, 0xe0);
+ break;
+ case MERLINDAC:
+ setMerlinDACmode(ba, 0xf0);
+ break;
+ }
+ HDE = (gv->disp_width / 8) * 3;
+ break;
+ case 32:
+ switch(etdtype) {
+ case SIERRA11483:
+ case MUSICDAC:
+ vgaw(ba, VDAC_MASK, 0); /* illegal mode! */
+ break;
+ case SIERRA15025:
+ vgaw(ba, VDAC_MASK, 0x61);
+ break;
+ case MERLINDAC:
+ setMerlinDACmode(ba, 0xb0);
+ break;
+ }
+ HDE = gv->disp_width / 2;
+ break;
+ }
+ WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x0a : 0x01));
+ WAttr(ba, 0x20 | ACT_ID_COLOR_PLANE_ENA,
+ (gv->depth == 1) ? 0x01 : 0x0f);
+
+ WCrt(ba, CRT_ID_OFFSET, HDE);
+
+ /* text initialization */
+ if (TEXT) {
+ et_inittextmode(gp);
+ }
+
+ WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01);
+
+ /* Pass-through */
+ RegOffpass(ba);
+
+ return (1);
+}
+
+
+void
+et_inittextmode(gp)
+ struct grf_softc *gp;
+{
+ struct grfettext_mode *tm = (struct grfettext_mode *) gp->g_data;
+ volatile unsigned char *ba = gp->g_regkva;
+ unsigned char *fb = gp->g_fbkva;
+ unsigned char *c, *f, y;
+ unsigned short z;
+
+
+ /* load text font into beginning of display memory. Each character
+ * cell is 32 bytes long (enough for 4 planes) */
+
+ SetTextPlane(ba, 0x02);
+ et_memset(fb, 0, 256 * 32);
+ c = (unsigned char *) (fb) + (32 * tm->fdstart);
+ f = tm->fdata;
+ for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy))
+ for (y = 0; y < tm->fy; y++)
+ *c++ = *f++;
+
+ /* clear out text/attr planes (three screens worth) */
+
+ SetTextPlane(ba, 0x01);
+ et_memset(fb, 0x07, tm->cols * tm->rows * 3);
+ SetTextPlane(ba, 0x00);
+ et_memset(fb, 0x20, tm->cols * tm->rows * 3);
+
+ /* print out a little init msg */
+
+ c = (unsigned char *) (fb) + (tm->cols - 16);
+ strcpy(c, "TSENG");
+ c[6] = 0x20;
+
+ /* set colors (B&W) */
+
+ switch(ettype) {
+ case MERLIN:
+ vgaw(ba, MERLIN_VDAC_INDEX, 0);
+ for (z = 0; z < 256; z++) {
+ y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
+
+ vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][0]);
+ vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][1]);
+ vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][2]);
+ }
+ break;
+ default:
+ vgaw(ba, VDAC_ADDRESS_W, 0);
+ for (z = 0; z < 256; z++) {
+ y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
+
+ vgaw(ba, VDAC_DATA, etconscolors[y][0] >> etcmap_shift);
+ vgaw(ba, VDAC_DATA, etconscolors[y][1] >> etcmap_shift);
+ vgaw(ba, VDAC_DATA, etconscolors[y][2] >> etcmap_shift);
+ }
+ break;
+ }
+}
+
+
+void
+et_memset(d, c, l)
+ unsigned char *d;
+ unsigned char c;
+ int l;
+{
+ for (; l > 0; l--)
+ *d++ = c;
+}
+
+
+static int
+et_getControllerType(gp)
+ struct grf_softc * gp;
+{
+ unsigned char *ba = gp->g_regkva; /* register base */
+ unsigned char *mem = gp->g_fbkva; /* memory base */
+ unsigned char *mmu = mem + MMU_APERTURE0; /* MMU aperture 0 base */
+
+ *mem = 0;
+
+ /* make ACL visible */
+ WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xfb);
+ WIma(ba, IMA_PORTCONTROL, 0x01);
+
+ *((unsigned long *)mmu) = 0;
+ *(mem + 0x13) = 0x38;
+
+ *mmu = 0xff;
+
+ /* hide ACL */
+ WIma(ba, IMA_PORTCONTROL, 0x00);
+ WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xd3);
+
+ return((*mem == 0xff) ? ETW32 : ET4000);
+}
+
+
+static int
+et_getDACType(gp)
+ struct grf_softc * gp;
+{
+ unsigned char *ba = gp->g_regkva;
+ union {
+ int tt;
+ char cc[4];
+ } check;
+
+ /* check for Sierra SC 15025 */
+
+ if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR));
+ vgaw(ba, VDAC_COMMAND, 0x10); /* set ERPF */
+
+ vgaw(ba, VDAC_XINDEX, 9);
+ check.cc[0]=vgar(ba, VDAC_XDATA);
+ vgaw(ba, VDAC_XINDEX, 10);
+ check.cc[1]=vgar(ba, VDAC_XDATA);
+ vgaw(ba, VDAC_XINDEX, 11);
+ check.cc[2]=vgar(ba, VDAC_XDATA);
+ vgaw(ba, VDAC_XINDEX, 12);
+ check.cc[3]=vgar(ba, VDAC_XDATA);
+
+ if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR));
+ vgaw(ba, VDAC_COMMAND, 0x00); /* clear ERPF */
+
+ if(check.tt == 0x533ab141){
+ if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR));
+ vgaw(ba, VDAC_COMMAND, 0x10); /* set ERPF */
+
+ /* switch to 8 bits per color */
+ vgaw(ba, VDAC_XINDEX, 8);
+ vgaw(ba, VDAC_XDATA, 1);
+ /* do not shift color values */
+ etcmap_shift = 0;
+
+ if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR));
+ vgaw(ba, VDAC_COMMAND, 0x00); /* clear ERPF */
+
+ vgaw(ba, VDAC_MASK, 0xff);
+ return(SIERRA15025);
+ }
+
+ /* check for MUSIC DAC */
+
+ if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR));
+ vgaw(ba, VDAC_COMMAND, 0x02); /* set some strange MUSIC mode (???) */
+
+ vgaw(ba, VDAC_XINDEX, 0x01);
+ if(vgar(ba, VDAC_XDATA) == 0x01){
+ /* shift color values by 2 */
+ etcmap_shift = 2;
+
+ vgaw(ba, VDAC_MASK, 0xff);
+ return(MUSICDAC);
+ }
+
+ /* nothing else found, so let us pretend it is a stupid Sierra SC 11483 */
+ /* shift color values by 2 */
+ etcmap_shift = 2;
+
+ vgaw(ba, VDAC_MASK, 0xff);
+ return(SIERRA11483);
+}
+
+#endif /* NGRFET */