diff options
Diffstat (limited to 'hw/kdrive/trident/trident.c')
-rw-r--r-- | hw/kdrive/trident/trident.c | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/hw/kdrive/trident/trident.c b/hw/kdrive/trident/trident.c new file mode 100644 index 000000000..384800f78 --- /dev/null +++ b/hw/kdrive/trident/trident.c @@ -0,0 +1,279 @@ +/* + * $Id$ + * + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* $XFree86: $ */ + +#include "trident.h" +#define extern +#include <asm/io.h> +#undef extern + +#undef TRI_DEBUG + +Bool +tridentCardInit (KdCardInfo *card) +{ + int k; + char *pixels; + TridentCardInfo *tridentc; + + tridentc = (TridentCardInfo *) xalloc (sizeof (TridentCardInfo)); + if (!tridentc) + return FALSE; + + if (!fbdevInitialize (card, &tridentc->fb)) + { + xfree (tridentc); + return FALSE; + } + + iopl (3); + tridentc->cop_base = (CARD8 *) KdMapDevice (TRIDENT_COP_BASE, + TRIDENT_COP_SIZE); + tridentc->cop = (Cop *) (tridentc->cop_base + TRIDENT_COP_OFF); + card->driver = tridentc; + + return TRUE; +} + +Bool +tridentScreenInit (KdScreenInfo *screen) +{ + TridentCardInfo *tridentc = screen->card->driver; + TridentScreenInfo *tridents; + int screen_size, memory; + + tridents = (TridentScreenInfo *) xalloc (sizeof (TridentScreenInfo)); + if (!tridents) + return FALSE; + memset (tridents, '\0', sizeof (TridentScreenInfo)); + if (!fbdevScreenInit (screen)) + { + xfree (tridents); + return FALSE; + } + if (!tridentc->cop) + screen->dumb = TRUE; + screen_size = screen->byteStride * screen->height; + memory = (2048 + 512) * 1024; + if (memory >= screen_size + 2048) + { + tridents->cursor_base = tridentc->fb.fb + memory - 2048; + } + else + tridents->cursor_base = 0; + screen->driver = tridents; + return TRUE; +} + +CARD8 +tridentReadIndex (TridentCardInfo *tridentc, CARD16 port, CARD8 index) +{ + CARD8 value; + + outb (index, port); + value = inb (port+1); + return value; +} + +void +tridentWriteIndex (TridentCardInfo *tridentc, CARD16 port, CARD8 index, CARD8 value) +{ + outb (index, port); + outb (value, port+1); +} + +void +tridentPause () +{ + struct timeval tv; + + tv.tv_sec = 0; + tv.tv_usec = 200 * 1000; + select (1, 0, 0, 0, &tv); +} + +void +tridentPreserve (KdCardInfo *card) +{ + TridentCardInfo *tridentc = card->driver; + + fbdevPreserve (card); + tridentc->save.reg_3c4_0e = tridentReadIndex (tridentc, 0x3c4, 0x0e); + tridentc->save.reg_3d4_36 = tridentReadIndex (tridentc, 0x3d4, 0x36); + tridentc->save.reg_3d4_39 = tridentReadIndex (tridentc, 0x3d4, 0x39); + tridentc->save.reg_3d4_62 = tridentReadIndex (tridentc, 0x3d4, 0x62); + tridentc->save.reg_3ce_21 = tridentReadIndex (tridentc, 0x3ce, 0x21); +#ifdef TRI_DEBUG + fprintf (stderr, "3c4 0e: %02x\n", tridentc->save.reg_3c4_0e); + fprintf (stderr, "3d4 36: %02x\n", tridentc->save.reg_3d4_36); + fprintf (stderr, "3d4 39: %02x\n", tridentc->save.reg_3d4_39); + fprintf (stderr, "3d4 62: %02x\n", tridentc->save.reg_3d4_62); + fprintf (stderr, "3ce 21: %02x\n", tridentc->save.reg_3ce_21); + fflush (stderr); +#endif + tridentPause (); +} + +void +tridentSetMMIO (TridentCardInfo *tridentc) +{ + int tries; + CARD8 v; + +#ifdef TRI_DEBUG + fprintf (stderr, "Set MMIO\n"); +#endif + /* enable config port writes */ + for (tries = 0; tries < 3; tries++) + { + /* enable direct read when GE busy, enable PCI retries */ + tridentWriteIndex (tridentc, 0x3d4, 0x62, + tridentc->save.reg_3d4_62 | 0x70); + /* make sure the chip is in new mode */ + tridentReadIndex (tridentc, 0x3c4, 0xb); + /* enable access to upper registers */ + tridentWriteIndex (tridentc, 0x3c4, 0xe, + tridentc->save.reg_3c4_0e | 0x80); + v = tridentReadIndex (tridentc, 0x3c4, 0xe); + if (!(v & 0x80)) + { + fprintf (stderr, "Trident GE not enabled 0x%x\n", v); + continue; + } + /* enable burst r/w, disable memory mapped ports */ + tridentWriteIndex (tridentc, 0x3d4, 0x39, 0x6); + /* reset GE, enable GE, set GE to 0xbff00 */ + tridentWriteIndex (tridentc, 0x3d4, 0x36, 0x92); + if (tridentc->cop->status != 0xffffffff) + break; + } +#ifdef TRI_DEBUG + fprintf (stderr, "COP status 0x%x\n", tridentc->cop->status); +#endif + if (tridentc->cop->status == 0xffffffff) + FatalError ("Trident COP not visible\n"); +} + +void +tridentResetMMIO (TridentCardInfo *tridentc) +{ +#ifdef TRI_DEBUG + fprintf (stderr, "Reset MMIO\n"); +#endif + tridentWriteIndex (tridentc, 0x3ce, 0x21, tridentc->save.reg_3ce_21); + tridentWriteIndex (tridentc, 0x3d4, 0x62, tridentc->save.reg_3d4_62); + tridentWriteIndex (tridentc, 0x3d4, 0x39, tridentc->save.reg_3d4_39); + tridentWriteIndex (tridentc, 0x3d4, 0x36, tridentc->save.reg_3d4_36); + tridentWriteIndex (tridentc, 0x3c4, 0x0e, tridentc->save.reg_3c4_0e); + tridentPause (); +} + +void +tridentEnable (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + TridentCardInfo *tridentc = pScreenPriv->card->driver; + + fbdevEnable (pScreen); + tridentSetMMIO (tridentc); +} + +void +tridentDisable (ScreenPtr pScreen) +{ + fbdevDisable (pScreen); +} + +const CARD8 tridentDPMSModes[4] = { + 0x80, /* KD_DPMS_NORMAL */ + 0x8c, /* KD_DPMS_STANDBY */ + 0x8c, /* KD_DPMS_STANDBY */ + 0x8c, /* KD_DPMS_STANDBY */ +/* 0xb0, /* KD_DPMS_SUSPEND */ +/* 0xbc, /* KD_DPMS_POWERDOWN */ +}; + +Bool +tridentDPMS (ScreenPtr pScreen, int mode) +{ + KdScreenPriv(pScreen); + TridentCardInfo *tridentc = pScreenPriv->card->driver; + + tridentWriteIndex (tridentc, 0x3ce, 0x21, tridentDPMSModes[mode]); + return TRUE; +} + +void +tridentRestore (KdCardInfo *card) +{ + TridentCardInfo *tridentc = card->driver; + + tridentResetMMIO (tridentc); + fbdevRestore (card); +} + +void +tridentScreenFini (KdScreenInfo *screen) +{ + TridentScreenInfo *tridents = (TridentScreenInfo *) screen->driver; + + xfree (tridents); + screen->driver = 0; +} + +void +tridentCardFini (KdCardInfo *card) +{ + TridentCardInfo *tridentc = card->driver; + + if (tridentc->cop_base) + KdUnmapDevice ((void *) tridentc->cop_base, TRIDENT_COP_SIZE); + fbdevCardFini (card); +} + +KdCardFuncs tridentFuncs = { + tridentCardInit, /* cardinit */ + tridentScreenInit, /* scrinit */ + tridentPreserve, /* preserve */ + tridentEnable, /* enable */ + tridentDPMS, /* dpms */ + tridentDisable, /* disable */ + tridentRestore, /* restore */ + tridentScreenFini, /* scrfini */ + tridentCardFini, /* cardfini */ + + tridentCursorInit, /* initCursor */ + tridentCursorEnable, /* enableCursor */ + tridentCursorDisable, /* disableCursor */ + tridentCursorFini, /* finiCursor */ + tridentRecolorCursor, /* recolorCursor */ + + tridentDrawInit, /* initAccel */ + tridentDrawEnable, /* enableAccel */ + tridentDrawDisable, /* disableAccel */ + tridentDrawFini, /* finiAccel */ + + fbdevGetColors, /* getColors */ + fbdevPutColors, /* putColors */ +}; |