summaryrefslogtreecommitdiff
path: root/hw/kdrive
diff options
context:
space:
mode:
authorDirk Hohndel <dirk.hohndel@intel.com>1999-11-19 13:54:06 +0000
committerDirk Hohndel <dirk.hohndel@intel.com>1999-11-19 13:54:06 +0000
commitf13b792a3a8d307a18cd6a41aa5a06622009e42f (patch)
tree5d7e7eb1dd3d69a9a408d0082c031c6121d625ea /hw/kdrive
3336. Fx up new MMIO macros (#3337, Matt Grossman).xf-3_9_16fxf-3_9_16exf-3_9_16dxf-3_9_16Z
3335. Clean up compiler warnings in lib/font/bitmap (#3411, Matt Grossman). 3334. TGA fixes, add sync on green (#3410, Matt Grossman). 3333. Fix NULL pointer dereference in libXaw (#3406, Christopher Sekiya). 3332. Add Rage128 support (#3405, Rik Faith, funded by ATI). 3331. Add MTRR support for NetBSD and OpenBSD. Add new NetBSD aperture driver (#3404, Matthieu Herrb). 3330. Xterm patch #121 (#3402, Thomas Dickey). 3329. Rendition driver bugfixes and alpha related cleanups (#3400, Dejan Ilic, Marc Langenbach, Egbert Eich). 3328. Add void input device (#3392, Frederic Lepied). 3327. Changed the Xon serial option to be able to select xon/xoff for input, output or both. Add support for Graphire models. Change wacom init phase to use new Xoff option (#3391, Frederic Lepied). 3326. Change the SwapAxes option to SwapXY in elographics/microtouch driver to match an already existing option in the Dynapro driver. Add a Focus class capability to the elographics driver (#3395, Patrick Lecoanet). 3325. Update mouse rate handling (#3388, Harald Koenig). 3324. Fix NULL pointer dereference in misprite.c (#3380, Edward Wang). 3323. Add FBDev and ShadowFB support to glint driver. Add new option "NoWriteBitmap" (#3383, Michel Daenzer). 3322. Update SuperProbe to handle S3 Savage4, Savage200 and clean up Trio3D/Savage3D detection (#3382,3384 Harald Koenig). 3321. Add new framebuffer code and tiny X DDX architecture (#3379, Keith Packard). 3320. Add DGA2 documentation (#3378, Mark Vojkovich). 3319. Update XFree86 manpage wrt -bpp/-depth/-fbbpp (#3377, Andy Isaacson). 3318. Make SuperProbe check primary cards, only (#3374, Harald Koenig). 3317. Add SilkenMouse to *BSD (#3373, Matthieu Herrb). 3316. Allow SilkenMouse to work if not all drivers of an OS support SIGIO (#3372, Keith Packard). 3315. Fix a few problems in TGA driver and add support for backing store and SilkenMouse (#3371, Matt Grossman). 3314. Add smarter scheduler (#3370, Keith Packard). 3313. Xterm patch #120 (#3369, Thomas Dickey). 3312. Enable xf86SetKbdRate function on Solaris 8 (#3364, David Holland). 3311. Fix some bugs and add acceleration to Rendition server (#3360, Dejan Ilic). 3310. Make raw DDC information available as properties in the root window (#3357, Andrew Aitchison). 3309. Fix for xf86CreateRootWindow (#3355, Andrew Aitchison). 3308. Add manpage for the chips driver (#3353, David Bateman). 3307. Update contact info (#3352, Andrew van der Stock). 3306. Add kbd rate support for Linux (#3363, Harald Koenig). 3305. Update Portuguese XKB map (#3351, Joao Esteves, Francisco Colaco). 3304. Fix text clipping in 3dfx driver (#3349, Henrik Harmsen). 3303. Fix S3 ViRGE hw cursor (#3348, Harald Koenig). 3302. Fix clipping in 3dfx driver (#3342, Daryll Strauss). 3301. Enable SilkenMouse for 3dfx driver (#3341, Henrik Harmsen). 3300. Enable SIGIO support on LynxOS (#3339, Thomas Mueller). 3299. Get TRUE defined in sigio.c. Fix xterm compile problem on ISC (#3338, Michael Rohleder). 3298. Correct DPMS suspend/standby modes for 3dfx driver (#3336, Henrik Harmsen) 3297. Xterm patch #119 (#3335, Thomas Dickey).
Diffstat (limited to 'hw/kdrive')
-rw-r--r--hw/kdrive/Imakefile20
-rw-r--r--hw/kdrive/fbdev/Imakefile15
-rw-r--r--hw/kdrive/fbdev/fbdev.c256
-rw-r--r--hw/kdrive/fbdev/fbdev.h81
-rw-r--r--hw/kdrive/fbdev/fbinit.c78
-rw-r--r--hw/kdrive/itsy/Imakefile15
-rw-r--r--hw/kdrive/itsy/itsy.c311
-rw-r--r--hw/kdrive/itsy/itsy.h42
-rw-r--r--hw/kdrive/itsy/kbd.c234
-rw-r--r--hw/kdrive/itsy/ts.c209
-rw-r--r--hw/kdrive/keyboard.c440
-rw-r--r--hw/kdrive/linux.c322
-rw-r--r--hw/kdrive/ps2.c132
-rw-r--r--hw/kdrive/savage/Imakefile15
-rw-r--r--hw/kdrive/savage/s3.c997
-rw-r--r--hw/kdrive/savage/s3.h545
-rw-r--r--hw/kdrive/savage/s3.nick41
-rw-r--r--hw/kdrive/savage/s3clock.c86
-rw-r--r--hw/kdrive/savage/s3cmap.c67
-rw-r--r--hw/kdrive/savage/s3curs.c418
-rw-r--r--hw/kdrive/savage/s3draw.c2334
-rw-r--r--hw/kdrive/savage/s3draw.h372
-rw-r--r--hw/kdrive/savage/s3gc.c388
-rw-r--r--hw/kdrive/savage/s3reg.c1144
-rw-r--r--hw/kdrive/savage/s3reg.h195
-rw-r--r--hw/kdrive/savage/s3rtst.c141
-rw-r--r--hw/kdrive/savage/s3stub.c60
-rw-r--r--hw/kdrive/sis530/Imakefile15
-rw-r--r--hw/kdrive/sis530/sis.c953
-rw-r--r--hw/kdrive/sis530/sis.h1152
-rw-r--r--hw/kdrive/sis530/sisclock.c232
-rw-r--r--hw/kdrive/sis530/siscmap.c64
-rw-r--r--hw/kdrive/sis530/siscurs.c364
-rw-r--r--hw/kdrive/sis530/sisdraw.c1656
-rw-r--r--hw/kdrive/sis530/sisdraw.h183
-rw-r--r--hw/kdrive/sis530/sisio.c30
-rw-r--r--hw/kdrive/sis530/sisstub.c53
-rw-r--r--hw/kdrive/src/kcmap.c231
-rw-r--r--hw/kdrive/src/kcolor.c883
-rw-r--r--hw/kdrive/src/kdrive.c872
-rw-r--r--hw/kdrive/src/kdrive.h362
-rw-r--r--hw/kdrive/src/kinfo.c110
-rw-r--r--hw/kdrive/src/kinput.c1331
-rw-r--r--hw/kdrive/src/kkeymap.c235
-rw-r--r--hw/kdrive/src/kkeymap.h53
-rw-r--r--hw/kdrive/src/kloadmap.c200
-rw-r--r--hw/kdrive/src/kmap.c86
-rw-r--r--hw/kdrive/src/knoop.c294
-rw-r--r--hw/kdrive/src/ktest.c76
-rw-r--r--hw/kdrive/src/vga.c288
-rw-r--r--hw/kdrive/src/vga.h132
-rw-r--r--hw/kdrive/trident/Imakefile15
-rw-r--r--hw/kdrive/trident/trident.c279
-rw-r--r--hw/kdrive/trident/trident.h205
-rw-r--r--hw/kdrive/trident/tridentcurs.c414
-rw-r--r--hw/kdrive/trident/tridentdraw.c859
-rw-r--r--hw/kdrive/trident/tridentdraw.h63
-rw-r--r--hw/kdrive/trident/tridentstub.c54
-rw-r--r--hw/kdrive/trio/Imakefile21
-rw-r--r--hw/kdrive/trio/s3.c1298
-rw-r--r--hw/kdrive/trio/s3.h1238
-rw-r--r--hw/kdrive/trio/s3clock.c89
-rw-r--r--hw/kdrive/trio/s3cmap.c70
-rw-r--r--hw/kdrive/trio/s3curs.c433
-rw-r--r--hw/kdrive/trio/s3stub.c59
-rw-r--r--hw/kdrive/ts300/Imakefile15
-rw-r--r--hw/kdrive/ts300/ts300.c131
67 files changed, 24056 insertions, 0 deletions
diff --git a/hw/kdrive/Imakefile b/hw/kdrive/Imakefile
new file mode 100644
index 000000000..0becea61a
--- /dev/null
+++ b/hw/kdrive/Imakefile
@@ -0,0 +1,20 @@
+XCOMM $XConsortium: Imakefile /main/10 1996/12/02 10:20:33 lehors $
+XCOMM $XFree86: xc/programs/Xserver/hw/nvfb/Imakefile,v 3.8 1996/12/23 06:30:19 dawes Exp $
+#include <Server.tmpl>
+
+SRCS = kcmap.c kcolor.c kdrive.c kinfo.c kinput.c kmap.c knoop.c ktest.c \
+ ps2.c keyboard.c linux.c vga.c
+
+OBJS = kcmap.o kcolor.o kdrive.o kinfo.o kinput.o kmap.o knoop.o ktest.o \
+ ps2.o keyboard.o linux.o vga.o
+
+INCLUDES = -I. -I$(XBUILDINCDIR) -I$(FONTINCSRC) \
+ -I../../fb -I../../mi -I../../include -I../../os \
+ -I$(EXTINCSRC) -I$(XINCLUDESRC)
+
+NormalLibraryObjectRule()
+NormalLibraryTarget(kdrive,$(OBJS))
+
+SpecialCObjectRule(kdrive,,$(EXT_DEFINES))
+
+DependTarget()
diff --git a/hw/kdrive/fbdev/Imakefile b/hw/kdrive/fbdev/Imakefile
new file mode 100644
index 000000000..3ffcfd5f0
--- /dev/null
+++ b/hw/kdrive/fbdev/Imakefile
@@ -0,0 +1,15 @@
+XCOMM $XConsortium: Imakefile /main/10 1996/12/02 10:20:33 lehors $
+XCOMM $XFree86: xc/programs/Xserver/hw/nvfb/Imakefile,v 3.8 1996/12/23 06:30:19 dawes Exp $
+#include <Server.tmpl>
+
+SRCS = fbdev.c fbinit.c
+
+OBJS = fbdev.o fbinit.o
+
+INCLUDES = -I.. -I. -I$(XBUILDINCDIR) -I$(FONTINCSRC) \
+ -I../../../fb -I../../../mi -I../../../include -I../../../os \
+ -I$(EXTINCSRC) -I$(XINCLUDESRC)
+
+NormalLibraryObjectRule()
+NormalLibraryTarget(fbdev,$(OBJS))
+DependTarget()
diff --git a/hw/kdrive/fbdev/fbdev.c b/hw/kdrive/fbdev/fbdev.c
new file mode 100644
index 000000000..c268ae2b1
--- /dev/null
+++ b/hw/kdrive/fbdev/fbdev.c
@@ -0,0 +1,256 @@
+/*
+ * $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 "fbdev.h"
+
+Bool
+fbdevInitialize (KdCardInfo *card, FbdevPriv *priv)
+{
+ int k;
+ if ((priv->fd = open("/dev/fb0", O_RDWR)) < 0) {
+ perror("Error opening /dev/fb0\n");
+ return FALSE;
+ }
+ if ((k=ioctl(priv->fd, FBIOGET_FSCREENINFO, &priv->fix)) < 0) {
+ perror("Error with /dev/fb ioctl FIOGET_FSCREENINFO");
+ close (priv->fd);
+ return FALSE;
+ }
+ if ((k=ioctl(priv->fd, FBIOGET_VSCREENINFO, &priv->var)) < 0) {
+ perror("Error with /dev/fb ioctl FIOGET_VSCREENINFO");
+ close (priv->fd);
+ return FALSE;
+ }
+
+ priv->fb = (unsigned char *) mmap ((caddr_t) NULL,
+ priv->fix.smem_len,
+ PROT_READ|PROT_WRITE,
+ MAP_SHARED,
+ priv->fd, 0);
+
+ if (priv->fb == (char *)-1)
+ {
+ perror("ERROR: mmap framebuffer fails!");
+ close (priv->fd);
+ return FALSE;
+ }
+}
+
+Bool
+fbdevCardInit (KdCardInfo *card)
+{
+ int k;
+ char *pixels;
+ FbdevPriv *priv;
+
+ priv = (FbdevPriv *) xalloc (sizeof (FbdevPriv));
+ if (!priv)
+ return FALSE;
+
+ if (!fbdevInitialize (card, priv))
+ {
+ xfree (priv);
+ return FALSE;
+ }
+ card->driver = priv;
+
+ return TRUE;
+}
+
+Bool
+fbdevScreenInit (KdScreenInfo *screen)
+{
+ FbdevPriv *priv = screen->card->driver;
+ Pixel allbits;
+ int depth;
+
+ screen->width = priv->var.xres;
+ screen->height = priv->var.yres;
+ screen->depth = priv->var.bits_per_pixel;
+ screen->bitsPerPixel = priv->var.bits_per_pixel;
+ screen->byteStride = priv->fix.line_length;
+ screen->pixelStride = (priv->fix.line_length * 8 /
+ priv->var.bits_per_pixel);
+ switch (priv->fix.visual) {
+ case FB_VISUAL_PSEUDOCOLOR:
+ screen->visuals = ((1 << StaticGray) |
+ (1 << GrayScale) |
+ (1 << StaticColor) |
+ (1 << PseudoColor) |
+ (1 << TrueColor) |
+ (1 << DirectColor));
+ screen->blueMask = 0x00;
+ screen->greenMask = 0x00;
+ screen->redMask = 0x00;
+ break;
+ case FB_VISUAL_TRUECOLOR:
+ screen->visuals = (1 << TrueColor);
+ screen->redMask = FbStipMask (priv->var.red.offset, priv->var.red.length);
+ screen->greenMask = FbStipMask (priv->var.green.offset, priv->var.green.length);
+ screen->blueMask = FbStipMask (priv->var.blue.offset, priv->var.blue.length);
+ allbits = screen->redMask | screen->greenMask | screen->blueMask;
+ depth = 32;
+ while (depth && !(allbits & (1 << (depth - 1))))
+ depth--;
+ screen->depth = depth;
+ break;
+ default:
+ return FALSE;
+ break;
+ }
+ screen->rate = 72;
+ screen->frameBuffer = (CARD8 *) (priv->fb);
+ return TRUE;
+}
+
+void
+fbdevPreserve (KdCardInfo *card)
+{
+}
+
+void
+fbdevEnable (ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ FbdevPriv *priv = pScreenPriv->card->driver;
+ int k;
+
+ priv->var.activate = FB_ACTIVATE_NOW|FB_CHANGE_CMAP_VBL;
+
+ /* display it on the LCD */
+ k = ioctl (priv->fd, FBIOPUT_VSCREENINFO, &priv->var);
+ if (k < 0)
+ perror ("FBIOPUT_VSCREENINFO");
+}
+
+Bool
+fbdevDPMS (ScreenPtr pScreen, int mode)
+{
+ KdScreenPriv(pScreen);
+ FbdevPriv *priv = pScreenPriv->card->driver;
+
+ if (!ioctl (priv->fd, FBIOPUT_POWERMODE, &mode))
+ return TRUE;
+ return FALSE;
+}
+
+void
+fbdevDisable (ScreenPtr pScreen)
+{
+}
+
+void
+fbdevRestore (KdCardInfo *card)
+{
+}
+
+void
+fbdevScreenFini (KdScreenInfo *screen)
+{
+}
+
+void
+fbdevCardFini (KdCardInfo *card)
+{
+ int k;
+ FbdevPriv *priv = card->driver;
+
+ munmap (priv->fb, priv->fix.smem_len);
+ close (priv->fd);
+ xfree (priv);
+}
+
+void
+fbdevGetColors (ScreenPtr pScreen, int n, xColorItem *pdefs)
+{
+ KdScreenPriv(pScreen);
+ FbdevPriv *priv = pScreenPriv->card->driver;
+ struct fb_cmap cmap;
+ int p;
+ int k;
+ int min, max;
+
+ min = 256;
+ max = 0;
+ for (k = 0; k < n; k++)
+ {
+ if (pdefs[k].pixel < min)
+ min = pdefs[k].pixel;
+ if (pdefs[k].pixel > max)
+ max = pdefs[k].pixel;
+ }
+ cmap.start = min;
+ cmap.len = max - min + 1;
+ cmap.red = &priv->red[min];
+ cmap.green = &priv->green[min];;
+ cmap.blue = &priv->blue[min];
+ cmap.transp = 0;
+ k = ioctl (priv->fd, FBIOGETCMAP, &cmap);
+ if (k < 0)
+ {
+ perror ("can't get colormap");
+ return;
+ }
+ while (n--)
+ {
+ p = pdefs->pixel;
+ pdefs->red = priv->red[p];
+ pdefs->green = priv->green[p];
+ pdefs->blue = priv->blue[p];
+ pdefs++;
+ }
+}
+
+void
+fbdevPutColors (ScreenPtr pScreen, int n, xColorItem *pdefs)
+{
+ KdScreenPriv(pScreen);
+ FbdevPriv *priv = pScreenPriv->card->driver;
+ struct fb_cmap cmap;
+ int p;
+ int min, max;
+
+ min = 256;
+ max = 0;
+ while (n--)
+ {
+ p = pdefs->pixel;
+ priv->red[p] = pdefs->red;
+ priv->green[p] = pdefs->green;
+ priv->blue[p] = pdefs->blue;
+ if (p < min)
+ min = p;
+ if (p > max)
+ max = p;
+ pdefs++;
+ }
+ cmap.start = min;
+ cmap.len = max - min + 1;
+ cmap.red = &priv->red[min];
+ cmap.green = &priv->green[min];
+ cmap.blue = &priv->blue[min];
+ cmap.transp = 0;
+ ioctl (priv->fd, FBIOPUTCMAP, &cmap);
+}
diff --git a/hw/kdrive/fbdev/fbdev.h b/hw/kdrive/fbdev/fbdev.h
new file mode 100644
index 000000000..46c8bb2ef
--- /dev/null
+++ b/hw/kdrive/fbdev/fbdev.h
@@ -0,0 +1,81 @@
+/*
+ * $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: $ */
+
+#ifndef _FBDEV_H_
+#define _FBDEV_H_
+#include "kdrive.h"
+#include <stdio.h>
+#include <linux/fb.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+typedef struct _fbdevPriv {
+ struct fb_var_screeninfo var;
+ struct fb_fix_screeninfo fix;
+ __u16 red[256];
+ __u16 green[256];
+ __u16 blue[256];
+ int fd;
+ char *fb;
+} FbdevPriv;
+
+Bool
+fbdevInitialize (KdCardInfo *card, FbdevPriv *priv);
+
+Bool
+fbdevCardInit (KdCardInfo *card);
+
+Bool
+fbdevScreenInit (KdScreenInfo *screen);
+
+void
+fbdevPreserve (KdCardInfo *card);
+
+void
+fbdevEnable (ScreenPtr pScreen);
+
+Bool
+fbdevDPMS (ScreenPtr pScreen, int mode);
+
+void
+fbdevDisable (ScreenPtr pScreen);
+
+void
+fbdevRestore (KdCardInfo *card);
+
+void
+fbdevScreenFini (KdScreenInfo *screen);
+
+void
+fbdevCardFini (KdCardInfo *card);
+
+void
+fbdevGetColors (ScreenPtr pScreen, int n, xColorItem *pdefs);
+
+void
+fbdevPutColors (ScreenPtr pScreen, int n, xColorItem *pdefs);
+
+
+#endif /* _FBDEV_H_ */
diff --git a/hw/kdrive/fbdev/fbinit.c b/hw/kdrive/fbdev/fbinit.c
new file mode 100644
index 000000000..ea1439145
--- /dev/null
+++ b/hw/kdrive/fbdev/fbinit.c
@@ -0,0 +1,78 @@
+/*
+ * $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 <fbdev.h>
+
+KdCardFuncs fbdevFuncs = {
+ fbdevCardInit, /* cardinit */
+ fbdevScreenInit, /* scrinit */
+ fbdevPreserve, /* preserve */
+ fbdevEnable, /* enable */
+ fbdevDPMS, /* dpms */
+ fbdevDisable, /* disable */
+ fbdevRestore, /* restore */
+ fbdevScreenFini, /* scrfini */
+ fbdevCardFini, /* cardfini */
+
+ 0, /* initCursor */
+ 0, /* enableCursor */
+ 0, /* disableCursor */
+ 0, /* finiCursor */
+ 0, /* recolorCursor */
+
+ 0, /* initAccel */
+ 0, /* enableAccel */
+ 0, /* disableAccel */
+ 0, /* finiAccel */
+
+ fbdevGetColors, /* getColors */
+ fbdevPutColors, /* putColors */
+};
+
+void
+InitCard (char *name)
+{
+ KdCardAttr attr;
+
+ KdCardInfoAdd (&fbdevFuncs, &attr, 0);
+}
+
+void
+InitOutput (ScreenInfo *pScreenInfo, int argc, char **argv)
+{
+ KdInitOutput (pScreenInfo, argc, argv);
+}
+
+void
+InitInput (int argc, char **argv)
+{
+ KdInitInput (&Ps2MouseFuncs, &LinuxKeyboardFuncs);
+}
+
+void
+OsVendorInit (void)
+{
+ KdOsInit (&LinuxFuncs);
+}
diff --git a/hw/kdrive/itsy/Imakefile b/hw/kdrive/itsy/Imakefile
new file mode 100644
index 000000000..98e4a41a9
--- /dev/null
+++ b/hw/kdrive/itsy/Imakefile
@@ -0,0 +1,15 @@
+XCOMM $XConsortium: Imakefile /main/10 1996/12/02 10:20:33 lehors $
+XCOMM $XFree86: xc/programs/Xserver/hw/nvfb/Imakefile,v 3.8 1996/12/23 06:30:19 dawes Exp $
+#include <Server.tmpl>
+
+SRCS = itsy.c ts.c kbd.c
+
+OBJS = itsy.o ts.o kbd.o
+
+INCLUDES = -I.. -I. -I$(XBUILDINCDIR) -I$(FONTINCSRC) \
+ -I../../../fb -I../../../mi -I../../../include -I../../../os \
+ -I$(EXTINCSRC) -I$(XINCLUDESRC)
+
+NormalLibraryObjectRule()
+NormalLibraryTarget(itsy,$(OBJS))
+DependTarget()
diff --git a/hw/kdrive/itsy/itsy.c b/hw/kdrive/itsy/itsy.c
new file mode 100644
index 000000000..68ce60aaa
--- /dev/null
+++ b/hw/kdrive/itsy/itsy.c
@@ -0,0 +1,311 @@
+/*
+ * $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 "itsy.h"
+
+/* struct with LCD characteristics defined in fb_brutus.h */
+static struct FbLcdParamsStruct fbLcdParams;
+static int fb_d;
+static int fbn;
+Bool
+itsyCardInit (KdCardInfo *card)
+{
+ int k;
+ char *fb;
+ char *pixels;
+
+ if ((fb_d = open("/dev/fbclone", O_RDWR)) < 0) {
+ perror("Error opening /dev/fb\n");
+ return FALSE;
+ }
+ if ((k=ioctl(fb_d, FB_LCD_PARAMS, &fbLcdParams)) != 0) {
+ perror("Error with /dev/fb ioctl FB_LCD_PARAMS call");
+ return FALSE;
+ }
+
+ fb = (char *) mmap ((caddr_t) NULL, fbLcdParams.frameBufferSize,
+ PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, fb_d, 0);
+
+ fprintf (stderr, "fb mapped at 0x%x\n", fb);
+ if (fb == (char *)-1) {
+ perror("ERROR: mmap framebuffer fails!");
+ return FALSE;
+ }
+
+ card->driver = fb;
+
+ return TRUE;
+}
+
+Bool
+itsyScreenInit (KdScreenInfo *screen)
+{
+ CARD8 *fb = screen->card->driver;
+
+ screen->width = fbLcdParams.screenSizeH;
+ screen->height = fbLcdParams.screenSizeV;
+ screen->depth = fbLcdParams.bitsPerPixel;
+ screen->bitsPerPixel = fbLcdParams.bitsPerPixel;
+ screen->byteStride = fbLcdParams.frameBufferSizeH;
+ screen->pixelStride = (fbLcdParams.frameBufferSizeH * 8 /
+ fbLcdParams.bitsPerPixel);
+ fprintf (stderr, "width %d height %d depth %d pstride %d bstride %d\n",
+ screen->width, screen->height, screen->depth,
+ screen->pixelStride, screen->byteStride);
+ screen->dumb = FALSE;
+ screen->softCursor = TRUE;
+ screen->blueMask = 0;
+ screen->greenMask = 0;
+ screen->redMask = 0;
+ screen->visuals = 1 << StaticGray;
+ screen->rate = 72;
+ screen->frameBuffer = (CARD8 *) (fb +
+ fbLcdParams.pixelDataOffset +
+ (fbLcdParams.reserveTopRows *
+ screen->byteStride));
+ fprintf (stderr, "Frame buffer 0x%x\n", screen->frameBuffer);
+ return TRUE;
+}
+
+void
+itsyPreserve (KdCardInfo *card)
+{
+}
+
+void
+itsyEnable (ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+
+ fprintf (stderr, "Enabling LCD display\n");
+ /* display it on the LCD */
+ ioctl(fb_d, FB_LCD_SHOW, 0);
+}
+
+Bool
+itsyDPMS (ScreenPtr pScreen, int mode)
+{
+ if (mode)
+ ioctl (fb_d, FB_LCD_OFF, 0);
+ else
+ ioctl (fb_d, FB_LCD_ON, 0);
+ return TRUE;
+}
+
+void
+itsyDisable (ScreenPtr pScreen)
+{
+/* ioctl (fb_d, FB_LCD_SWITCH, 0); */
+/* fprintf (stderr, "Disabling LCD display\n");*/
+}
+
+void
+itsyRestore (KdCardInfo *card)
+{
+}
+
+void
+itsyScreenFini (KdScreenInfo *screen)
+{
+}
+
+void
+itsyCardFini (KdCardInfo *card)
+{
+ int k;
+
+ fprintf (stderr, "Unmapping driver at 0x%x\n", card->driver);
+ munmap (card->driver, fbLcdParams.frameBufferSize);
+ fprintf (stderr, "Releasing fbn %d\n", fbn);
+ /* release it */
+ if (ioctl(fb_d, FB_LCD_FREE, fbn) != 0) {
+ printf("FB_LCD_FREE of %d fails!\n", fbn);
+ }
+ close (fb_d);
+ fprintf (stderr, "itsyFini done\n");
+}
+
+static unsigned short itsyIntensity[16] = {
+ 0xffff,
+ 0xffff,
+ 0xedb6,
+ 0xdb6d,
+ 0xc924,
+ 0xb6db,
+ 0xa492,
+ 0x9249,
+ 0x8000,
+ 0x6db6,
+ 0x5b6d,
+ 0x4924,
+ 0x36db,
+ 0x2492,
+ 0x1249,
+ 0x0000,
+};
+
+Bool
+itsyCreateColormap (ColormapPtr pmap)
+{
+ int i;
+
+ for (i = 0; i < 16; i++)
+ {
+ pmap->red[i].co.local.red = itsyIntensity[i];
+ pmap->red[i].co.local.green = itsyIntensity[i];
+ pmap->red[i].co.local.blue = itsyIntensity[i];
+ }
+ return TRUE;
+}
+
+Bool
+itsySetupScreen (ScreenPtr pScreen)
+{
+ pScreen->CreateColormap = itsyCreateColormap;
+ return FALSE;
+}
+
+KdCardFuncs itsyFuncs = {
+ itsyCardInit, /* cardinit */
+ itsyScreenInit, /* scrinit */
+ itsyPreserve, /* preserve */
+ itsyEnable, /* enable */
+ itsyDPMS, /* dpms */
+ itsyDisable, /* disable */
+ itsyRestore, /* restore */
+ itsyScreenFini, /* scrfini */
+ itsyCardFini, /* cardfini */
+
+ 0, /* initCursor */
+ 0, /* enableCursor */
+ 0, /* disableCursor */
+ 0, /* finiCursor */
+ 0, /* recolorCursor */
+
+ itsySetupScreen, /* initAccel */
+ 0, /* enableAccel */
+ 0, /* disableAccel */
+ 0, /* finiAccel */
+
+ 0, /* getColors */
+ 0, /* putColors */
+};
+
+void
+InitCard (void)
+{
+ KdCardAttr attr;
+
+ KdCardInfoAdd (&itsyFuncs, &attr, 0);
+}
+
+void
+InitOutput (ScreenInfo *pScreenInfo, int argc, char **argv)
+{
+ KdInitOutput (pScreenInfo, argc, argv);
+}
+
+void
+InitInput (int argc, char **argv)
+{
+ KdInitInput (&itsyTsMouseFuncs, &itsyKeyboardFuncs);
+}
+
+int itsySessionFd = -1;
+
+int
+ItsyOsInit (void)
+{
+ pid_t sid;
+ int i;
+ itsy_session_info info;
+
+ if (itsySessionFd < 0)
+ {
+ itsySessionFd = open ("/dev/session", 0);
+ ErrorF("itsySessionFD %d\n", itsySessionFd);
+ }
+
+ (void) setsid ();
+ sid = getsid (0);
+ ErrorF ("Session ID %d PID %d\n", sid, getpid ());
+ info.sid = sid;
+ strcpy (info.name, "X");
+ if (itsySessionFd >= 0)
+ {
+ i = ioctl (itsySessionFd, SESSION_SET_INFO, &info);
+ if (i < 0)
+ perror ("SESSION_SET_INFO");
+ }
+ return 1;
+}
+
+void
+ItsyOsEnable (void)
+{
+ itsy_session_request req;
+ int i;
+
+#define MANAGER_SID_TO_FOREGROUND 2
+
+ req.operation = MANAGER_SID_TO_FOREGROUND;
+ req.data = 0;
+ if (itsySessionFd >= 0)
+ {
+ i = ioctl (itsySessionFd, SESSION_MANAGER_REQUEST, &req);
+ if (i < 0)
+ perror ("SESSION_MANAGER_REQUEST");
+ }
+}
+
+Bool
+ItsyOsSpecialKey (KeySym sym)
+{
+ return FALSE;
+}
+
+void
+ItsyOsDisable (void)
+{
+}
+
+void
+ItsyOsFini (void)
+{
+}
+
+KdOsFuncs ItsyOsFuncs = {
+ ItsyOsInit,
+ ItsyOsEnable,
+ ItsyOsSpecialKey,
+ ItsyOsDisable,
+ ItsyOsFini,
+};
+
+void
+OsVendorInit (void)
+{
+ KdOsInit (&ItsyOsFuncs);
+}
diff --git a/hw/kdrive/itsy/itsy.h b/hw/kdrive/itsy/itsy.h
new file mode 100644
index 000000000..86ebb9105
--- /dev/null
+++ b/hw/kdrive/itsy/itsy.h
@@ -0,0 +1,42 @@
+/*
+ * $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 "kdrive.h"
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <linux/itsy_fb.h>
+#include <linux/itsy_ts.h>
+#include <linux/itsy_buttons.h>
+#include <linux/itsy_session.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+#define FB_HEIGHT 200
+#define FB_WIDTH 320
+#define FB_DEPTH 4
+#define FB_PALETTE_SIZE 16
+
+extern KdMouseFuncs itsyTsMouseFuncs;
+extern KdKeyboardFuncs itsyKeyboardFuncs;
diff --git a/hw/kdrive/itsy/kbd.c b/hw/kdrive/itsy/kbd.c
new file mode 100644
index 000000000..ef7897a15
--- /dev/null
+++ b/hw/kdrive/itsy/kbd.c
@@ -0,0 +1,234 @@
+/*
+ * $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 "itsy.h"
+#include "kkeymap.h"
+#include <X11/keysym.h>
+#include <linux/itsy_buttons.h>
+
+#define ITSY_WIDTH 2
+
+KeySym ItsyKeymap[] = {
+/* 1 8 */ XK_Escape, NoSymbol,
+/* 2 9 */ XK_1, XK_exclam,
+/* 3 10 */ XK_2, XK_at,
+/* 4 11 */ XK_3, XK_numbersign,
+/* 5 12 */ XK_4, XK_dollar,
+/* 6 13 */ XK_5, XK_percent,
+/* 7 14 */ XK_6, XK_asciicircum,
+/* 8 15 */ XK_7, XK_ampersand,
+/* 9 16 */ XK_8, XK_asterisk,
+/* 10 17 */ XK_9, XK_parenleft,
+/* 11 18 */ XK_0, XK_parenright,
+/* 12 19 */ XK_minus, XK_underscore,
+/* 13 20 */ XK_equal, XK_plus,
+/* 14 21 */ XK_BackSpace, NoSymbol,
+/* 15 22 */ XK_Tab, NoSymbol,
+/* 16 23 */ XK_Q, NoSymbol,
+/* 17 24 */ XK_W, NoSymbol,
+/* 18 25 */ XK_E, NoSymbol,
+/* 19 26 */ XK_R, NoSymbol,
+/* 20 27 */ XK_T, NoSymbol,
+/* 21 28 */ XK_Y, NoSymbol,
+/* 22 29 */ XK_U, NoSymbol,
+/* 23 30 */ XK_I, NoSymbol,
+/* 24 31 */ XK_O, NoSymbol,
+/* 25 32 */ XK_P, NoSymbol,
+/* 26 33 */ XK_bracketleft, XK_braceleft,
+/* 27 34 */ XK_bracketright, XK_braceright,
+/* 28 35 */ XK_Return, NoSymbol,
+/* 29 36 */ XK_Control_L, NoSymbol,
+/* 30 37 */ XK_A, NoSymbol,
+/* 31 38 */ XK_S, NoSymbol,
+/* 32 39 */ XK_D, NoSymbol,
+/* 33 40 */ XK_F, NoSymbol,
+/* 34 41 */ XK_G, NoSymbol,
+/* 35 42 */ XK_H, NoSymbol,
+/* 36 43 */ XK_J, NoSymbol,
+/* 37 44 */ XK_K, NoSymbol,
+/* 38 45 */ XK_L, NoSymbol,
+/* 39 46 */ XK_semicolon, XK_colon,
+/* 40 47 */ XK_apostrophe, XK_quotedbl,
+/* 41 48 */ XK_grave, XK_asciitilde,
+/* 42 49 */ XK_Shift_L, NoSymbol,
+/* 43 50 */ XK_backslash, XK_bar,
+/* 44 51 */ XK_Z, NoSymbol,
+/* 45 52 */ XK_X, NoSymbol,
+/* 46 53 */ XK_C, NoSymbol,
+/* 47 54 */ XK_V, NoSymbol,
+/* 48 55 */ XK_B, NoSymbol,
+/* 49 56 */ XK_N, NoSymbol,
+/* 50 57 */ XK_M, NoSymbol,
+/* 51 58 */ XK_comma, XK_less,
+/* 52 59 */ XK_period, XK_greater,
+/* 53 60 */ XK_slash, XK_question,
+/* 54 61 */ XK_Shift_R, NoSymbol,
+/* 55 62 */ XK_KP_Multiply, NoSymbol,
+/* 56 63 */ XK_Alt_L, XK_Meta_L,
+/* 57 64 */ XK_space, NoSymbol,
+/* 58 65 */ XK_Caps_Lock, NoSymbol,
+/* 59 66 */ XK_F1, NoSymbol,
+/* 60 67 */ XK_F2, NoSymbol,
+/* 61 68 */ XK_F3, NoSymbol,
+/* 62 69 */ XK_F4, NoSymbol,
+/* 63 70 */ XK_F5, NoSymbol,
+/* 64 71 */ XK_F6, NoSymbol,
+/* 65 72 */ XK_F7, NoSymbol,
+/* 66 73 */ XK_F8, NoSymbol,
+/* 67 74 */ XK_F9, NoSymbol,
+/* 68 75 */ XK_F10, NoSymbol,
+/* 69 76 */ XK_Break, XK_Pause,
+/* 70 77 */ XK_Scroll_Lock, NoSymbol,
+/* 71 78 */ XK_KP_Home, XK_KP_7,
+/* 72 79 */ XK_KP_Up, XK_KP_8,
+/* 73 80 */ XK_KP_Page_Up, XK_KP_9,
+/* 74 81 */ XK_KP_Subtract, NoSymbol,
+/* 75 82 */ XK_KP_Left, XK_KP_4,
+/* 76 83 */ XK_KP_5, NoSymbol,
+/* 77 84 */ XK_KP_Right, XK_KP_6,
+/* 78 85 */ XK_KP_Add, NoSymbol,
+/* 79 86 */ XK_KP_End, XK_KP_1,
+/* 80 87 */ XK_KP_Down, XK_KP_2,
+/* 81 88 */ XK_KP_Page_Down, XK_KP_3,
+/* 82 89 */ XK_KP_Insert, XK_KP_0,
+/* 83 90 */ XK_KP_Delete, XK_KP_Decimal,
+/* 84 91 */ NoSymbol, NoSymbol,
+/* 85 92 */ NoSymbol, NoSymbol,
+/* 86 93 */ NoSymbol, NoSymbol,
+/* 87 94 */ XK_F11, NoSymbol,
+/* 88 95 */ XK_F12, NoSymbol,
+
+/* These are remapped from the extended set (using ExtendMap) */
+
+/* 89 96 */ XK_Control_R, NoSymbol,
+/* 90 97 */ XK_KP_Enter, NoSymbol,
+/* 91 98 */ XK_KP_Divide, NoSymbol,
+/* 92 99 */ XK_Sys_Req, XK_Print,
+/* 93 100 */ XK_Alt_R, XK_Meta_R,
+/* 94 101 */ XK_Num_Lock, NoSymbol,
+/* 95 102 */ XK_Home, NoSymbol,
+/* 96 103 */ XK_Up, NoSymbol,
+/* 97 104 */ XK_Page_Up, NoSymbol,
+/* 98 105 */ XK_Left, NoSymbol,
+/* 99 106 */ XK_Right, NoSymbol,
+/* 100 107 */ XK_End, NoSymbol,
+/* 101 108 */ XK_Down, NoSymbol,
+/* 102 109 */ XK_Page_Down, NoSymbol,
+/* 103 110 */ XK_Insert, NoSymbol,
+/* 104 111 */ XK_Delete, NoSymbol,
+/* 105 112 */ XK_Super_L, NoSymbol,
+/* 106 113 */ XK_Super_R, NoSymbol,
+/* 107 114 */ XK_Menu, NoSymbol,
+
+/* Itsy hardware buttons */
+#define ITSY_BUTTON_FIRST 108
+#define ITSY_BUTTON_LAST 116
+
+/* 108 115 */ XK_Next, NoSymbol, /* right button on side */
+/* 109 116 */ XK_Prior, NoSymbol, /* left button on side */
+/* 110 117 */ XK_Up, NoSymbol, /* joypad */
+/* 111 118 */ XK_Down, NoSymbol,
+/* 112 119 */ XK_Left, NoSymbol,
+/* 113 120 */ XK_Right, NoSymbol,
+/* 114 121 */ NoSymbol, NoSymbol, /* left near speaker */
+/* 115 122 */ NoSymbol, NoSymbol, /* right near speaker */
+/* 116 123 */ NoSymbol, NoSymbol, /* tiny button */
+};
+
+static unsigned long itsyButtonState;
+
+void
+ItsyKeyboardLoad (void)
+{
+ KeySym *k;
+
+ itsyButtonState = 0;
+ kdMinScanCode = 1;
+ kdKeymapWidth = ITSY_WIDTH;
+ kdMaxScanCode = (sizeof (ItsyKeymap) / sizeof (ItsyKeymap[0])) / ITSY_WIDTH;
+ memcpy (kdKeymap, ItsyKeymap, sizeof (ItsyKeymap));
+}
+
+int
+ItsyKeyboardInit (void)
+{
+ int butPort;
+
+ butPort = open ("/dev/buttons", 0);
+ fprintf (stderr, "butPort %d\n", butPort);
+ return butPort;
+}
+
+void
+ItsyKeyboardFini (int fd)
+{
+ if (fd >= 0)
+ close (fd);
+}
+
+void
+ItsyKeyboardRead (int fd)
+{
+ itsy_buttons_event event;
+ int b;
+ unsigned long bit;
+ unsigned long change;
+ unsigned long buttons;
+
+ if (read (fd, &event, sizeof (event)) == sizeof (event))
+ {
+ buttons = event.state;
+ change = buttons ^ itsyButtonState;
+ if (!change)
+ return;
+ for (b = ITSY_BUTTON_FIRST; b <= ITSY_BUTTON_LAST; b++)
+ {
+ bit = (1 << (b - ITSY_BUTTON_FIRST));
+ if (change & bit)
+ KdEnqueueKeyboardEvent (b, (buttons & bit) == 0);
+ }
+ itsyButtonState = buttons;
+ }
+}
+
+void
+ItsyKeyboardLeds (int leds)
+{
+}
+
+void
+ItsyKeyboardBell (int volume, int frequency, int duration)
+{
+}
+
+KdKeyboardFuncs itsyKeyboardFuncs = {
+ ItsyKeyboardLoad,
+ ItsyKeyboardInit,
+ ItsyKeyboardRead,
+ ItsyKeyboardLeds,
+ ItsyKeyboardBell,
+ ItsyKeyboardFini,
+ 0,
+};
diff --git a/hw/kdrive/itsy/ts.c b/hw/kdrive/itsy/ts.c
new file mode 100644
index 000000000..24bf24ecd
--- /dev/null
+++ b/hw/kdrive/itsy/ts.c
@@ -0,0 +1,209 @@
+/*
+ * $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: $ */
+
+#define NEED_EVENTS
+#include "itsy.h"
+#include "Xproto.h"
+#include "inputstr.h"
+#include "Xpoll.h"
+
+int
+itsyTsReadBytes (int fd, char *buf, int len, int min)
+{
+ int n, tot;
+ fd_set set;
+ struct timeval tv;
+
+ tot = 0;
+ while (len)
+ {
+ n = read (fd, buf, len);
+ if (n > 0)
+ {
+ tot += n;
+ buf += n;
+ len -= n;
+ }
+ if (tot % min == 0)
+ break;
+ FD_ZERO (&set);
+ FD_SET (fd, &set);
+ tv.tv_sec = 0;
+ tv.tv_usec = 100 * 1000;
+ n = select (fd + 1, &set, 0, 0, &tv);
+ if (n <= 0)
+ break;
+ }
+ return tot;
+}
+
+void
+itsyTsRead (int tsPort)
+{
+ ts_event event;
+ long buf[3];
+ int n;
+ long pressure;
+ long x, y;
+ unsigned long flags;
+ unsigned long buttons;
+
+ n = itsyTsReadBytes (tsPort, (char *) &event,
+ sizeof (event), sizeof (event));
+ if (n == sizeof (event))
+ {
+ if (event.pressure)
+ {
+ flags = KD_BUTTON_1;
+ x = event.point.x;
+ y = event.point.y;
+ }
+ else
+ {
+ flags = KD_MOUSE_DELTA;
+ x = 0;
+ y = 0;
+ }
+ KdEnqueueMouseEvent (flags, x, y);
+ }
+}
+
+#if 0
+#define ITSY_DEBUG_LOW 1
+
+//
+// Touch screen parameters are stored
+// in the flash. This code is taken from 'wm1'.
+//
+void itsySetTouchCalibration (int mou_filedsc,
+ int xs, int xt, int ys, int yt, int xys)
+{
+ int k, ibuf[10];
+
+ ibuf[0] = xs;
+ ibuf[1] = xt;
+ ibuf[2] = ys;
+ ibuf[3] = yt;
+ ibuf[4] = xys;
+ if ((k=ioctl(mou_filedsc, TS_SET_CALM, ibuf)) != 0) {
+ fprintf(stderr, "ERROR: ioctl TS_SET_CALM returns %d\n", k);
+ }
+}
+
+
+int itsyReadFlashBlock(int location, signed char *data, int dbytes)
+{
+ int offset, bytes;
+ int flashfd;
+
+ flashfd = open("/dev/flash1", O_RDONLY);
+ if (flashfd < 0) return(0);
+
+ offset = lseek(flashfd, location, SEEK_SET);
+ if (offset != location) {
+ close(flashfd);
+ return(0);
+ }
+
+ bytes = read(flashfd, data, dbytes);
+ if (bytes != dbytes) {
+ close(flashfd);
+ return(0);
+ }
+
+ close(flashfd);
+ return(1);
+}
+
+/**********************************************************************/
+#define RAMSIZE (0x400000)
+#define MONITOR_BLOCKSIZE (32)
+/**********************************************************************/
+
+/* code for storing calibration into flash */
+
+#define CALIBRATE_BLOCKSIZE (32)
+#define CALIBRATE_OFFSET (RAMSIZE-MONITOR_BLOCKSIZE-CALIBRATE_BLOCKSIZE)
+#define CALIBRATE_MAGIC_NUM (0x0babedee)
+
+
+static int check_if_calibrated_and_set(int mou_filedsc)
+{
+ signed char cal_data[CALIBRATE_BLOCKSIZE];
+ int *iptr;
+
+ if (itsyReadFlashBlock(CALIBRATE_OFFSET,
+ cal_data, CALIBRATE_BLOCKSIZE) == 0) {
+ if ( ITSY_DEBUG_LOW ) {
+ fprintf(stderr,"unable to read calibration data for touch screen\n");
+ }
+ return(0);
+ }
+
+ iptr = (int *) cal_data;
+ if (iptr[0] == CALIBRATE_MAGIC_NUM) {
+ if ( ITSY_DEBUG_LOW ) {
+ fprintf(stderr,"Calibrating touch screen using %d, %d, %d, %d, %d\n",
+ iptr[1], iptr[2], iptr[3], iptr[4], iptr[5]);
+ }
+ itsySetTouchCalibration(mou_filedsc, iptr[1], iptr[2], iptr[3], iptr[4], iptr[5]);
+ return(1);
+ }
+ else {
+ if ( ITSY_DEBUG_LOW ) {
+ fprintf(stderr,"Couldn't calibrate screen\n");
+ }
+ return(0);
+ }
+}
+#endif
+
+int
+itsyTsInit (void)
+{
+ int tsPort;
+
+ tsPort = open ("/dev/ts", 0);
+ fprintf (stderr, "tsPort %d\n", tsPort);
+#if 0
+ if (tsPort >= 0)
+ check_if_calibrated_and_set (tsPort);
+#endif
+ return tsPort;
+}
+
+void
+itsyTsFini (int tsPort)
+{
+ if (tsPort >= 0)
+ close (tsPort);
+}
+
+KdMouseFuncs itsyTsMouseFuncs = {
+ itsyTsInit,
+ itsyTsRead,
+ itsyTsFini
+};
+
diff --git a/hw/kdrive/keyboard.c b/hw/kdrive/keyboard.c
new file mode 100644
index 000000000..2b1a14377
--- /dev/null
+++ b/hw/kdrive/keyboard.c
@@ -0,0 +1,440 @@
+/*
+ * $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 "kdrive.h"
+#include "kkeymap.h"
+#include <linux/keyboard.h>
+#include <linux/kd.h>
+#include <X11/keysym.h>
+#include <termios.h>
+
+extern int LinuxConsoleFd;
+
+static KeySym linux_to_x[256] = {
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ XK_BackSpace, XK_Tab, XK_Linefeed, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, XK_Escape,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ XK_space, XK_exclam, XK_quotedbl, XK_numbersign,
+ XK_dollar, XK_percent, XK_ampersand, XK_apostrophe,
+ XK_parenleft, XK_parenright, XK_asterisk, XK_plus,
+ XK_comma, XK_minus, XK_period, XK_slash,
+ XK_0, XK_1, XK_2, XK_3,
+ XK_4, XK_5, XK_6, XK_7,
+ XK_8, XK_9, XK_colon, XK_semicolon,
+ XK_less, XK_equal, XK_greater, XK_question,
+ XK_at, XK_A, XK_B, XK_C,
+ XK_D, XK_E, XK_F, XK_G,
+ XK_H, XK_I, XK_J, XK_K,
+ XK_L, XK_M, XK_N, XK_O,
+ XK_P, XK_Q, XK_R, XK_S,
+ XK_T, XK_U, XK_V, XK_W,
+ XK_X, XK_Y, XK_Z, XK_bracketleft,
+ XK_backslash, XK_bracketright,XK_asciicircum, XK_underscore,
+ XK_grave, XK_a, XK_b, XK_c,
+ XK_d, XK_e, XK_f, XK_g,
+ XK_h, XK_i, XK_j, XK_k,
+ XK_l, XK_m, XK_n, XK_o,
+ XK_p, XK_q, XK_r, XK_s,
+ XK_t, XK_u, XK_v, XK_w,
+ XK_x, XK_y, XK_z, XK_braceleft,
+ XK_bar, XK_braceright, XK_asciitilde, XK_Delete,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ XK_nobreakspace,XK_exclamdown, XK_cent, XK_sterling,
+ XK_currency, XK_yen, XK_brokenbar, XK_section,
+ XK_diaeresis, XK_copyright, XK_ordfeminine, XK_guillemotleft,
+ XK_notsign, XK_hyphen, XK_registered, XK_macron,
+ XK_degree, XK_plusminus, XK_twosuperior, XK_threesuperior,
+ XK_acute, XK_mu, XK_paragraph, XK_periodcentered,
+ XK_cedilla, XK_onesuperior, XK_masculine, XK_guillemotright,
+ XK_onequarter, XK_onehalf, XK_threequarters,XK_questiondown,
+ XK_Agrave, XK_Aacute, XK_Acircumflex, XK_Atilde,
+ XK_Adiaeresis, XK_Aring, XK_AE, XK_Ccedilla,
+ XK_Egrave, XK_Eacute, XK_Ecircumflex, XK_Ediaeresis,
+ XK_Igrave, XK_Iacute, XK_Icircumflex, XK_Idiaeresis,
+ XK_ETH, XK_Ntilde, XK_Ograve, XK_Oacute,
+ XK_Ocircumflex, XK_Otilde, XK_Odiaeresis, XK_multiply,
+ XK_Ooblique, XK_Ugrave, XK_Uacute, XK_Ucircumflex,
+ XK_Udiaeresis, XK_Yacute, XK_THORN, XK_ssharp,
+ XK_agrave, XK_aacute, XK_acircumflex, XK_atilde,
+ XK_adiaeresis, XK_aring, XK_ae, XK_ccedilla,
+ XK_egrave, XK_eacute, XK_ecircumflex, XK_ediaeresis,
+ XK_igrave, XK_iacute, XK_icircumflex, XK_idiaeresis,
+ XK_eth, XK_ntilde, XK_ograve, XK_oacute,
+ XK_ocircumflex, XK_otilde, XK_odiaeresis, XK_division,
+ XK_oslash, XK_ugrave, XK_uacute, XK_ucircumflex,
+ XK_udiaeresis, XK_yacute, XK_thorn, XK_ydiaeresis
+};
+
+static unsigned char tbl[KD_MAX_WIDTH] =
+{
+ 0,
+ 1 << KG_SHIFT,
+ (1 << KG_ALT),
+ (1 << KG_ALT) | (1 << KG_SHIFT)
+};
+
+static void
+readKernelMapping()
+{
+ KeySym *k;
+ int i, j;
+ struct kbentry kbe;
+ int minKeyCode, maxKeyCode;
+
+ minKeyCode = NR_KEYS;
+ maxKeyCode = 0;
+ k = kdKeymap;
+ for (i = 0;
+ i < NR_KEYS && (maxKeyCode - minKeyCode + 1) < KD_MAX_LENGTH;
+ ++i)
+ {
+ kbe.kb_index = i;
+
+ for (j = 0; j < KD_MAX_WIDTH; ++j)
+ {
+ unsigned short kval;
+
+ k[j] = NoSymbol;
+
+ kbe.kb_table = tbl[j];
+ if (ioctl(LinuxConsoleFd, KDGKBENT, &kbe))
+ continue;
+
+ kval = KVAL(kbe.kb_value);
+ switch (KTYP(kbe.kb_value))
+ {
+ case KT_LATIN:
+ case KT_LETTER:
+ k[j] = linux_to_x[kval];
+ break;
+
+ case KT_FN:
+ if (kval <= 19)
+ k[j] = XK_F1 + kval;
+ else switch (kbe.kb_value)
+ {
+ case K_FIND:
+ k[j] = XK_Home; /* or XK_Find */
+ break;
+ case K_INSERT:
+ k[j] = XK_Insert;
+ break;
+ case K_REMOVE:
+ k[j] = XK_Delete;
+ break;
+ case K_SELECT:
+ k[j] = XK_End; /* or XK_Select */
+ break;
+ case K_PGUP:
+ k[j] = XK_Prior;
+ break;
+ case K_PGDN:
+ k[j] = XK_Next;
+ break;
+ case K_HELP:
+ k[j] = XK_Help;
+ break;
+ case K_DO:
+ k[j] = XK_Execute;
+ break;
+ case K_PAUSE:
+ k[j] = XK_Pause;
+ break;
+ case K_MACRO:
+ k[j] = XK_Menu;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case KT_SPEC:
+ switch (kbe.kb_value)
+ {
+ case K_ENTER:
+ k[j] = XK_Return;
+ break;
+ case K_BREAK:
+ k[j] = XK_Break;
+ break;
+ case K_CAPS:
+ k[j] = XK_Caps_Lock;
+ break;
+ case K_NUM:
+ k[j] = XK_Num_Lock;
+ break;
+ case K_HOLD:
+ k[j] = XK_Scroll_Lock;
+ break;
+ case K_COMPOSE:
+ k[j] = XK_Multi_key;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case KT_PAD:
+ switch (kbe.kb_value)
+ {
+ case K_PPLUS:
+ k[j] = XK_KP_Add;
+ break;
+ case K_PMINUS:
+ k[j] = XK_KP_Subtract;
+ break;
+ case K_PSTAR:
+ k[j] = XK_KP_Multiply;
+ break;
+ case K_PSLASH:
+ k[j] = XK_KP_Divide;
+ break;
+ case K_PENTER:
+ k[j] = XK_KP_Enter;
+ break;
+ case K_PCOMMA:
+ k[j] = XK_KP_Separator;
+ break;
+ case K_PDOT:
+ k[j] = XK_KP_Decimal;
+ break;
+ case K_PPLUSMINUS:
+ k[j] = XK_KP_Subtract;
+ break;
+ default:
+ if (kval <= 9)
+ k[j] = XK_KP_0 + kval;
+ break;
+ }
+ break;
+
+ /*
+ * KT_DEAD keys are for accelerated diacritical creation.
+ */
+ case KT_DEAD:
+ switch (kbe.kb_value)
+ {
+ case K_DGRAVE:
+ k[j] = XK_dead_grave;
+ break;
+ case K_DACUTE:
+ k[j] = XK_dead_acute;
+ break;
+ case K_DCIRCM:
+ k[j] = XK_dead_circumflex;
+ break;
+ case K_DTILDE:
+ k[j] = XK_dead_tilde;
+ break;
+ case K_DDIERE:
+ k[j] = XK_dead_diaeresis;
+ break;
+ }
+ break;
+
+ case KT_CUR:
+ switch (kbe.kb_value)
+ {
+ case K_DOWN:
+ k[j] = XK_Down;
+ break;
+ case K_LEFT:
+ k[j] = XK_Left;
+ break;
+ case K_RIGHT:
+ k[j] = XK_Right;
+ break;
+ case K_UP:
+ k[j] = XK_Up;
+ break;
+ }
+ break;
+
+ case KT_SHIFT:
+ switch (kbe.kb_value)
+ {
+ case K_ALTGR:
+ k[j] = XK_Alt_R;
+ break;
+ case K_ALT:
+ k[j] = (kbe.kb_index == 0x64 ?
+ XK_Alt_R : XK_Alt_L);
+ break;
+ case K_CTRL:
+ k[j] = (kbe.kb_index == 0x61 ?
+ XK_Control_R : XK_Control_L);
+ break;
+ case K_CTRLL:
+ k[j] = XK_Control_L;
+ break;
+ case K_CTRLR:
+ k[j] = XK_Control_R;
+ break;
+ case K_SHIFT:
+ k[j] = (kbe.kb_index == 0x36 ?
+ XK_Shift_R : XK_Shift_L);
+ break;
+ case K_SHIFTL:
+ k[j] = XK_Shift_L;
+ break;
+ case K_SHIFTR:
+ k[j] = XK_Shift_R;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ /*
+ * KT_ASCII keys accumulate a 3 digit decimal number that gets
+ * emitted when the shift state changes. We can't emulate that.
+ */
+ case KT_ASCII:
+ break;
+
+ case KT_LOCK:
+ if (kbe.kb_value == K_SHIFTLOCK)
+ k[j] = XK_Shift_Lock;
+ break;
+
+ default:
+ break;
+ }
+ if (i < minKeyCode)
+ minKeyCode = i;
+ if (i > maxKeyCode)
+ maxKeyCode = i;
+ }
+
+ if (minKeyCode == NR_KEYS)
+ continue;
+
+ if (k[3] == k[2]) k[3] = NoSymbol;
+ if (k[2] == k[1]) k[2] = NoSymbol;
+ if (k[1] == k[0]) k[1] = NoSymbol;
+ if (k[0] == k[2] && k[1] == k[3]) k[2] = k[3] = NoSymbol;
+ if (k[3] == k[0] && k[2] == k[1] && k[2] == NoSymbol) k[3] =NoSymbol;
+
+ k += KD_MAX_WIDTH;
+ }
+ kdMinScanCode = minKeyCode;
+ kdMaxScanCode = maxKeyCode;
+}
+
+void
+LinuxKeyboardLoad (void)
+{
+ readKernelMapping ();
+}
+
+static int LinuxKbdTrans;
+static struct termios LinuxTermios;
+
+int
+LinuxKeyboardInit (void)
+{
+ struct termios nTty;
+
+ ioctl (LinuxConsoleFd, KDGKBMODE, &LinuxKbdTrans);
+ tcgetattr (LinuxConsoleFd, &LinuxTermios);
+
+ ioctl(LinuxConsoleFd, KDSKBMODE, K_MEDIUMRAW);
+ nTty = LinuxTermios;
+ nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP);
+ nTty.c_oflag = 0;
+ nTty.c_cflag = CREAD | CS8;
+ nTty.c_lflag = 0;
+ nTty.c_cc[VTIME]=0;
+ nTty.c_cc[VMIN]=1;
+ cfsetispeed(&nTty, 9600);
+ cfsetospeed(&nTty, 9600);
+ tcsetattr(LinuxConsoleFd, TCSANOW, &nTty);
+ return LinuxConsoleFd;
+}
+
+void
+LinuxKeyboardFini (int fd)
+{
+ ioctl(LinuxConsoleFd, KDSKBMODE, LinuxKbdTrans);
+ tcsetattr(LinuxConsoleFd, TCSANOW, &LinuxTermios);
+}
+
+void
+LinuxKeyboardRead (int fd)
+{
+ unsigned char buf[256], *b;
+ int n;
+
+ while ((n = read (fd, buf, sizeof (buf))) > 0)
+ {
+ b = buf;
+ while (n--)
+ {
+ KdEnqueueKeyboardEvent (b[0] & 0x7f, b[0] & 0x80);
+ b++;
+ }
+ }
+}
+
+void
+LinuxKeyboardLeds (int leds)
+{
+ ioctl (LinuxConsoleFd, KDSETLED, leds & 7);
+}
+
+void
+LinuxKeyboardBell (int volume, int pitch, int duration)
+{
+ if (volume && pitch)
+ {
+ ioctl(LinuxConsoleFd, KDMKTONE,
+ ((1193190 / pitch) & 0xffff) |
+ (((unsigned long)duration *
+ volume / 50) << 16));
+
+ }
+}
+
+KdKeyboardFuncs LinuxKeyboardFuncs = {
+ LinuxKeyboardLoad,
+ LinuxKeyboardInit,
+ LinuxKeyboardRead,
+ LinuxKeyboardLeds,
+ LinuxKeyboardBell,
+ LinuxKeyboardFini,
+ 3,
+};
diff --git a/hw/kdrive/linux.c b/hw/kdrive/linux.c
new file mode 100644
index 000000000..67ac83af2
--- /dev/null
+++ b/hw/kdrive/linux.c
@@ -0,0 +1,322 @@
+/*
+ * $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 "kdrive.h"
+#include <errno.h>
+#include <signal.h>
+#include <linux/vt.h>
+#include <linux/kd.h>
+#include <sys/stat.h>
+#include <keysym.h>
+
+static int vtno;
+int LinuxConsoleFd;
+static int activeVT;
+static Bool enabled;
+
+void
+LinuxVTRequest (int sig)
+{
+ kdSwitchPending = TRUE;
+}
+
+/* Check before chowning -- this avoids touching the file system */
+void
+LinuxCheckChown (char *file)
+{
+ struct stat st;
+ __uid_t u;
+ __gid_t g;
+
+ if (stat (file, &st) < 0)
+ return;
+ u = getuid ();
+ g = getgid ();
+ if (st.st_uid != u || st.st_gid != g)
+ chown (file, u, g);
+}
+
+int
+LinuxInit ()
+{
+ int i, fd;
+ char vtname[11];
+ struct vt_stat vts;
+ struct stat statb;
+
+ LinuxConsoleFd = -1;
+ /* check if we're run with euid==0 */
+ if (geteuid() != 0)
+ {
+ FatalError("LinuxInit: Server must be suid root\n");
+ }
+
+ if ((fd = open("/dev/tty0",O_WRONLY,0)) < 0)
+ {
+ FatalError(
+ "LinuxInit: Cannot open /dev/tty0 (%s)\n",
+ strerror(errno));
+ }
+ if ((ioctl(fd, VT_OPENQRY, &vtno) < 0) ||
+ (vtno == -1))
+ {
+ FatalError("xf86OpenConsole: Cannot find a free VT\n");
+ }
+ close(fd);
+
+/* ErrorF("(using VT number %d)\n\n", vtno); */
+
+ sprintf(vtname,"/dev/tty%d",vtno); /* /dev/tty1-64 */
+
+ if ((LinuxConsoleFd = open(vtname, O_RDWR|O_NDELAY, 0)) < 0)
+ {
+ FatalError("LinuxInit: Cannot open %s (%s)\n",
+ vtname, strerror(errno));
+ }
+
+ /* change ownership of the vt */
+ LinuxCheckChown (vtname);
+
+ /*
+ * the current VT device we're running on is not "console", we want
+ * to grab all consoles too
+ *
+ * Why is this needed?
+ */
+ LinuxCheckChown ("/dev/tty0");
+ /*
+ * Linux doesn't switch to an active vt after the last close of a vt,
+ * so we do this ourselves by remembering which is active now.
+ */
+ if (ioctl(LinuxConsoleFd, VT_GETSTATE, &vts) == 0)
+ {
+ activeVT = vts.v_active;
+ }
+
+ return 1;
+}
+
+Bool
+LinuxFindPci (CARD16 vendor, CARD16 device, CARD32 count, KdCardAttr *attr)
+{
+ FILE *f;
+ char line[2048], *l, *end;
+ CARD32 bus, id, mode, addr;
+ int n;
+ CARD32 ven_dev;
+ Bool ret = FALSE;
+
+ ven_dev = (((CARD32) vendor) << 16) | ((CARD32) device);
+ f = fopen ("/proc/bus/pci/devices", "r");
+ if (!f)
+ return FALSE;
+ while (fgets (line, sizeof (line)-1, f))
+ {
+ line[sizeof(line)-1] = '\0';
+ l = line;
+ bus = strtoul (l, &end, 16);
+ if (end == l)
+ continue;
+ l = end;
+ id = strtoul (l, &end, 16);
+ if (end == l)
+ continue;
+ l = end;
+ if (id != ven_dev)
+ continue;
+ if (count--)
+ continue;
+ (void) strtoul (l, &end, 16);
+ if (end == l)
+ continue;
+ l = end;
+ n = 0;
+ for (;;)
+ {
+ addr = strtoul (l, &end, 16);
+ if (end == l)
+ break;
+ if (addr & 1)
+ attr->io = addr & ~0xf;
+ else
+ {
+ if (n == KD_MAX_CARD_ADDRESS)
+ break;
+ attr->address[n++] = addr & ~0xf;
+ }
+ l = end;
+ }
+ while (n > 0)
+ {
+ if (attr->address[n-1] != 0)
+ break;
+ n--;
+ }
+ attr->naddr = n;
+ ret = TRUE;
+ break;
+ }
+ fclose (f);
+ return ret;
+}
+
+void
+LinuxEnable (void)
+{
+ struct sigaction act;
+ struct vt_mode VT;
+
+ if (enabled)
+ return;
+ if (kdSwitchPending)
+ {
+ kdSwitchPending = FALSE;
+ ioctl (LinuxConsoleFd, VT_RELDISP, VT_ACKACQ);
+ }
+ /*
+ * now get the VT
+ */
+ if (ioctl(LinuxConsoleFd, VT_ACTIVATE, vtno) != 0)
+ {
+ ErrorF("LinuxInit: VT_ACTIVATE failed\n");
+ }
+ if (ioctl(LinuxConsoleFd, VT_WAITACTIVE, vtno) != 0)
+ {
+ ErrorF("LinuxInit: VT_WAITACTIVE failed\n");
+ }
+ if (ioctl(LinuxConsoleFd, VT_GETMODE, &VT) < 0)
+ {
+ FatalError ("LinuxInit: VT_GETMODE failed\n");
+ }
+
+ act.sa_handler = LinuxVTRequest;
+ sigemptyset (&act.sa_mask);
+ act.sa_flags = 0;
+ act.sa_restorer = 0;
+ sigaction (SIGUSR1, &act, 0);
+
+ VT.mode = VT_PROCESS;
+ VT.relsig = SIGUSR1;
+ VT.acqsig = SIGUSR1;
+ if (ioctl(LinuxConsoleFd, VT_SETMODE, &VT) < 0)
+ {
+ FatalError("LinuxInit: VT_SETMODE VT_PROCESS failed\n");
+ }
+ if (ioctl(LinuxConsoleFd, KDSETMODE, KD_GRAPHICS) < 0)
+ {
+ FatalError("LinuxInit: KDSETMODE KD_GRAPHICS failed\n");
+ }
+ enabled = TRUE;
+}
+
+Bool
+LinuxSpecialKey (KeySym sym)
+{
+ struct vt_stat vts;
+ int con;
+
+ if (XK_F1 <= sym && sym <= XK_F12)
+ {
+ con = sym - XK_F1 + 1;
+ ioctl (LinuxConsoleFd, VT_GETSTATE, &vts);
+ if (con != vts.v_active && (vts.v_state & (1 << con)))
+ {
+ ioctl (LinuxConsoleFd, VT_ACTIVATE, con);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void
+LinuxDisable (void)
+{
+ ioctl(LinuxConsoleFd, KDSETMODE, KD_TEXT); /* Back to text mode ... */
+ if (kdSwitchPending)
+ {
+ kdSwitchPending = FALSE;
+ ioctl (LinuxConsoleFd, VT_RELDISP, 1);
+ }
+ enabled = FALSE;
+}
+
+void
+LinuxFini (void)
+{
+ struct vt_mode VT;
+ struct vt_stat vts;
+ int fd;
+
+ if (LinuxConsoleFd < 0)
+ return;
+
+ if (ioctl(LinuxConsoleFd, VT_GETMODE, &VT) != -1)
+ {
+ VT.mode = VT_AUTO;
+ ioctl(LinuxConsoleFd, VT_SETMODE, &VT); /* set dflt vt handling */
+ }
+ ioctl (LinuxConsoleFd, VT_GETSTATE, &vts);
+ /*
+ * Find a legal VT to switch to, either the one we started from
+ * or the lowest active one that isn't ours
+ */
+ if (activeVT < 0 ||
+ activeVT == vts.v_active ||
+ !(vts.v_state & (1 << activeVT)))
+ {
+ for (activeVT = 1; activeVT < 16; activeVT++)
+ if (activeVT != vtno && (vts.v_state & (1 << activeVT)))
+ break;
+ if (activeVT == 16)
+ activeVT = -1;
+ }
+ /*
+ * Perform a switch back to the active VT when we were started
+ */
+ if (activeVT >= -1)
+ {
+ ioctl (LinuxConsoleFd, VT_ACTIVATE, activeVT);
+ ioctl (LinuxConsoleFd, VT_WAITACTIVE, activeVT);
+ activeVT = -1;
+ }
+ close(LinuxConsoleFd); /* make the vt-manager happy */
+ fd = open ("/dev/tty0", O_RDWR|O_NDELAY, 0);
+ if (fd >= 0)
+ {
+ ioctl (fd, VT_GETSTATE, &vts);
+ if (ioctl (fd, VT_DISALLOCATE, vtno) < 0)
+ fprintf (stderr, "Can't deallocate console %d errno %d\n", vtno, errno);
+ close (fd);
+ }
+ return;
+}
+
+KdOsFuncs LinuxFuncs = {
+ LinuxInit,
+ LinuxEnable,
+ LinuxSpecialKey,
+ LinuxDisable,
+ LinuxFini,
+};
diff --git a/hw/kdrive/ps2.c b/hw/kdrive/ps2.c
new file mode 100644
index 000000000..2d2612f55
--- /dev/null
+++ b/hw/kdrive/ps2.c
@@ -0,0 +1,132 @@
+/*
+ * $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: $ */
+
+#define NEED_EVENTS
+#include "X.h"
+#include "Xproto.h"
+#include "inputstr.h"
+#include "scrnintstr.h"
+#include "kdrive.h"
+#include "Xpoll.h"
+
+int
+Ps2ReadBytes (int fd, char *buf, int len, int min)
+{
+ int n, tot;
+ fd_set set;
+ struct timeval tv;
+
+ tot = 0;
+ while (len)
+ {
+ n = read (fd, buf, len);
+ if (n > 0)
+ {
+ tot += n;
+ buf += n;
+ len -= n;
+ }
+ if (tot % min == 0)
+ break;
+ FD_ZERO (&set);
+ FD_SET (fd, &set);
+ tv.tv_sec = 0;
+ tv.tv_usec = 100 * 1000;
+ n = select (fd + 1, &set, 0, 0, &tv);
+ if (n <= 0)
+ break;
+ }
+ return tot;
+}
+
+void
+Ps2Read (int ps2Port)
+{
+ unsigned char buf[3 * 200];
+ unsigned char *b;
+ int n;
+ int dx, dy;
+ unsigned long flags;
+
+ while ((n = Ps2ReadBytes (ps2Port, buf, sizeof (buf), 3)) > 0)
+ {
+ b = buf;
+ while (n >= 3)
+ {
+ flags = KD_MOUSE_DELTA;
+ if (b[0] & 4)
+ flags |= KD_BUTTON_2;
+ if (b[0] & 2)
+ flags |= KD_BUTTON_3;
+ if (b[0] & 1)
+ flags |= KD_BUTTON_1;
+
+ dx = b[1];
+ if (b[0] & 0x10)
+ dx -= 256;
+ dy = b[2];
+ if (b[0] & 0x20)
+ dy -= 256;
+ dy = -dy;
+ n -= 3;
+ b += 3;
+ KdEnqueueMouseEvent (flags, dx, dy);
+ }
+ }
+}
+
+char *Ps2Names[] = {
+ "/dev/psaux",
+ "/dev/mouse",
+};
+
+#define NUM_PS2_NAMES (sizeof (Ps2Names) / sizeof (Ps2Names[0]))
+
+int
+Ps2Init (void)
+{
+ int i;
+ int ps2Port;
+
+ for (i = 0; i < NUM_PS2_NAMES; i++)
+ {
+ ps2Port = open (Ps2Names[i], 0);
+ if (ps2Port >= 0)
+ return ps2Port;
+ }
+}
+
+void
+Ps2Fini (int ps2Port)
+{
+ if (ps2Port >= 0)
+ close (ps2Port);
+}
+
+KdMouseFuncs Ps2MouseFuncs = {
+ Ps2Init,
+ Ps2Read,
+ Ps2Fini
+};
diff --git a/hw/kdrive/savage/Imakefile b/hw/kdrive/savage/Imakefile
new file mode 100644
index 000000000..ba7c9cc84
--- /dev/null
+++ b/hw/kdrive/savage/Imakefile
@@ -0,0 +1,15 @@
+XCOMM $XConsortium: Imakefile /main/10 1996/12/02 10:20:33 lehors $
+XCOMM $XFree86: xc/programs/Xserver/hw/nvfb/Imakefile,v 3.8 1996/12/23 06:30:19 dawes Exp $
+#include <Server.tmpl>
+
+SRCS = s3.c s3clock.c s3cmap.c s3curs.c s3draw.c s3gc.c s3reg.c s3stub.c
+
+OBJS = s3.o s3clock.o s3cmap.o s3curs.o s3draw.o s3gc.o s3reg.o s3stub.o
+
+INCLUDES = -I.. -I. -I$(XBUILDINCDIR) -I$(FONTINCSRC) \
+ -I../../../fb -I../../../mi -I../../../include -I../../../os \
+ -I$(EXTINCSRC) -I$(XINCLUDESRC)
+
+NormalLibraryObjectRule()
+NormalLibraryTarget(savage,$(OBJS))
+DependTarget()
diff --git a/hw/kdrive/savage/s3.c b/hw/kdrive/savage/s3.c
new file mode 100644
index 000000000..bf3e2896a
--- /dev/null
+++ b/hw/kdrive/savage/s3.c
@@ -0,0 +1,997 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999 SuSE, Inc.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+/* $XFree86: $ */
+
+#include "s3.h"
+
+#define REGISTERS_OFFSET (0x1000000)
+#define PACKED_OFFSET (0x8100)
+#define IOMAP_OFFSET (0x8000)
+
+/*
+ * Clock synthesis:
+ *
+ * f_out = f_ref * ((M + 2) / ((N + 2) * (1 << R)))
+ *
+ * Constraints:
+ *
+ * 1. 135MHz <= f_ref * ((M + 2) / (N + 2)) <= 270 MHz
+ * 2. N >= 1
+ *
+ * Vertical refresh rate = clock / ((hsize + hblank) * (vsize + vblank))
+ * Horizontal refresh rate = clock / (hsize + hblank)
+ */
+
+#define DEFAULT_S3_TIMING 1
+
+S3Timing s3Timings[] = {
+ /* FP BP BLANK */
+ /* M N R blank bios5 */
+ { 640, 480, 60,
+ 16, 48, 160, /* horizontal 31.321 KHz */
+ 10, 33, 45, /* vertical 59.568 Hz */
+ 26, 0, 3, /* pixel 25.057 MHz */
+ },
+
+ { 800, 600, 85,
+ 32, 152, 248, /* horizontal 53.673 KHz */
+ 1, 27, 31, /* vertical 85.060 Hz */
+ 108, 5, 2, /* pixel 56.249 MHz */
+ },
+ { 800, 600, 75,
+ 16, 160, 256, /* horizontal 46.891 KHz */
+ 1, 21, 25, /* vertical 75.025 Hz */
+ 81, 4, 2, /* pixel 49.516 MHz */
+ },
+ { 800, 600, 72,
+ 56, 64, 240, /* horizontal 48.186 KHz */
+ 37, 23, 66, /* vertical 72.351 Hz */
+ 26, 0, 2, /* pixel 50.113 MHz */
+ },
+ { 800, 600, 60,
+ 48, 80, 256,
+ 1, 23, 28,
+ 0, 0, 0,
+ },
+ { 1024, 768, 85,
+ 48, 208, 352, /* horizontal 68.676 KHz */
+ 1, 36, 40, /* vertical 84.996 Hz */
+ 64, 3, 1, /* pixel 94.499 MHz */
+ },
+ { 1024, 768, 75,
+ 16, 176, 288, /* horizontal 60.022 KHz */
+ 1, 28, 32, /* vertical 75.028 Hz */
+ 20, 0, 1, /* pixel 78.749 MHz */
+ },
+ { 1024, 768, 70,
+ 32, 136, 304, /* horizontal 56.604 KHz */
+ 2, 30, 38, /* vertical 70.227 Hz */
+ 124, 1, 3, /* pixel 75.170 MHz */
+ },
+ { 1024, 768, 66,
+ 24, 144, 304, /* horizontal 53.234 KHz */
+ 3, 29, 38, /* vertical 66.047 Hz */
+ 77, 6, 1, /* pixel 70.695 MHz */
+ },
+
+ { 1152, 900, 85,
+ 48, 208, 384, /* horizontal 79.900 KHz */
+ 1, 32, 38, /* vertical 85.181 Hz */
+ 118, 5, 1, /* pixel 122.726 MHz */
+ },
+ { 1152, 900, 75,
+ 32, 208, 384, /* horizontal 70.495 Khz */
+ 1, 32, 38, /* vertical 75.154 Hz */
+ 119, 6, 1, /* pixel 108.280 MHz */
+ },
+ { 1152, 900, 70,
+ 32, 208, 384, /* horizontal 65.251 KHz */
+ 2, 32, 38, /* vertical 69.564 Hz */
+ 12, 0, 0, /* pixel 100.226 MHz */
+ },
+ { 1152, 900, 66,
+ 32, 208, 384, /* horizontal 61.817 KHz */
+ 1, 32, 38, /* vertical 65.903 Hz */
+ 124, 17, 0, /* pixel 94.951 MHz */
+ },
+ { 1280, 1024, 85,
+ 32, 248, 416, /* horizontal 90.561 KHz */
+ 1, 40, 45, /* vertical 84.717 Hz */
+ 116, 9, 0, /* pixel 153.593 MHz */
+ },
+ { 1280, 1024, 75,
+ 16, 248, 408, /* horizontal 80.255 KHz */
+ 1, 38, 42, /* vertical 75.285 Hz */
+ 111, 4, 1, /* pixel 134.828 MHz */
+ },
+ { 1280, 1024, 70,
+ 32, 248, 400, /* horizontal 74.573 KHz */
+ 0, 36, 39, /* vertical 70.153 Hz */
+ 68, 2, 1, /* pixel 125.283 MHz */
+ },
+ { 1280, 1024, 66,
+ 32, 248, 400, /* horizontal 70.007 KHz */
+ 0, 36, 39, /* vertical 65.858 Hz */
+ 113, 5, 1, /* pixel 117.612 MHz */
+ },
+ { 1280, 1024, 60,
+ 56, 240, 408, /* horizontal 70.007 KHz */
+ 1, 38, 42, /* vertical 65.858 Hz */
+ 113, 5, 1, /* pixel 117.612 MHz */
+ },
+ { 1600, 1200, 85,
+ 64, 304, 560, /* horizontal 106.059 KHz */
+ 1, 46, 50, /* vertical 84.847 Hz */
+ 126, 6, 0, /* pixel 229.088 MHz */
+ },
+ { 1600, 1200, 75,
+ 64, 304, 560, /* horizontal 93.748 KHz */
+ 1, 46, 50, /* vertical 74.999 Hz */
+ 97, 5, 0, /* pixel 202.497 MHz */
+ },
+ { 1600, 1200, 70,
+ 56, 304, 588, /* horizontal 87.524 KHz */
+ 1, 46, 50, /* vertical 70.019 Hz */
+ 105, 6, 0, /* pixel 191.503 MHz */
+ },
+ { 1600, 1200, 65,
+ 56, 308, 524, /* horizontal 80.050 KHz */
+ 1, 38, 42, /* vertical 64.453 Hz */
+ 93, 6, 0, /* pixel 170.026 MHz */
+ },
+};
+
+#define NUM_S3_TIMINGS (sizeof (s3Timings) / sizeof (s3Timings[0]))
+
+static void
+_s3SetBlank (S3Ptr s3, S3Vga *s3vga, Bool blank)
+{
+ CARD8 clock_mode;
+
+ s3SetImm(s3vga, s3_screen_off, blank ? 1 : 0);
+}
+
+static void
+_s3SetDepth (S3Ptr s3, S3Vga *s3vga)
+{
+ CARD8 save_3c2;
+ _s3SetBlank (s3, s3vga, TRUE);
+ VgaFlush(&s3vga->card);
+ VgaSetImm (&s3vga->card, s3_clock_load_imm, 1);
+ VgaSetImm(&s3vga->card, s3_clock_load_imm, 0);
+ _s3SetBlank (s3, s3vga, FALSE);
+}
+
+Bool
+s3CardInit (KdCardInfo *card)
+{
+ S3CardInfo *s3c;
+ S3Ptr s3;
+ S3Vga *s3vga;
+ int size;
+ CARD8 *registers;
+ CARD32 s3FrameBuffer;
+ CARD32 s3Registers;
+ CARD8 *temp_buffer;
+ CARD32 max_memory;
+ VGA32 save_linear_window_size;
+ VGA32 save_enable_linear;
+ VGA32 save_register_lock_2;
+
+ s3c = (S3CardInfo *) xalloc (sizeof (S3CardInfo));
+ if (!s3c)
+ {
+ goto bail0;
+ }
+
+ memset (s3c, '\0', sizeof (S3CardInfo));
+
+ card->driver = s3c;
+
+ if (card->attr.naddr > 1)
+ {
+ s3FrameBuffer = card->attr.address[1];
+ s3Registers = card->attr.address[0];
+ max_memory = 32 * 1024 * 1024;
+ }
+ else
+ {
+ s3FrameBuffer = card->attr.address[0];
+ s3Registers = s3FrameBuffer + REGISTERS_OFFSET;
+ max_memory = 16 * 1024 * 1024;
+ }
+
+#ifdef DEBUG
+ fprintf (stderr, "S3 at 0x%x/0x%x\n", s3Registers, s3FrameBuffer);
+#endif
+ registers = KdMapDevice (s3Registers,
+ sizeof (S3) + PACKED_OFFSET);
+ if (!registers)
+ {
+ ErrorF ("Can't map s3 device\n");
+ goto bail2;
+ }
+ s3 = (S3Ptr) (registers + PACKED_OFFSET);
+ s3c->registers = registers;
+ s3c->s3 = s3;
+
+ s3vga = &s3c->s3vga;
+ s3RegInit (s3vga, (VGAVOL8 *) (registers + IOMAP_OFFSET));
+
+ save_register_lock_2 = s3Get (s3vga, s3_register_lock_2);
+ s3SetImm (s3vga, s3_register_lock_2, 0xa0);
+ save_linear_window_size = s3Get (s3vga, s3_linear_window_size);
+ save_enable_linear = s3Get (s3vga, s3_enable_linear);
+ s3Set (s3vga, s3_linear_window_size, 3);
+ s3Set (s3vga, s3_enable_linear, 1);
+ VgaFlush (&s3vga->card);
+ VgaFinish (&s3vga->card);
+
+ /*
+ * Can't trust S3 register value for frame buffer amount, must compute
+ */
+ temp_buffer = KdMapDevice (s3FrameBuffer, max_memory);
+
+ s3c->memory = KdFrameBufferSize (temp_buffer, max_memory);
+
+ s3Set (s3vga, s3_linear_window_size, save_linear_window_size);
+ s3Set (s3vga, s3_enable_linear, save_enable_linear);
+ VgaFlush (&s3vga->card);
+ s3SetImm (s3vga, s3_register_lock_2, save_register_lock_2);
+ VgaFinish (&s3vga->card);
+#ifdef DEBUG
+ fprintf (stderr, "Frame buffer 0x%x\n", s3c->memory);
+#endif
+ KdUnmapDevice (temp_buffer, max_memory);
+
+ if (!s3c->memory)
+ {
+ ErrorF ("Can't detect s3 frame buffer at 0x%x\n", s3FrameBuffer);
+ goto bail3;
+ }
+
+ s3c->frameBuffer = KdMapDevice (s3FrameBuffer, s3c->memory);
+ if (!s3c->frameBuffer)
+ {
+ ErrorF ("Can't map s3 frame buffer\n");
+ goto bail3;
+ }
+
+ card->driver = s3c;
+
+ return TRUE;
+bail3:
+ KdUnmapDevice ((void *) s3, sizeof (S3));
+bail2:
+bail1:
+ xfree (s3c);
+bail0:
+ return FALSE;
+}
+
+Bool
+s3ScreenInit (KdScreenInfo *screen)
+{
+ KdCardInfo *card = screen->card;
+ S3CardInfo *s3c = (S3CardInfo *) card->driver;
+ S3ScreenInfo *s3s;
+ int screen_size;
+ int memory;
+ int requested_memory;
+ int v_total, h_total;
+ int byte_width;
+ int pixel_width;
+ int m, n, r;
+ int i;
+ S3Timing *t;
+
+ s3s = (S3ScreenInfo *) xalloc (sizeof (S3ScreenInfo));
+ if (!s3s)
+ return FALSE;
+
+ memset (s3s, '\0', sizeof (S3ScreenInfo));
+
+ if (!screen->width || !screen->height)
+ {
+ screen->width = 800;
+ screen->height = 600;
+ screen->rate = 72;
+ }
+ if (!screen->depth)
+ screen->depth = 8;
+
+ for (i = 0, t = s3Timings; i < NUM_S3_TIMINGS; i++, t++)
+ {
+ if (t->horizontal >= screen->width &&
+ t->vertical >= screen->height &&
+ (!screen->rate || t->rate <= screen->rate))
+ break;
+ }
+ if (i == NUM_S3_TIMINGS)
+ t = &s3Timings[DEFAULT_S3_TIMING];
+ screen->rate = t->rate;
+ screen->width = t->horizontal;
+ screen->height = t->vertical;
+ s3GetClock (S3ModeClock(t), &m, &n, &r, 511, 127, 4);
+#ifdef DEBUG
+ fprintf (stderr, "computed %d,%d,%d (%d) provided %d,%d,%d (%d)\n",
+ m, n, r, S3_CLOCK(m,n,r),
+ t->dac_m, t->dac_n, t->dac_r,
+ S3_CLOCK(t->dac_m, t->dac_n, t->dac_r));
+#endif
+ /*
+ * Can only operate in pixel-doubled mode at 8 bits per pixel
+ */
+ if (screen->depth > 16 && S3_CLOCK(m,n,r) > S3_MAX_CLOCK)
+ screen->depth = 16;
+
+ for (;;)
+ {
+ if (screen->depth >= 24)
+ {
+ screen->depth = 24;
+ screen->bitsPerPixel = 32;
+ }
+ else if (screen->depth >= 16)
+ {
+ screen->depth = 16;
+ screen->bitsPerPixel = 16;
+ }
+ else if (screen->depth >= 15)
+ {
+ screen->depth = 15;
+ screen->bitsPerPixel = 16;
+ }
+ else
+ {
+ screen->depth = 8;
+ screen->bitsPerPixel = 8;
+ }
+
+ /* Normalize width to supported values */
+
+ if (screen->width >= 1600)
+ screen->width = 1600;
+ else if (screen->width >= 1280)
+ screen->width = 1280;
+ else if (screen->width >= 1152)
+ screen->width = 1152;
+ else if (screen->width >= 1024)
+ screen->width = 1024;
+ else if (screen->width >= 800)
+ screen->width = 800;
+ else
+ screen->width = 640;
+
+ byte_width = screen->width * (screen->bitsPerPixel >> 3);
+ pixel_width = screen->width;
+ screen->pixelStride = pixel_width;
+ screen->byteStride = byte_width;
+
+ screen_size = byte_width * screen->height;
+
+ if (screen_size <= s3c->memory)
+ break;
+
+ /*
+ * Fix requested depth and geometry until it works
+ */
+ if (screen->depth > 16)
+ screen->depth = 16;
+ else if (screen->depth > 8)
+ screen->depth = 8;
+ else if (screen->width > 1152)
+ {
+ screen->width = 1152;
+ screen->height = 900;
+ }
+ else if (screen->width > 1024)
+ {
+ screen->width = 1024;
+ screen->height = 768;
+ }
+ else if (screen->width > 800)
+ {
+ screen->width = 800;
+ screen->height = 600;
+ }
+ else if (screen->width > 640)
+ {
+ screen->width = 640;
+ screen->height = 480;
+ }
+ else
+ {
+ xfree (s3s);
+ return FALSE;
+ }
+ }
+
+ memory = s3c->memory - screen_size;
+
+ /*
+ * Stick frame buffer at start of memory
+ */
+ screen->frameBuffer = s3c->frameBuffer;
+
+ /*
+ * Stick cursor at end of memory
+ */
+ if (memory >= 2048)
+ {
+ s3s->cursor_base = s3c->frameBuffer + (s3c->memory - 2048);
+ memory -= 2048;
+ }
+ else
+ s3s->cursor_base = 0;
+
+ /*
+ * Use remaining memory for off-screen storage, but only use
+ * one piece (either right or bottom).
+ */
+ if (memory >= byte_width * S3_TILE_SIZE)
+ {
+ s3s->offscreen = s3c->frameBuffer + screen_size;
+ s3s->offscreen_x = 0;
+ s3s->offscreen_y = screen_size / byte_width;
+ s3s->offscreen_width = pixel_width;
+ s3s->offscreen_height = memory / byte_width;
+ memory -= s3s->offscreen_height * byte_width;
+ }
+ else if (pixel_width - screen->width >= S3_TILE_SIZE)
+ {
+ s3s->offscreen = s3c->frameBuffer + screen->width;
+ s3s->offscreen_x = screen->width;
+ s3s->offscreen_y = 0;
+ s3s->offscreen_width = pixel_width - screen->width;
+ s3s->offscreen_height = screen->height;
+ }
+ else
+ s3s->offscreen = 0;
+
+ switch (screen->depth) {
+ case 8:
+ screen->visuals = ((1 << StaticGray) |
+ (1 << GrayScale) |
+ (1 << StaticColor) |
+ (1 << PseudoColor) |
+ (1 << TrueColor) |
+ (1 << DirectColor));
+ screen->blueMask = 0x00;
+ screen->greenMask = 0x00;
+ screen->redMask = 0x00;
+ break;
+ case 15:
+ screen->visuals = (1 << TrueColor);
+ screen->blueMask = 0x001f;
+ screen->greenMask = 0x03e0;
+ screen->redMask = 0x7c00;
+ break;
+ case 16:
+ screen->visuals = (1 << TrueColor);
+ screen->blueMask = 0x001f;
+ screen->greenMask = 0x07e0;
+ screen->redMask = 0xf800;
+ break;
+ case 24:
+ screen->visuals = (1 << TrueColor);
+ screen->blueMask = 0x0000ff;
+ screen->greenMask = 0x00ff00;
+ screen->redMask = 0xff0000;
+ break;
+ }
+
+ screen->driver = s3s;
+
+ return TRUE;
+}
+
+void
+s3Preserve (KdCardInfo *card)
+{
+ S3CardInfo *s3c = card->driver;
+ S3Ptr s3 = s3c->s3;
+ S3Vga *s3vga = &s3c->s3vga;
+ S3Save *save = &s3c->save;
+ CARD8 t1, t2;
+ CARD8 *cursor_base;
+
+ s3Save (s3vga);
+ _s3SetBlank (s3, s3vga, TRUE);
+ /*
+ * Preserve the first part of the frame buffer which holds
+ * the text mode fonts and data
+ */
+ s3Set (s3vga, s3_linear_window_size, 3);
+ s3Set (s3vga, s3_enable_linear, 1);
+ VgaFlush (&s3vga->card);
+ memcpy (save->text_save, s3c->frameBuffer, S3_TEXT_SAVE);
+ /*
+ * Preserve graphics engine state
+ */
+ save->alt_mix = s3->alt_mix;
+ save->write_mask = s3->write_mask;
+ save->fg = s3->fg;
+ save->bg = s3->bg;
+ _s3SetBlank (s3, s3vga, FALSE);
+}
+
+/*
+ * Enable the card for rendering. Manipulate the initial settings
+ * of the card here.
+ */
+void
+s3Enable (ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ KdCardInfo *card = pScreenPriv->card;
+ KdScreenInfo *screen = pScreenPriv->screen;
+ s3CardInfo (pScreenPriv);
+ s3ScreenInfo (pScreenPriv);
+
+ S3Vga *s3vga = &s3c->s3vga;
+ int hactive, hblank, hfp, hbp;
+ int vactive, vblank, vfp, vbp;
+ int hsize;
+
+ int h_total;
+ int h_display_end;
+ int h_blank_start;
+ int h_blank_end;
+ int h_sync_start;
+ int h_sync_end;
+ int h_screen_off;
+ int h_start_fifo_fetch;
+
+ int primary_stream_l1;
+
+ int v_total;
+ int v_retrace_start;
+ int v_retrace_end;
+ int v_display_end;
+ int v_blank_start;
+ int v_blank_end;
+
+ int h_blank_start_adjust;
+ int h_blank_end_adjust;
+ int h_sync_extend;
+ int h_blank_extend;
+ int i;
+ CARD16 cursor_address;
+ S3Timing *t;
+ int m, n, r;
+ Bool clock_double;
+
+ for (i = 0; i < NUM_S3_TIMINGS; i++)
+ {
+ t = &s3Timings[i];
+
+ if (t->horizontal == screen->width &&
+ t->vertical == screen->height &&
+ t->rate <= screen->rate)
+ break;
+ }
+ if (i == NUM_S3_TIMINGS)
+ t = &s3Timings[DEFAULT_S3_TIMING];
+
+ hfp = t->hfp;
+ hbp = t->hbp;
+ hblank = t->hblank;
+ hactive = t->horizontal;
+
+ vfp = t->vfp;
+ vbp = t->vbp;
+ vblank = t->vblank;
+ vactive = t->vertical;
+
+ m = s3Get (s3vga, s3_dclk_m);
+ n = s3Get (s3vga, s3_dclk_n);
+ r = s3Get (s3vga, s3_dclk_r);
+#ifdef DEBUG
+ fprintf (stderr, "old clock %d, %d, %d\n", m, n, r);
+#endif
+ clock_double = FALSE;
+ s3GetClock (S3ModeClock(t), &m, &n, &r, 511, 127, 4);
+ if (S3_CLOCK(m,n,r) > S3_MAX_CLOCK)
+ clock_double = TRUE;
+ s3Set (s3vga, s3_clock_select, 3);
+ s3Set (s3vga, s3_dclk_m, m);
+ s3Set (s3vga, s3_dclk_n, n);
+ s3Set (s3vga, s3_dclk_r, r);
+#ifdef DEBUG
+ fprintf (stderr, "new clock %d, %d, %d\n", m, n, r);
+#endif
+
+ s3Set (s3vga, s3_select_graphics_mode, 1);
+ s3Set (s3vga, s3_enable_blinking, 0);
+ s3Set (s3vga, s3_enable_vga_16bit, 0);
+ s3Set (s3vga, s3_enhanced_memory_mapping, 1);
+ s3Set (s3vga, s3_enable_sff, 1);
+ s3Set (s3vga, s3_enable_2d_access, 1);
+ s3Set (s3vga, s3_byte_mode, 1);
+ s3Set (s3vga, s3_max_scan_line, 0);
+ s3Set (s3vga, s3_linear_window_size, 3);
+ s3Set (s3vga, s3_enable_linear, 1);
+ s3Set (s3vga, s3_enable_2d_3d, 1);
+ s3Set (s3vga, s3_refresh_control, 1);
+ s3Set (s3vga, s3_disable_pci_read_bursts, 0);
+ s3Set (s3vga, s3_pci_retry_enable, 1);
+ s3Set (s3vga, s3_enable_256, 1);
+#if 1
+ s3Set (s3vga, s3_border_select, 1); /* eliminate white border */
+#else
+ s3Set (s3vga, s3_border_select, 0); /* eliminate white border */
+#endif
+ s3Set (s3vga, s3_disable_v_retrace_int, 1);
+ s3Set (s3vga, s3_horz_sync_neg, 0);
+ s3Set (s3vga, s3_vert_sync_neg, 0);
+
+ s3Set (s3vga, s3_dot_clock_8, 1);
+ s3Set (s3vga, s3_enable_write_plane, 0xf);
+ s3Set (s3vga, s3_extended_memory_access, 1);
+ s3Set (s3vga, s3_sequential_addressing_mode, 1);
+ s3Set (s3vga, s3_select_chain_4_mode, 1);
+#if 1
+ s3Set (s3vga, s3_linear_addressing_control, 1);
+#else
+ s3Set (s3vga, s3_linear_addressing_control, 0);
+#endif
+ s3Set (s3vga, s3_enable_8_bit_luts, 1);
+
+ s3Set (s3vga, s3_dclk_invert, 0);
+ s3Set (s3vga, s3_enable_clock_double, 0);
+
+ s3Set (s3vga, s3_cpu_timeout, 0x1f);
+ s3Set (s3vga, s3_fifo_fetch_timing, 1);
+ s3Set (s3vga, s3_fifo_drain_delay, 7);
+
+
+ s3Set (s3vga, s3_delay_h_enable, 0);
+ s3Set (s3vga, s3_sdclk_skew, 0);
+
+ /*
+ * Compute character lengths for horizontal timing values
+ */
+ h_blank_start_adjust = 0;
+ h_blank_end_adjust = 0;
+ switch (screen->bitsPerPixel) {
+ case 8:
+ hactive = screen->width / 8;
+ hblank /= 8;
+ hfp /= 8;
+ hbp /= 8;
+ h_screen_off = hactive;
+ s3Set (s3vga, s3_2d_graphics_engine_timeout, 0x1f);
+ s3Set (s3vga, s3_pixel_length, 0);
+ s3Set (s3vga, s3_color_mode, 0);
+ /*
+ * Set up for double-pixel mode, switch color modes,
+ * divide the dclk and delay h blank by 2 dclks
+ */
+ if (clock_double)
+ {
+ s3Set (s3vga, s3_color_mode, 1);
+ s3Set (s3vga, s3_dclk_over_2, 1);
+ s3Set (s3vga, s3_enable_clock_double, 1);
+ s3Set (s3vga, s3_border_select, 0);
+#if 0
+ s3Set (s3vga, s3_delay_blank, 2);
+ s3Set (s3vga, s3_delay_h_enable, 2);
+ crtc->extended_bios_5 = 2;
+#endif
+ h_blank_start_adjust = -1;
+ h_blank_end_adjust = 0;
+ }
+ break;
+ case 16:
+ hactive = screen->width / 8;
+ hblank /= 8;
+ hfp /= 8;
+ hbp /= 8;
+ h_screen_off = hactive * 2;
+ s3Set (s3vga, s3_pixel_length, 1);
+ s3Set (s3vga, s3_2d_graphics_engine_timeout, 0x14);
+ if (clock_double)
+ {
+ if (screen->depth == 15)
+ s3Set (s3vga, s3_color_mode, 3);
+ else
+ s3Set (s3vga, s3_color_mode, 5);
+ s3Set (s3vga, s3_dclk_over_2, 1);
+ s3Set (s3vga, s3_enable_clock_double, 1);
+ s3Set (s3vga, s3_border_select, 0);
+ }
+ else
+ {
+ if (screen->depth == 15)
+ s3Set (s3vga, s3_color_mode, 2);
+ else
+ s3Set (s3vga, s3_color_mode, 4);
+ s3Set (s3vga, s3_dclk_over_2, 0);
+ s3Set (s3vga, s3_enable_clock_double, 0);
+ s3Set (s3vga, s3_delay_blank, 0);
+ }
+ break;
+ case 32:
+ hactive = screen->width / 8;
+ hblank /= 8;
+ hfp /= 8;
+ hbp /= 8;
+ h_screen_off = hactive * 4;
+ s3Set (s3vga, s3_pixel_length, 3);
+ s3Set (s3vga, s3_color_mode, 0xd);
+ s3Set (s3vga, s3_2d_graphics_engine_timeout, 0x07);
+ break;
+ }
+
+ /*
+ * X server starts frame buffer at top of memory
+ */
+ s3Set (s3vga, s3_start_address, 0);
+
+ /*
+ * Compute horizontal register values from timings
+ */
+ h_total = hactive + hblank - 5;
+ h_display_end = hactive - 1;
+
+ h_sync_start = hactive + hfp;
+ h_sync_end = hactive + hblank - hbp;
+ /*
+ * pad the blank values narrow a bit and use the border_select to
+ * eliminate the remaining border; don't know why, but it doesn't
+ * work in the documented fashion
+ */
+ h_blank_start = hactive + 1 + h_blank_start_adjust;
+ h_blank_end = hactive + hblank - 2 + h_blank_end_adjust;
+ /*
+ * The manual says h_total - 5, but the
+ * bios does differently...
+ */
+ if (screen->width >= 1600)
+ h_start_fifo_fetch = h_total - 24;
+ else if (screen->width >= 1280)
+ h_start_fifo_fetch = h_total - 19;
+ else if (screen->width >= 1024)
+ h_start_fifo_fetch = h_total - 14;
+ else if (screen->width >= 800)
+ h_start_fifo_fetch = h_total - 10;
+ else
+ h_start_fifo_fetch = h_total - 5;
+
+ if (h_blank_end - h_blank_start >= 0x40)
+ h_blank_extend = 1;
+ else
+ h_blank_extend = 0;
+
+ if (h_sync_end - h_sync_start >= 0x20)
+ h_sync_extend = 1;
+ else
+ h_sync_extend = 0;
+
+ primary_stream_l1 = (screen->width * screen->bitsPerPixel / (8 * 8)) - 1;
+
+#ifdef DEBUG
+ fprintf (stderr, "h_total %d h_display_end %d\n",
+ h_total, h_display_end);
+ fprintf (stderr, "h_sync_start %d h_sync_end %d h_sync_extend %d\n",
+ h_sync_start, h_sync_end, h_sync_extend);
+ fprintf (stderr, "h_blank_start %d h_blank_end %d h_blank_extend %d\n",
+ h_blank_start, h_blank_end, h_blank_extend);
+#endif
+
+ s3Set (s3vga, s3_h_total, h_total);
+ s3Set (s3vga, s3_h_display_end, h_display_end);
+ s3Set (s3vga, s3_h_blank_start, h_blank_start);
+ s3Set (s3vga, s3_h_blank_end, h_blank_end);
+ s3Set (s3vga, s3_h_sync_start, h_sync_start);
+ s3Set (s3vga, s3_h_sync_end, h_sync_end);
+ s3Set (s3vga, s3_screen_offset, h_screen_off);
+ s3Set (s3vga, s3_h_start_fifo_fetch, h_start_fifo_fetch);
+ s3Set (s3vga, s3_h_sync_extend, h_sync_extend);
+ s3Set (s3vga, s3_h_blank_extend, h_blank_extend);
+
+ s3Set (s3vga, s3_primary_stream_l1, primary_stream_l1);
+
+ v_total = vactive + vblank - 2;
+ v_display_end = vactive - 1;
+
+#if 0
+ v_blank_start = vactive - 1;
+ v_blank_end = v_blank_start + vblank - 1;
+#else
+ v_blank_start = vactive - 1;
+ v_blank_end = v_blank_start + vblank - 1;
+#endif
+
+ v_retrace_start = vactive + vfp;
+ v_retrace_end = vactive + vblank - vbp;
+
+ s3Set (s3vga, s3_v_total, v_total);
+ s3Set (s3vga, s3_v_retrace_start, v_retrace_start);
+ s3Set (s3vga, s3_v_retrace_end, v_retrace_end);
+ s3Set (s3vga, s3_v_display_end, v_display_end);
+ s3Set (s3vga, s3_v_blank_start, v_blank_start);
+ s3Set (s3vga, s3_v_blank_end, v_blank_end);
+
+ if (vactive >= 1024)
+ s3Set (s3vga, s3_line_compare, 0x7ff);
+ else
+ s3Set (s3vga, s3_line_compare, 0x3ff);
+
+ /*
+ * Set cursor
+ */
+ if (!screen->softCursor)
+ {
+ cursor_address = (s3s->cursor_base - screen->frameBuffer) / 1024;
+
+ s3Set (s3vga, s3_cursor_address, cursor_address);
+ s3Set (s3vga, s3_cursor_ms_x11, 0);
+ s3Set (s3vga, s3_cursor_enable, 1);
+ }
+ else
+ s3Set (s3vga, s3_cursor_enable, 0);
+
+ /*
+ * Set accelerator
+ */
+ switch (screen->width) {
+ case 640: s3Set (s3vga, s3_ge_screen_width, 1); break;
+ case 800: s3Set (s3vga, s3_ge_screen_width, 2); break;
+ case 1024: s3Set (s3vga, s3_ge_screen_width, 0); break;
+ case 1152: s3Set (s3vga, s3_ge_screen_width, 4); break;
+ case 1280: s3Set (s3vga, s3_ge_screen_width, 3); break;
+ case 1600: s3Set (s3vga, s3_ge_screen_width, 6); break;
+ }
+
+#if 0
+ crtc->l_parm_0_7 = screen->width / 4; /* Undocumented. */
+#endif
+
+ /*
+ * Set DPMS to normal
+ */
+ s3Set (s3vga, s3_hsync_control, 0);
+ s3Set (s3vga, s3_vsync_control, 0);
+
+ _s3SetDepth (s3c->s3, s3vga);
+}
+
+void
+s3Disable (ScreenPtr pScreen)
+{
+}
+
+void
+s3Restore (KdCardInfo *card)
+{
+ S3CardInfo *s3c = card->driver;
+ S3Ptr s3 = s3c->s3;
+ S3Vga *s3vga = &s3c->s3vga;
+ S3Save *save = &s3c->save;
+ CARD8 *cursor_base;
+
+ /* graphics engine state */
+ s3->alt_mix = save->alt_mix;
+ s3->write_mask = save->write_mask;
+ s3->fg = save->fg;
+ s3->bg = save->bg;
+ /* XXX should save and restore real values? */
+ s3->scissors_tl = 0x00000000;
+ s3->scissors_br = 0x0fff0fff;
+
+ _s3SetBlank (s3, s3vga, TRUE);
+ VgaRestore (&s3vga->card);
+ s3Set (s3vga, s3_linear_window_size, 3);
+ s3Set (s3vga, s3_enable_linear, 1);
+ VgaFlush (&s3vga->card);
+ memcpy (s3c->frameBuffer, save->text_save, S3_TEXT_SAVE);
+ s3Reset (s3vga);
+ _s3SetBlank (s3, s3vga, FALSE);
+}
+
+void
+_s3SetSync (S3CardInfo *s3c, int hsync, int vsync)
+{
+ /* this abuses the macros defined to access the crtc structure */
+ S3Ptr s3 = s3c->s3;
+ S3Vga *s3vga = &s3c->s3vga;
+
+ s3Set (s3vga, s3_hsync_control, hsync);
+ s3Set (s3vga, s3_vsync_control, vsync);
+ VgaFlush (&s3vga->card);
+}
+
+Bool
+s3DPMS (ScreenPtr pScreen, int mode)
+{
+ KdScreenPriv(pScreen);
+ s3CardInfo(pScreenPriv);
+ S3Vga *s3vga = &s3c->s3vga;
+
+ switch (mode) {
+ case KD_DPMS_NORMAL:
+ _s3SetSync (s3c, 0, 0);
+ _s3SetBlank (s3c->s3, s3vga, FALSE);
+ break;
+ case KD_DPMS_STANDBY:
+ _s3SetBlank (s3c->s3, s3vga, TRUE);
+ _s3SetSync (s3c, 1, 0);
+ break;
+ case KD_DPMS_SUSPEND:
+ _s3SetBlank (s3c->s3, s3vga, TRUE);
+ _s3SetSync (s3c, 0, 1);
+ break;
+ case KD_DPMS_POWERDOWN:
+ _s3SetBlank (s3c->s3, s3vga, TRUE);
+ _s3SetSync (s3c, 1, 1);
+ break;
+ }
+ return TRUE;
+}
+
+void
+s3ScreenFini (KdScreenInfo *screen)
+{
+ S3ScreenInfo *s3s = (S3ScreenInfo *) screen->driver;
+
+ xfree (s3s);
+ screen->driver = 0;
+}
+
+void
+s3CardFini (KdCardInfo *card)
+{
+ S3CardInfo *s3c = (S3CardInfo *) card->driver;
+
+ KdUnmapDevice (s3c->frameBuffer, s3c->memory);
+ KdUnmapDevice (s3c->registers, sizeof (S3) + PACKED_OFFSET);
+ xfree (s3c);
+ card->driver = 0;
+}
+
+KdCardFuncs s3Funcs = {
+ s3CardInit,
+ s3ScreenInit,
+ s3Preserve,
+ s3Enable,
+ s3DPMS,
+ s3Disable,
+ s3Restore,
+ s3ScreenFini,
+ s3CardFini,
+ s3CursorInit,
+ s3CursorEnable,
+ s3CursorDisable,
+ s3CursorFini,
+ s3RecolorCursor,
+ s3DrawInit,
+ s3DrawEnable,
+ s3DrawDisable,
+ s3DrawFini,
+ s3GetColors,
+ s3PutColors,
+};
diff --git a/hw/kdrive/savage/s3.h b/hw/kdrive/savage/s3.h
new file mode 100644
index 000000000..95a8edddd
--- /dev/null
+++ b/hw/kdrive/savage/s3.h
@@ -0,0 +1,545 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999 SuSE, Inc.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+/* $XFree86: $ */
+
+#ifndef _S3_H_
+#define _S3_H_
+
+#include "kdrive.h"
+#include "s3reg.h"
+
+#define PLATFORM 300
+
+/* VESA Approved Register Definitions */
+
+/*
+ * Linear Addressing 000 0000 - 0ff ffff (16m)
+ * Image data transfer 100 0000 - 100 7fff (32k)
+ * PCI config 100 8000 - 100 8043
+ * Packed enhanced regs 100 8100 - 100 814a
+ * Streams regs 100 8180 - 100 81ff
+ * Current Y pos 100 82e8
+ * CRT VGA 3b? regs 100 83b0 - 100 83bf
+ * CRT VGA 3c? regs 100 83c0 - 100 83cf
+ * CRT VGA 3d? regs 100 83d0 - 100 83df
+ * Subsystem status (42e8h) 100 8504
+ * Advanced function (42e8h) 100 850c
+ * Enhanced regs 100 86e8 - 100 eeea
+ * Local peripheral bus 100 ff00 - 100 ff5c
+ *
+ * We don't care about the image transfer or PCI regs, so
+ * this structure starts at the packed enhanced regs
+ */
+
+typedef volatile CARD32 VOL32;
+typedef volatile CARD16 VOL16;
+typedef volatile CARD8 VOL8;
+
+typedef volatile struct _s3 {
+ VOL32 alt_curxy; /* 8100 */
+ VOL32 _pad0; /* 8104 */
+ VOL32 alt_step; /* 8108 */
+ VOL32 _pad1; /* 810c */
+ VOL32 err_term; /* 8110 */
+ VOL32 _pad2; /* 8114 */
+ VOL32 cmd_gp_stat; /* 8118 */
+ VOL32 short_stroke; /* 811c */
+ VOL32 bg; /* 8120 */
+ VOL32 fg; /* 8124 */
+ VOL32 write_mask; /* 8128 */
+ VOL32 read_mask; /* 812c */
+ VOL32 color_cmp; /* 8130 */
+ VOL32 alt_mix; /* 8134 */
+ VOL32 scissors_tl; /* 8138 */
+ VOL32 scissors_br; /* 813c */
+ VOL16 pix_cntl; /* 8140 */
+ VOL16 mult_misc2; /* 8142 */
+ VOL32 mult_misc_read_sel; /* 8144 */
+ VOL32 alt_pcnt; /* 8148 min_axis_pcnt, maj_axis_pcnt */
+ VOL8 _pad3[0x19c]; /* 814c */
+ VOL16 cur_y; /* 82e8 */
+ VOL8 _pad4[0xc6]; /* 82ea */
+
+ VOL8 crt_vga_3b0; /* 83b0 */
+ VOL8 crt_vga_3b1; /* 83b1 */
+ VOL8 crt_vga_3b2; /* 83b2 */
+ VOL8 crt_vga_3b3; /* 83b3 */
+ VOL8 crt_vga_3b4; /* 83b4 */
+ VOL8 crt_vga_3b5; /* 83b5 */
+ VOL8 crt_vga_3b6; /* 83b6 */
+ VOL8 crt_vga_3b7; /* 83b7 */
+ VOL8 crt_vga_3b8; /* 83b8 */
+ VOL8 crt_vga_3b9; /* 83b9 */
+ VOL8 crt_vga_3ba; /* 83ba */
+ VOL8 crt_vga_3bb; /* 83bb */
+ VOL8 crt_vga_3bc; /* 83bc */
+ VOL8 crt_vga_3bd; /* 83bd */
+ VOL8 crt_vga_3be; /* 83be */
+ VOL8 crt_vga_3bf; /* 83bf */
+
+ VOL8 crt_vga_3c0; /* 83c0 */
+ VOL8 crt_vga_3c1; /* 83c1 */
+ VOL8 crt_vga_3c2; /* 83c2 */
+ VOL8 crt_vga_3c3; /* 83c3 */
+ VOL8 crt_vga_3c4; /* 83c4 */
+ VOL8 crt_vga_3c5; /* 83c5 */
+ VOL8 crt_vga_dac_ad_mk; /* 83c6 */
+ VOL8 crt_vga_dac_rd_ad; /* 83c7 */
+ VOL8 crt_vga_dac_wt_ad; /* 83c8 */
+ VOL8 crt_vga_dac_data; /* 83c9 */
+ VOL8 crt_vga_3ca; /* 83ca */
+ VOL8 crt_vga_3cb; /* 83cb */
+ VOL8 crt_vga_3cc; /* 83cc */
+ VOL8 crt_vga_3cd; /* 83cd */
+ VOL8 crt_vga_3ce; /* 83ce */
+ VOL8 crt_vga_3cf; /* 83cf */
+
+ VOL8 crt_vga_3d0; /* 83d0 */
+ VOL8 crt_vga_3d1; /* 83d1 */
+ VOL8 crt_vga_3d2; /* 83d2 */
+ VOL8 crt_vga_3d3; /* 83d3 */
+ VOL8 crt_vga_3d4; /* 83d4 */
+ VOL8 crt_vga_3d5; /* 83d5 */
+ VOL8 crt_vga_3d6; /* 83d6 */
+ VOL8 crt_vga_3d7; /* 83d7 */
+ VOL8 crt_vga_3d8; /* 83d8 */
+ VOL8 crt_vga_3d9; /* 83d9 */
+ VOL8 crt_vga_status_1; /* 83da */
+ VOL8 crt_vga_3db; /* 83db */
+ VOL8 crt_vga_3dc; /* 83dc */
+ VOL8 crt_vga_3dd; /* 83dd */
+ VOL8 crt_vga_3de; /* 83de */
+ VOL8 crt_vga_3df; /* 83df */
+
+ VOL8 _pad5[0x124]; /* 83e0 */
+ VOL16 subsys_status; /* 8504 */
+ VOL8 _pad6[0x6]; /* 8506 */
+ VOL16 adv_control; /* 850c */
+ VOL8 _pad7[0x1da]; /* 850e */
+ VOL16 cur_x; /* 86e8 */
+ VOL8 _pad8[0x3fe]; /* 86ea */
+ VOL16 desty_axstp; /* 8ae8 */
+ VOL8 _pad9[0x3fe]; /* 8aea */
+ VOL16 destx_diastp; /* 8ee8 */
+ VOL8 _pad10[0x3fe]; /* 8eea */
+ VOL16 enh_err_term; /* 92e8 */
+ VOL8 _pad11[0x3fe]; /* 92ea */
+ VOL16 maj_axis_pcnt; /* 96e8 */
+ VOL8 _pad12[0x3fe]; /* 96ea */
+ VOL16 enh_cmd_gp_stat; /* 9ae8 */
+ VOL8 _pad13[0x3fe]; /* 9aea */
+ VOL16 enh_short_stroke; /* 9ee8 */
+ VOL8 _pad14[0x3fe]; /* 9eea */
+ VOL16 enh_bg; /* a2e8 */
+ VOL8 _pad15[0x3fe]; /* a2ea */
+ VOL16 enh_fg; /* a6e8 */
+ VOL8 _pad16[0x3fe]; /* a6ea */
+ VOL16 enh_wrt_mask; /* aae8 */
+ VOL8 _pad17[0x3fe]; /* aaea */
+ VOL16 enh_rd_mask; /* aee8 */
+ VOL8 _pad18[0x3fe]; /* aeea */
+ VOL16 enh_color_cmp; /* b2e8 */
+ VOL8 _pad19[0x3fe]; /* b2ea */
+ VOL16 enh_bg_mix; /* b6e8 */
+ VOL8 _pad20[0x3fe]; /* b6ea */
+ VOL16 enh_fg_mix; /* bae8 */
+ VOL8 _pad21[0x3fe]; /* baea */
+ VOL16 enh_rd_reg_dt; /* bee8 */
+ VOL8 _pad22[0x23fe]; /* beea */
+ VOL32 pix_trans; /* e2e8 */
+
+ VOL8 _pad23[0x3a974]; /* e2ec */
+ VOL32 alt_status_0; /* 48c60 */
+} S3, *S3Ptr;
+
+#define VGA_STATUS_1_DTM 0x01
+#define VGA_STATUS_1_VSY 0x08
+
+#define DAC_MASK 0x03c6
+#define DAC_R_INDEX 0x03c7
+#define DAC_W_INDEX 0x03c8
+#define DAC_DATA 0x03c9
+#define DISP_STAT 0x02e8
+#define H_TOTAL 0x02e8
+#define H_DISP 0x06e8
+#define H_SYNC_STRT 0x0ae8
+#define H_SYNC_WID 0x0ee8
+#define V_TOTAL 0x12e8
+#define V_DISP 0x16e8
+#define V_SYNC_STRT 0x1ae8
+#define V_SYNC_WID 0x1ee8
+#define DISP_CNTL 0x22e8
+#define ADVFUNC_CNTL 0x4ae8
+#define SUBSYS_STAT 0x42e8
+#define SUBSYS_CNTL 0x42e8
+#define ROM_PAGE_SEL 0x46e8
+#define CUR_Y 0x82e8
+#define CUR_X 0x86e8
+#define DESTY_AXSTP 0x8ae8
+#define DESTX_DIASTP 0x8ee8
+#define ERR_TERM 0x92e8
+#define MAJ_AXIS_PCNT 0x96e8
+#define GP_STAT 0x9ae8
+#define CMD 0x9ae8
+#define SHORT_STROKE 0x9ee8
+#define BKGD_COLOR 0xa2e8
+#define FRGD_COLOR 0xa6e8
+#define WRT_MASK 0xaae8
+#define RD_MASK 0xaee8
+#define COLOR_CMP 0xb2e8
+#define BKGD_MIX 0xb6e8
+#define FRGD_MIX 0xbae8
+#define MULTIFUNC_CNTL 0xbee8
+#define MIN_AXIS_PCNT 0x0000
+#define SCISSORS_T 0x1000
+#define SCISSORS_L 0x2000
+#define SCISSORS_B 0x3000
+#define SCISSORS_R 0x4000
+#define MEM_CNTL 0x5000
+#define PATTERN_L 0x8000
+#define PATTERN_H 0x9000
+#define PIX_CNTL 0xa000
+#define PIX_TRANS 0xe2e8
+
+/* Advanced Function Control Regsiter */
+#define CLKSEL 0x0004
+#define DISABPASSTHRU 0x0001
+
+/* Graphics Processor Status Register */
+
+#define GPNSLOT 13
+
+#define GPBUSY_1 0x0080
+#define GPBUSY_2 0x0040
+#define GPBUSY_3 0x0020
+#define GPBUSY_4 0x0010
+#define GPBUSY_5 0x0008
+#define GPBUSY_6 0x0004
+#define GPBUSY_7 0x0002
+#define GPBUSY_8 0x0001
+#define GPBUSY_9 0x8000
+#define GPBUSY_10 0x4000
+#define GPBUSY_11 0x2000
+#define GPBUSY_12 0x1000
+#define GPBUSY_13 0x0800
+
+#define GPEMPTY 0x0400
+#define GPBUSY 0x0200
+#define DATDRDY 0x0100
+
+/* Command Register */
+#define CMD_NOP 0x0000
+#define CMD_LINE 0x2000
+#define CMD_RECT 0x4000
+#define CMD_RECTV1 0x6000
+#define CMD_RECTV2 0x8000
+#define CMD_LINEAF 0xa000
+#define CMD_BITBLT 0xc000
+#define CMD_PATBLT 0xe000
+#define CMD_OP_MSK 0xe000
+#define BYTSEQ 0x1000
+#define _32BITNOPAD 0x0600
+#define _32BIT 0x0400
+#define _16BIT 0x0200
+#define _8BIT 0x0000
+#define PCDATA 0x0100
+#define INC_Y 0x0080
+#define YMAJAXIS 0x0040
+#define INC_X 0x0020
+#define DRAW 0x0010
+#define LINETYPE 0x0008
+#define LASTPIX 0x0004 /* Draw last pixel in line */
+#define PLANAR 0x0002
+#define WRTDATA 0x0001
+
+/* Background Mix Register */
+#define BSS_BKGDCOL 0x0000
+#define BSS_FRGDCOL 0x0020
+#define BSS_PCDATA 0x0040
+#define BSS_BITBLT 0x0060
+
+/* Foreground Mix Register */
+#define FSS_BKGDCOL 0x0000
+#define FSS_FRGDCOL 0x0020
+#define FSS_PCDATA 0x0040
+#define FSS_BITBLT 0x0060
+
+/* The Mixes */
+#define MIX_MASK 0x001f
+
+#define MIX_NOT_DST 0x0000
+#define MIX_0 0x0001
+#define MIX_1 0x0002
+#define MIX_DST 0x0003
+#define MIX_NOT_SRC 0x0004
+#define MIX_XOR 0x0005
+#define MIX_XNOR 0x0006
+#define MIX_SRC 0x0007
+#define MIX_NAND 0x0008
+#define MIX_NOT_SRC_OR_DST 0x0009
+#define MIX_SRC_OR_NOT_DST 0x000a
+#define MIX_OR 0x000b
+#define MIX_AND 0x000c
+#define MIX_SRC_AND_NOT_DST 0x000d
+#define MIX_NOT_SRC_AND_DST 0x000e
+#define MIX_NOR 0x000f
+
+#define MIX_MIN 0x0010
+#define MIX_DST_MINUS_SRC 0x0011
+#define MIX_SRC_MINUS_DST 0x0012
+#define MIX_PLUS 0x0013
+#define MIX_MAX 0x0014
+#define MIX_HALF__DST_MINUS_SRC 0x0015
+#define MIX_HALF__SRC_MINUS_DST 0x0016
+#define MIX_AVERAGE 0x0017
+#define MIX_DST_MINUS_SRC_SAT 0x0018
+#define MIX_SRC_MINUS_DST_SAT 0x001a
+#define MIX_HALF__DST_MINUS_SRC_SAT 0x001c
+#define MIX_HALF__SRC_MINUS_DST_SAT 0x001e
+#define MIX_AVERAGE_SAT 0x001f
+
+/* Pixel Control Register */
+#define MIXSEL_FRGDMIX 0x0000
+#define MIXSEL_PATT 0x0040
+#define MIXSEL_EXPPC 0x0080
+#define MIXSEL_EXPBLT 0x00c0
+#define COLCMPOP_F 0x0000
+#define COLCMPOP_T 0x0008
+#define COLCMPOP_GE 0x0010
+#define COLCMPOP_LT 0x0018
+#define COLCMPOP_NE 0x0020
+#define COLCMPOP_EQ 0x0028
+#define COLCMPOP_LE 0x0030
+#define COLCMPOP_GT 0x0038
+#define PLANEMODE 0x0004
+
+
+#define S3_SAVAGE4_SLOTS 0x0001ffff
+#define S3_SAVAGE4_2DI 0x00800000
+
+#define _s3WaitLoop(mask,value){ \
+ int __loop = 100000; \
+ while (((s3)->alt_status_0 & (mask)) != (value)) \
+ if (--__loop == 0) { \
+ ErrorF ("savage wait loop failed 0x%x\n", s3->alt_status_0); \
+ break; \
+ } \
+}
+
+#define _s3WaitSlot(s3) _s3WaitLoop(0x1, 0x0)
+#define _s3WaitEmpty(s3) _s3WaitLoop(S3_SAVAGE4_SLOTS, 0)
+#define _s3WaitIdleEmpty(s3) _s3WaitLoop(S3_SAVAGE4_SLOTS|S3_SAVAGE4_2DI, \
+ S3_SAVAGE4_2DI)
+#define _s3WaitIdle(s3) _s3WaitLoop(S3_SAVAGE4_2DI, S3_SAVAGE4_2DI)
+
+typedef struct _s3Cursor {
+ int width, height;
+ int xhot, yhot;
+ Bool has_cursor;
+ CursorPtr pCursor;
+ Pixel source, mask;
+} S3Cursor;
+
+typedef struct _s3PatternCache {
+ int id;
+ int x, y;
+} S3PatternCache;
+
+typedef struct _s3Patterns {
+ S3PatternCache *cache;
+ int ncache;
+ int last_used;
+ int last_id;
+} S3Patterns;
+
+#define S3_CLOCK_REF 14318 /* KHz */
+
+#define S3_CLOCK(m,n,r) (S3_CLOCK_REF * ((m) + 2) / (((n) + 2) * (1 << (r))))
+
+#if PLATFORM == 200
+#define S3_MAX_CLOCK 80000 /* KHz */
+#endif
+#if PLATFORM == 300
+#define S3_MAX_CLOCK 135000 /* KHz */
+#endif
+
+typedef struct _s3Timing {
+ /* label */
+ int horizontal;
+ int vertical;
+ int rate;
+ /* horizontal timing */
+ int hfp; /* front porch */
+ int hbp; /* back porch */
+ int hblank; /* blanking */
+ /* vertical timing */
+ int vfp; /* front porch */
+ int vbp; /* back porch */
+ int vblank; /* blanking */
+ /* clock values */
+ int dac_m;
+ int dac_n;
+ int dac_r;
+} S3Timing;
+
+#define S3_TEXT_SAVE (64*1024)
+
+typedef struct _s3Save {
+ CARD8 cursor_fg;
+ CARD8 cursor_bg;
+ CARD8 lock1;
+ CARD8 lock2;
+ CARD8 locksrtc;
+ CARD8 clock_mode;
+ CARD32 alt_mix;
+ CARD32 write_mask;
+ CARD32 fg;
+ CARD32 bg;
+ CARD8 text_save[S3_TEXT_SAVE];
+} S3Save;
+
+typedef struct _s3CardInfo {
+ S3Ptr s3; /* pointer to register structure */
+ int memory; /* amount of memory */
+ CARD8 *frameBuffer; /* pointer to frame buffer */
+ CARD8 *registers; /* pointer to register map */
+ S3Vga s3vga;
+ S3Save save;
+} S3CardInfo;
+
+typedef struct _s3ScreenInfo {
+ CARD8 *cursor_base; /* pointer to cursor area */
+ CARD8 *offscreen; /* pointer to offscreen area */
+ int offscreen_y; /* top y coordinate of offscreen area */
+ int offscreen_x; /* top x coordinate of offscreen area */
+ int offscreen_width; /* width of offscreen area */
+ int offscreen_height; /* height of offscreen area */
+ S3Cursor cursor;
+ S3Patterns patterns;
+} S3ScreenInfo;
+
+#define getS3CardInfo(kd) ((S3CardInfo *) ((kd)->card->driver))
+#define s3CardInfo(kd) S3CardInfo *s3c = getS3CardInfo(kd)
+
+#define getS3ScreenInfo(kd) ((S3ScreenInfo *) ((kd)->screen->driver))
+#define s3ScreenInfo(kd) S3ScreenInfo *s3s = getS3ScreenInfo(kd)
+
+Bool s3CardInit (KdCardInfo *);
+Bool s3ScreenInit (KdScreenInfo *);
+void s3Enable (ScreenPtr pScreen);
+void s3Disable (ScreenPtr pScreen);
+void s3Fini (ScreenPtr pScreen);
+
+Bool s3CursorInit (ScreenPtr pScreen);
+void s3CursorEnable (ScreenPtr pScreen);
+void s3CursorDisable (ScreenPtr pScreen);
+void s3CursorFini (ScreenPtr pScreen);
+void s3RecolorCursor (ScreenPtr pScreen, int ndef, xColorItem *pdefs);
+
+Bool s3DrawInit (ScreenPtr pScreen);
+void s3DrawEnable (ScreenPtr pScreen);
+void s3DrawDisable (ScreenPtr pScreen);
+void s3DrawFini (ScreenPtr pScreen);
+
+void s3GetColors (ScreenPtr pScreen, int ndef, xColorItem *pdefs);
+void s3PutColors (ScreenPtr pScreen, int ndef, xColorItem *pdefs);
+
+void S3InitCard (KdCardAttr *attr);
+
+void s3GetClock (int target, int *Mp, int *Np, int *Rp, int maxM, int maxN, int maxR);
+
+#define S3ModeClock(t) (((t->horizontal + t->hblank) * \
+ (t->vertical + t->vblank) * \
+ t->rate) / 1000)
+
+extern KdCardFuncs s3Funcs;
+
+/*
+ * Wait for the begining of the retrace interval
+ */
+
+#define S3_RETRACE_LOOP_CHECK if (++_loop_count > 300000) {\
+ DRAW_DEBUG ((DEBUG_FAILURE, "S3 wait loop failed at %s:%d", \
+ __FILE__, __LINE__)); \
+ break; \
+}
+
+#define DRAW_DEBUG(a)
+
+#define _s3WaitVRetrace(s3) { \
+ VOL8 *_status = &s3->crt_vga_status_1; \
+ int _loop_count; \
+ DRAW_DEBUG ((DEBUG_CRTC, "_s3WaitVRetrace 0x%x", *_status)); \
+ _loop_count = 0; \
+ while ((*_status & VGA_STATUS_1_VSY) != 0) S3_RETRACE_LOOP_CHECK; \
+ _loop_count = 0; \
+ while ((*_status & VGA_STATUS_1_VSY) == 0) S3_RETRACE_LOOP_CHECK; \
+}
+/*
+ * Wait for the begining of the retrace interval
+ */
+#define _s3WaitVRetraceEnd(s3) { \
+ VOL8 *_status = &s3->crt_vga_status_1; \
+ int _loop_count; \
+ DRAW_DEBUG ((DEBUG_CRTC, "_s3WaitVRetraceEnd 0x%x", *_status)); \
+ _loop_count = 0; \
+ while ((*_status & VGA_STATUS_1_VSY) == 0) S3_RETRACE_LOOP_CHECK; \
+ _loop_count = 0; \
+ while ((*_status & VGA_STATUS_1_VSY) != 0) S3_RETRACE_LOOP_CHECK; \
+}
+
+#define S3_CURSOR_WIDTH 64
+#define S3_CURSOR_HEIGHT 64
+#define S3_CURSOR_SIZE ((S3_CURSOR_WIDTH * S3_CURSOR_HEIGHT + 7) / 8)
+
+#define S3_TILE_SIZE 8
+
+/*
+ * Ok, so the S3 is broken -- it expects bitmaps to come MSB bit order,
+ * but it's willing to take them in LSB byte order. These macros
+ * flip bits around without flipping bytes. Instead of using a table
+ * and burning memory bandwidth, do them in place with the CPU.
+ */
+
+/* The MIPS compiler automatically places these constants in registers */
+#define S3InvertBits32(v) { \
+ v = ((v & 0x55555555) << 1) | ((v >> 1) & 0x55555555); \
+ v = ((v & 0x33333333) << 2) | ((v >> 2) & 0x33333333); \
+ v = ((v & 0x0f0f0f0f) << 4) | ((v >> 4) & 0x0f0f0f0f); \
+}
+
+#define S3InvertBits16(v) { \
+ v = ((v & 0x5555) << 1) | ((v >> 1) & 0x5555); \
+ v = ((v & 0x3333) << 2) | ((v >> 2) & 0x3333); \
+ v = ((v & 0x0f0f) << 4) | ((v >> 4) & 0x0f0f); \
+}
+
+#define S3InvertBits8(v) { \
+ v = ((v & 0x55) << 1) | ((v >> 1) & 0x55); \
+ v = ((v & 0x33) << 2) | ((v >> 2) & 0x33); \
+ v = ((v & 0x0f) << 4) | ((v >> 4) & 0x0f); \
+}
+
+#endif /* _S3_H_ */
diff --git a/hw/kdrive/savage/s3.nick b/hw/kdrive/savage/s3.nick
new file mode 100644
index 000000000..500b03d7b
--- /dev/null
+++ b/hw/kdrive/savage/s3.nick
@@ -0,0 +1,41 @@
+/* $XFree86: $ */
+
+global f_ref = 14318000;
+
+function s3_clock (m, n, r)
+{
+ return f_ref * (m + 2) / ((n + 2) * (2 ^ r));
+}
+
+function s3_near (f1, f2)
+{
+ return abs (f1 - f2) < f1 / 10;
+}
+
+function s3_clocks (f)
+{
+ auto m, n, r, ft;
+ auto dist, min_dist;
+ auto min_m, min_n, min_r;
+
+ min_dist = f / 5;
+ for (r = 0; r <= 3; r++)
+ for (n = 0; n <= 31; n++)
+ for (m = 0; m <= 127; m++)
+ {
+ ft = s3_clock (m, n, r);
+ if (s3_near (ft, f))
+ printf ("m %d n %d r %d = %d\n",
+ m, n, r, ft);
+ dist = abs (f - ft);
+ if (dist < min_dist)
+ {
+ min_dist = dist;
+ min_m = m;
+ min_n = n;
+ min_r = r;
+ }
+ }
+ printf ("m %d n %d r %d f %d dist %d\n",
+ min_m, min_n, min_r, s3_clock(min_m, min_n, min_r), min_dist);
+}
diff --git a/hw/kdrive/savage/s3clock.c b/hw/kdrive/savage/s3clock.c
new file mode 100644
index 000000000..457f5c57e
--- /dev/null
+++ b/hw/kdrive/savage/s3clock.c
@@ -0,0 +1,86 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999 SuSE, Inc.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+/* $XFree86: $ */
+
+#include "s3.h"
+
+/*
+ * Clock synthesis:
+ *
+ * f_out = f_ref * ((M + 2) / ((N + 2) * (1 << R)))
+ *
+ * Constraints:
+ *
+ * 1. 135MHz <= f_ref * ((M + 2) / (N + 2)) <= 270 MHz
+ * 2. N >= 1
+ *
+ * Vertical refresh rate = clock / ((hsize + hblank) * (vsize + vblank))
+ * Horizontal refresh rate = clock / (hsize + hblank)
+ */
+
+/* all in kHz */
+#define MIN_VCO 135000.0
+#define MAX_VCO 270000.0
+
+void
+s3GetClock (int target, int *Mp, int *Np, int *Rp, int maxM, int maxN, int maxR)
+{
+ int M, N, R, bestM, bestN;
+ int f_vco, f_out;
+ int err, abserr, besterr;
+
+ /*
+ * Compute correct R value to keep VCO in range
+ */
+ for (R = 0; R <= maxR; R++)
+ {
+ f_vco = target * (1 << R);
+ if (MIN_VCO <= f_vco && f_vco < MAX_VCO)
+ break;
+ }
+
+ /* M = f_out / f_ref * ((N + 2) * (1 << R)); */
+ besterr = target;
+ for (N = 0; N <= maxN; N++)
+ {
+ M = (target * (N + 2) * (1 << R) + (S3_CLOCK_REF/2)) / S3_CLOCK_REF - 2;
+ if (0 <= M && M <= maxM)
+ {
+ f_out = S3_CLOCK(M,N,R);
+ err = target - f_out;
+ if (err < 0)
+ err = -err;
+ if (err < besterr)
+ {
+ besterr = err;
+ bestM = M;
+ bestN = N;
+ }
+ }
+ }
+ *Mp = bestM;
+ *Np = bestN;
+ *Rp = R;
+}
diff --git a/hw/kdrive/savage/s3cmap.c b/hw/kdrive/savage/s3cmap.c
new file mode 100644
index 000000000..1c10dfa16
--- /dev/null
+++ b/hw/kdrive/savage/s3cmap.c
@@ -0,0 +1,67 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999 SuSE, Inc.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+/* $XFree86: $ */
+
+#include "s3.h"
+
+void
+s3GetColors (ScreenPtr pScreen, int ndef, xColorItem *pdefs)
+{
+ KdScreenPriv(pScreen);
+ s3CardInfo(pScreenPriv);
+ S3Ptr s3 = s3c->s3;
+ VOL8 *dac_rd_ad = &s3->crt_vga_dac_rd_ad;
+ VOL8 *dac_data = &s3->crt_vga_dac_data;
+
+ while (ndef--)
+ {
+ *dac_rd_ad = pdefs->pixel;
+ pdefs->red = *dac_data << 8;
+ pdefs->green = *dac_data << 8;
+ pdefs->blue = *dac_data << 8;
+ pdefs++;
+ }
+}
+
+void
+s3PutColors (ScreenPtr pScreen, int ndef, xColorItem *pdefs)
+{
+ KdScreenPriv(pScreen);
+ s3CardInfo(pScreenPriv);
+ S3Ptr s3 = s3c->s3;
+ VOL8 *dac_wt_ad = &s3->crt_vga_dac_wt_ad;
+ VOL8 *dac_data = &s3->crt_vga_dac_data;
+
+ _s3WaitVRetrace (s3);
+ while (ndef--)
+ {
+ *dac_wt_ad = pdefs->pixel;
+ *dac_data = pdefs->red >> 8;
+ *dac_data = pdefs->green >> 8;
+ *dac_data = pdefs->blue >> 8;
+ pdefs++;
+ }
+}
+
diff --git a/hw/kdrive/savage/s3curs.c b/hw/kdrive/savage/s3curs.c
new file mode 100644
index 000000000..0fd1397ab
--- /dev/null
+++ b/hw/kdrive/savage/s3curs.c
@@ -0,0 +1,418 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999 SuSE, Inc.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+/* $XFree86: $ */
+
+#include "s3.h"
+#include "cursorstr.h"
+
+#define SetupCursor(s) KdScreenPriv(s); \
+ s3CardInfo(pScreenPriv); \
+ s3ScreenInfo(pScreenPriv); \
+ S3Ptr s3 = s3c->s3; \
+ S3Vga *s3vga = &s3c->s3vga; \
+ S3Cursor *pCurPriv = &s3s->cursor
+
+static void
+_s3MoveCursor (ScreenPtr pScreen, int x, int y)
+{
+ SetupCursor(pScreen);
+ CARD8 xlow, xhigh, ylow, yhigh;
+ CARD8 xoff, yoff;
+
+ DRAW_DEBUG ((DEBUG_CURSOR, "s3MoveCursor %d %d", x, y));
+
+ x -= pCurPriv->xhot;
+ xoff = 0;
+ if (x < 0)
+ {
+ xoff = -x;
+ x = 0;
+ }
+ y -= pCurPriv->yhot;
+ yoff = 0;
+ if (y < 0)
+ {
+ yoff = -y;
+ y = 0;
+ }
+ xlow = (CARD8) x;
+ xhigh = (CARD8) (x >> 8);
+ ylow = (CARD8) y;
+ yhigh = (CARD8) (y >> 8);
+
+
+ /* This is the recommended order to move the cursor */
+
+ s3SetImm (s3vga, s3_cursor_xhigh, xhigh);
+ s3SetImm (s3vga, s3_cursor_xlow, xlow);
+ s3SetImm (s3vga, s3_cursor_ylow, ylow);
+ s3SetImm (s3vga, s3_cursor_xoff, xoff);
+ s3SetImm (s3vga, s3_cursor_yoff, yoff);
+ s3SetImm (s3vga, s3_cursor_yhigh, yhigh);
+
+ DRAW_DEBUG ((DEBUG_CURSOR, "s3MoveCursor done"));
+}
+
+static void
+s3MoveCursor (ScreenPtr pScreen, int x, int y)
+{
+ SetupCursor (pScreen);
+
+ if (!pCurPriv->has_cursor)
+ return;
+
+ if (!pScreenPriv->enabled)
+ return;
+
+ _s3MoveCursor (pScreen, x, y);
+}
+
+static void
+s3AllocCursorColors (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+ CursorPtr pCursor = pCurPriv->pCursor;
+ xColorItem sourceColor, maskColor;
+
+ /*
+ * Set these to an invalid pixel value so that
+ * when the store colors comes through, the cursor
+ * won't get recolored
+ */
+ pCurPriv->source = ~0;
+ pCurPriv->mask = ~0;
+ /*
+ * XXX S3 bug workaround; s3 chip doesn't use RGB values from
+ * the cursor color registers as documented, rather it uses
+ * them to index the DAC. This is in the errata though.
+ */
+ sourceColor.red = pCursor->foreRed;
+ sourceColor.green = pCursor->foreGreen;
+ sourceColor.blue = pCursor->foreBlue;
+ FakeAllocColor(pScreenPriv->pInstalledmap, &sourceColor);
+ maskColor.red = pCursor->backRed;
+ maskColor.green = pCursor->backGreen;
+ maskColor.blue = pCursor->backBlue;
+ FakeAllocColor(pScreenPriv->pInstalledmap, &maskColor);
+ FakeFreeColor(pScreenPriv->pInstalledmap, sourceColor.pixel);
+ FakeFreeColor(pScreenPriv->pInstalledmap, maskColor.pixel);
+
+ pCurPriv->source = sourceColor.pixel;
+ pCurPriv->mask = maskColor.pixel;
+ switch (pScreenPriv->screen->bitsPerPixel) {
+ case 4:
+ pCurPriv->source |= pCurPriv->source << 4;
+ pCurPriv->mask |= pCurPriv->mask << 4;
+ case 8:
+ pCurPriv->source |= pCurPriv->source << 8;
+ pCurPriv->mask |= pCurPriv->mask << 8;
+ case 16:
+ pCurPriv->source |= pCurPriv->source << 16;
+ pCurPriv->mask |= pCurPriv->mask << 16;
+ }
+}
+
+static void
+_s3SetCursorColors (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+ /* set foreground */
+ /* Reset cursor color stack pointers */
+ (void) s3GetImm (s3vga, s3_cursor_enable);
+ s3SetImm (s3vga, s3_cursor_fg, pCurPriv->source);
+ s3SetImm (s3vga, s3_cursor_fg, pCurPriv->source >> 8);
+ s3SetImm (s3vga, s3_cursor_fg, pCurPriv->source >> 16);
+
+ /* set background */
+ /* Reset cursor color stack pointers */
+ (void) s3GetImm (s3vga, s3_cursor_enable);
+ s3SetImm (s3vga, s3_cursor_bg, pCurPriv->mask);
+ s3SetImm (s3vga, s3_cursor_bg, pCurPriv->mask >> 8);
+ s3SetImm (s3vga, s3_cursor_bg, pCurPriv->mask >> 16);
+}
+
+void
+s3RecolorCursor (ScreenPtr pScreen, int ndef, xColorItem *pdef)
+{
+ SetupCursor (pScreen);
+ CursorPtr pCursor = pCurPriv->pCursor;
+ xColorItem sourceColor, maskColor;
+
+ if (!pCurPriv->has_cursor || !pCursor)
+ return;
+
+ if (!pScreenPriv->enabled)
+ return;
+
+ if (pdef)
+ {
+ while (ndef)
+ {
+ if (pdef->pixel == pCurPriv->source ||
+ pdef->pixel == pCurPriv->mask)
+ break;
+ ndef--;
+ }
+ if (!ndef)
+ return;
+ }
+ s3AllocCursorColors (pScreen);
+ _s3SetCursorColors (pScreen);
+}
+
+static void
+s3LoadCursor (ScreenPtr pScreen, int x, int y)
+{
+ SetupCursor(pScreen);
+ CursorPtr pCursor = pCurPriv->pCursor;
+ CursorBitsPtr bits = pCursor->bits;
+ int w, h;
+ unsigned char r[2], g[2], b[2];
+ unsigned short *ram, *msk, *mskLine, *src, *srcLine;
+ unsigned short and, xor;
+ int i, j;
+ int cursor_address;
+ int wsrc;
+ unsigned char ramdac_control_;
+
+ /*
+ * Allocate new colors
+ */
+ s3AllocCursorColors (pScreen);
+
+ pCurPriv->pCursor = pCursor;
+ pCurPriv->xhot = pCursor->bits->xhot;
+ pCurPriv->yhot = pCursor->bits->yhot;
+
+ /*
+ * Stick new image into cursor memory
+ */
+ ram = (unsigned short *) s3s->cursor_base;
+ mskLine = (unsigned short *) bits->mask;
+ srcLine = (unsigned short *) bits->source;
+
+ h = bits->height;
+ if (h > S3_CURSOR_HEIGHT)
+ h = S3_CURSOR_HEIGHT;
+
+ wsrc = BitmapBytePad(bits->width) / 2; /* words per line */
+
+ for (i = 0; i < S3_CURSOR_HEIGHT; i++) {
+ msk = mskLine;
+ src = srcLine;
+ mskLine += wsrc;
+ srcLine += wsrc;
+ for (j = 0; j < S3_CURSOR_WIDTH / 16; j++) {
+
+ unsigned short m, s;
+
+ if (i < h && j < wsrc)
+ {
+ m = *msk++;
+ s = *src++;
+ xor = m & s;
+ and = ~m;
+ }
+ else
+ {
+ and = 0xffff;
+ xor = 0x0000;
+ }
+
+ S3InvertBits16(and);
+ *ram++ = and;
+ S3InvertBits16(xor);
+ *ram++ = xor;
+ }
+ }
+
+ _s3WaitIdle (s3);
+
+ /* Set new color */
+ _s3SetCursorColors (pScreen);
+
+ /* Enable the cursor */
+ s3SetImm (s3vga, s3_cursor_enable, 1);
+
+ /* Wait for VRetrace to make sure the position is read */
+ _s3WaitVRetrace (s3);
+
+ /* Move to new position */
+ _s3MoveCursor (pScreen, x, y);
+}
+
+static void
+s3UnloadCursor (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ /* Disable cursor */
+ s3SetImm (s3vga, s3_cursor_enable, 0);
+}
+
+static Bool
+s3RealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
+{
+ SetupCursor(pScreen);
+
+ if (!pScreenPriv->enabled)
+ return TRUE;
+
+ /* miRecolorCursor does this */
+ if (pCurPriv->pCursor == pCursor)
+ {
+ if (pCursor)
+ {
+ int x, y;
+
+ miPointerPosition (&x, &y);
+ s3LoadCursor (pScreen, x, y);
+ }
+ }
+ return TRUE;
+}
+
+static Bool
+s3UnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
+{
+ return TRUE;
+}
+
+static void
+s3SetCursor (ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
+{
+ SetupCursor(pScreen);
+
+ pCurPriv->pCursor = pCursor;
+
+ if (!pScreenPriv->enabled)
+ return;
+
+ if (pCursor)
+ s3LoadCursor (pScreen, x, y);
+ else
+ s3UnloadCursor (pScreen);
+}
+
+miPointerSpriteFuncRec s3PointerSpriteFuncs = {
+ s3RealizeCursor,
+ s3UnrealizeCursor,
+ s3SetCursor,
+ s3MoveCursor,
+};
+
+static void
+s3QueryBestSize (int class,
+ unsigned short *pwidth, unsigned short *pheight,
+ ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ switch (class)
+ {
+ case CursorShape:
+ if (*pwidth > pCurPriv->width)
+ *pwidth = pCurPriv->width;
+ if (*pheight > pCurPriv->height)
+ *pheight = pCurPriv->height;
+ if (*pwidth > pScreen->width)
+ *pwidth = pScreen->width;
+ if (*pheight > pScreen->height)
+ *pheight = pScreen->height;
+ break;
+ default:
+ fbQueryBestSize (class, pwidth, pheight, pScreen);
+ break;
+ }
+}
+
+Bool
+s3CursorInit (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ if (!s3s->cursor_base)
+ {
+ DRAW_DEBUG ((DEBUG_CURSOR,"Not enough screen memory for cursor %d", s3d->memory));
+ pCurPriv->has_cursor = FALSE;
+ return FALSE;
+ }
+
+ pCurPriv->width = S3_CURSOR_WIDTH;
+ pCurPriv->height= S3_CURSOR_HEIGHT;
+ pScreen->QueryBestSize = s3QueryBestSize;
+ miPointerInitialize (pScreen,
+ &s3PointerSpriteFuncs,
+ &kdPointerScreenFuncs,
+ FALSE);
+ pCurPriv->has_cursor = TRUE;
+ pCurPriv->pCursor = NULL;
+ return TRUE;
+}
+
+void
+s3CursorEnable (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ DRAW_DEBUG ((DEBUG_INIT, "s3CursorEnable"));
+ if (pCurPriv->has_cursor)
+ {
+ if (pCurPriv->pCursor)
+ {
+ int x, y;
+
+ miPointerPosition (&x, &y);
+ s3LoadCursor (pScreen, x, y);
+ }
+ else
+ s3UnloadCursor (pScreen);
+ }
+}
+
+void
+s3CursorDisable (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ if (!pScreenPriv->enabled)
+ return;
+
+ if (pCurPriv->has_cursor)
+ {
+ if (pCurPriv->pCursor)
+ {
+ s3UnloadCursor (pScreen);
+ }
+ }
+}
+
+void
+s3CursorFini (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ pCurPriv->pCursor = NULL;
+}
diff --git a/hw/kdrive/savage/s3draw.c b/hw/kdrive/savage/s3draw.c
new file mode 100644
index 000000000..c57bc2eb5
--- /dev/null
+++ b/hw/kdrive/savage/s3draw.c
@@ -0,0 +1,2334 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999 SuSE, Inc.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+/* $XFree86: $ */
+
+#include "s3.h"
+#include "s3draw.h"
+
+#include "Xmd.h"
+#include "gcstruct.h"
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "regionstr.h"
+#include "mistruct.h"
+#include "fontstruct.h"
+#include "dixfontstr.h"
+#include "fb.h"
+#include "migc.h"
+#include "miline.h"
+
+/*
+ * Map X rops to S3 rops
+ */
+
+short s3alu[16] = {
+ MIX_0,
+ MIX_AND,
+ MIX_SRC_AND_NOT_DST,
+ MIX_SRC,
+ MIX_NOT_SRC_AND_DST,
+ MIX_DST,
+ MIX_XOR,
+ MIX_OR,
+ MIX_NOR,
+ MIX_XNOR,
+ MIX_NOT_DST,
+ MIX_SRC_OR_NOT_DST,
+ MIX_NOT_SRC,
+ MIX_NOT_SRC_OR_DST,
+ MIX_NAND,
+ MIX_1
+};
+
+/*
+ * Handle pixel transfers
+ */
+
+#define BURST
+#ifdef BURST
+#define PixTransDeclare VOL32 *pix_trans_base = (VOL32 *) (s3c->registers),\
+ *pix_trans = pix_trans_base;
+#define PixTransStart(n) if (pix_trans + (n) > pix_trans_base + 8192) pix_trans = pix_trans_base;
+#define PixTransStore(t) *pix_trans++ = (t)
+#else
+#define PixTransDeclare VOL32 *pix_trans = &s3->pix_trans;
+#define PixTransStart(n)
+#define PixTransStore(t) *pix_trans = (t)
+#endif
+
+int s3GCPrivateIndex;
+int s3WindowPrivateIndex;
+int s3Generation;
+
+/*
+ s3DoBitBlt
+ =============
+ Bit Blit for all window to window blits.
+*/
+
+#define sourceInvarient(alu) (((alu) & 3) == (((alu) >> 2) & 3))
+
+void
+s3CopyNtoN (DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ BoxPtr pbox,
+ int nbox,
+ int dx,
+ int dy,
+ Bool reverse,
+ Bool upsidedown,
+ Pixel bitplane,
+ void *closure)
+{
+ SetupS3(pDstDrawable->pScreen);
+ int srcX, srcY, dstX, dstY;
+ int w, h;
+ int flags;
+
+ if (sourceInvarient (pGC->alu))
+ {
+ s3FillBoxSolid (pDstDrawable, nbox, pbox, 0, pGC->alu, pGC->planemask);
+ return;
+ }
+
+ _s3SetBlt(s3,pGC->alu,pGC->planemask);
+ DRAW_DEBUG ((DEBUG_RENDER, "s3CopyNtoN alu %d planemask 0x%x",
+ pGC->alu, pGC->planemask));
+ while (nbox--)
+ {
+ w = pbox->x2 - pbox->x1;
+ h = pbox->y2 - pbox->y1;
+ flags = 0;
+ if (reverse)
+ {
+ dstX = pbox->x2 - 1;
+ }
+ else
+ {
+ dstX = pbox->x1;
+ flags |= INC_X;
+ }
+ srcX = dstX + dx;
+
+ if (upsidedown)
+ {
+ dstY = pbox->y2 - 1;
+ }
+ else
+ {
+ dstY = pbox->y1;
+ flags |= INC_Y;
+ }
+ srcY = dstY + dy;
+
+ _s3Blt (s3, srcX, srcY, dstX, dstY, w, h, flags);
+ pbox++;
+ }
+ _s3WaitIdleEmpty(s3);
+}
+
+RegionPtr
+s3CopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
+ int srcx, int srcy, int width, int height, int dstx, int dsty)
+{
+ KdScreenPriv(pDstDrawable->pScreen);
+
+ if (pSrcDrawable->type == DRAWABLE_WINDOW &&
+ pDstDrawable->type == DRAWABLE_WINDOW)
+ {
+ return fbDoCopy (pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy, width, height,
+ dstx, dsty, s3CopyNtoN, 0, 0);
+ }
+ return fbCopyArea (pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy, width, height, dstx, dsty);
+}
+
+typedef struct _s31toNargs {
+ unsigned long copyPlaneFG, copyPlaneBG;
+} s31toNargs;
+
+void
+_s3Stipple (S3CardInfo *s3c,
+ FbStip *psrcBase,
+ FbStride widthSrc,
+ int srcx,
+ int srcy,
+ int dstx,
+ int dsty,
+ int width,
+ int height)
+{
+ S3Ptr s3 = s3c->s3;
+ FbStip *psrcLine, *psrc;
+ FbStride widthRest;
+ FbStip bits, tmp, lastTmp;
+ int leftShift, rightShift;
+ int nl, nlMiddle;
+ int r;
+ PixTransDeclare;
+
+ /* Compute blt address and parameters */
+ psrc = psrcBase + srcy * widthSrc + (srcx >> 5);
+ nlMiddle = (width + 31) >> 5;
+ leftShift = srcx & 0x1f;
+ rightShift = 32 - leftShift;
+ widthRest = widthSrc - nlMiddle;
+
+ _s3PlaneBlt(s3,dstx,dsty,width,height);
+
+ if (leftShift == 0)
+ {
+ while (height--)
+ {
+ nl = nlMiddle;
+ PixTransStart(nl);
+ while (nl--)
+ {
+ tmp = *psrc++;
+ S3InvertBits32(tmp);
+ PixTransStore (tmp);
+ }
+ psrc += widthRest;
+ }
+ }
+ else
+ {
+ widthRest--;
+ while (height--)
+ {
+ bits = *psrc++;
+ nl = nlMiddle;
+ PixTransStart(nl);
+ while (nl--)
+ {
+ tmp = FbStipLeft(bits, leftShift);
+ bits = *psrc++;
+ tmp |= FbStipRight(bits, rightShift);
+ S3InvertBits32(tmp);
+ PixTransStore (tmp);
+ }
+ psrc += widthRest;
+ }
+ }
+}
+
+void
+s3Copy1toN (DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ BoxPtr pbox,
+ int nbox,
+ int dx,
+ int dy,
+ Bool reverse,
+ Bool upsidedown,
+ Pixel bitplane,
+ void *closure)
+{
+ SetupS3(pDstDrawable->pScreen);
+
+ s31toNargs *args = closure;
+ int dstx, dsty;
+ FbStip *psrcBase;
+ FbStride widthSrc;
+ int srcBpp;
+
+ if (sourceInvarient (pGC->alu))
+ {
+ s3FillBoxSolid (pDstDrawable, nbox, pbox,
+ pGC->bgPixel, pGC->alu, pGC->planemask);
+ return;
+ }
+
+ fbGetStipDrawable (pSrcDrawable, psrcBase, widthSrc, srcBpp);
+
+ _s3SetOpaquePlaneBlt(s3,pGC->alu,pGC->planemask,args->copyPlaneFG,
+ args->copyPlaneBG);
+
+ while (nbox--)
+ {
+ dstx = pbox->x1;
+ dsty = pbox->y1;
+
+ _s3Stipple (s3c,
+ psrcBase, widthSrc,
+ dstx + dx, dsty + dy,
+ dstx, dsty,
+ pbox->x2 - dstx, pbox->y2 - dsty);
+ pbox++;
+ }
+ _s3WaitIdleEmpty (s3);
+}
+
+RegionPtr
+s3CopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
+ int srcx, int srcy, int width, int height,
+ int dstx, int dsty, unsigned long bitPlane)
+{
+ KdScreenPriv (pDstDrawable->pScreen);
+ RegionPtr ret;
+ s31toNargs args;
+
+ if (pDstDrawable->type == DRAWABLE_WINDOW &&
+ pSrcDrawable->depth == 1)
+ {
+ args.copyPlaneFG = pGC->fgPixel;
+ args.copyPlaneBG = pGC->bgPixel;
+ return fbDoCopy (pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy, width, height,
+ dstx, dsty, s3Copy1toN, bitPlane, &args);
+ }
+ return fbCopyPlane(pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy, width, height,
+ dstx, dsty, bitPlane);
+}
+
+void
+s3FillBoxSolid (DrawablePtr pDrawable, int nBox, BoxPtr pBox,
+ unsigned long pixel, int alu, unsigned long planemask)
+{
+ SetupS3(pDrawable->pScreen);
+ register int r;
+
+ _s3SetSolidFill(s3,pixel,alu,planemask);
+
+ while (nBox--) {
+ _s3SolidRect(s3,pBox->x1,pBox->y1,pBox->x2-pBox->x1,pBox->y2-pBox->y1);
+ pBox++;
+ }
+ _s3WaitIdleEmpty(s3);
+}
+
+void
+_s3SetPattern (ScreenPtr pScreen,
+ int alu, unsigned long planemask, s3PatternPtr pPattern)
+{
+ SetupS3(pScreen);
+ S3PatternCache *cache;
+
+ _s3LoadPattern (pScreen, pPattern);
+ cache = pPattern->cache;
+
+ switch (pPattern->fillStyle) {
+ case FillTiled:
+ _s3SetTile(s3,alu,planemask);
+ break;
+ case FillStippled:
+ _s3SetStipple(s3,alu,planemask,pPattern->fore);
+ break;
+ case FillOpaqueStippled:
+ _s3SetOpaqueStipple(s3,alu,planemask,pPattern->fore,pPattern->back);
+ break;
+ }
+}
+
+void
+s3FillBoxPattern (DrawablePtr pDrawable, int nBox, BoxPtr pBox,
+ int alu, unsigned long planemask, s3PatternPtr pPattern)
+{
+ SetupS3(pDrawable->pScreen);
+ S3PatternCache *cache;
+ int patx, paty;
+
+ _s3SetPattern (pDrawable->pScreen, alu, planemask, pPattern);
+ cache = pPattern->cache;
+ while (nBox--)
+ {
+ _s3PatRect(s3,cache->x, cache->y,
+ pBox->x1, pBox->y1,
+ pBox->x2-pBox->x1, pBox->y2-pBox->y1);
+ pBox++;
+ }
+ _s3WaitIdleEmpty(s3);
+}
+
+void
+s3FillBoxLargeStipple (DrawablePtr pDrawable, GCPtr pGC,
+ int nBox, BoxPtr pBox)
+{
+ SetupS3(pDrawable->pScreen);
+ DrawablePtr pStipple = &pGC->stipple->drawable;
+ int xRot = pGC->patOrg.x + pDrawable->x;
+ int yRot = pGC->patOrg.y + pDrawable->y;
+ FbStip *stip;
+ FbStride stipStride;
+ int stipBpp;
+ int stipWidth, stipHeight;
+ int dstX, dstY, width, height;
+
+ stipWidth = pStipple->width;
+ stipHeight = pStipple->height;
+ fbGetStipDrawable (pStipple, stip, stipStride, stipBpp);
+
+ if (pGC->fillStyle == FillOpaqueStippled)
+ {
+ _s3SetOpaquePlaneBlt(s3,pGC->alu,pGC->planemask,
+ pGC->fgPixel, pGC->bgPixel);
+
+ }
+ else
+ {
+ _s3SetTransparentPlaneBlt(s3,pGC->alu,pGC->planemask, pGC->fgPixel);
+ }
+
+ while (nBox--)
+ {
+ int stipX, stipY, sx;
+ int widthTmp;
+ int h, w;
+ int x, y;
+
+ dstX = pBox->x1;
+ dstY = pBox->y1;
+ width = pBox->x2 - pBox->x1;
+ height = pBox->y2 - pBox->y1;
+ pBox++;
+ modulus (dstY - yRot, stipHeight, stipY);
+ modulus (dstX - xRot, stipWidth, stipX);
+ y = dstY;
+ while (height)
+ {
+ h = stipHeight - stipY;
+ if (h > height)
+ h = height;
+ height -= h;
+ widthTmp = width;
+ x = dstX;
+ sx = stipX;
+ while (widthTmp)
+ {
+ w = (stipWidth - sx);
+ if (w > widthTmp)
+ w = widthTmp;
+ widthTmp -= w;
+ _s3Stipple (s3c,
+ stip,
+ stipStride,
+ sx, stipY,
+ x, y,
+ w, h);
+ x += w;
+ sx = 0;
+ }
+ y += h;
+ stipY = 0;
+ }
+ }
+ _s3WaitIdleEmpty (s3);
+}
+
+#define NUM_STACK_RECTS 1024
+
+void
+s3PolyFillRect (DrawablePtr pDrawable, GCPtr pGC,
+ int nrectFill, xRectangle *prectInit)
+{
+ s3GCPrivate(pGC);
+ xRectangle *prect;
+ RegionPtr prgnClip;
+ register BoxPtr pbox;
+ register BoxPtr pboxClipped;
+ BoxPtr pboxClippedBase;
+ BoxPtr pextent;
+ BoxRec stackRects[NUM_STACK_RECTS];
+ FbGCPrivPtr fbPriv = fbGetGCPrivate (pGC);
+ int numRects;
+ int n;
+ int xorg, yorg;
+ int x, y;
+
+ prgnClip = fbGetCompositeClip(pGC);
+ xorg = pDrawable->x;
+ yorg = pDrawable->y;
+
+ if (xorg || yorg)
+ {
+ prect = prectInit;
+ n = nrectFill;
+ while(n--)
+ {
+ prect->x += xorg;
+ prect->y += yorg;
+ prect++;
+ }
+ }
+
+ prect = prectInit;
+
+ numRects = REGION_NUM_RECTS(prgnClip) * nrectFill;
+ if (numRects > NUM_STACK_RECTS)
+ {
+ pboxClippedBase = (BoxPtr)ALLOCATE_LOCAL(numRects * sizeof(BoxRec));
+ if (!pboxClippedBase)
+ return;
+ }
+ else
+ pboxClippedBase = stackRects;
+
+ pboxClipped = pboxClippedBase;
+
+ if (REGION_NUM_RECTS(prgnClip) == 1)
+ {
+ int x1, y1, x2, y2, bx2, by2;
+
+ pextent = REGION_RECTS(prgnClip);
+ x1 = pextent->x1;
+ y1 = pextent->y1;
+ x2 = pextent->x2;
+ y2 = pextent->y2;
+ while (nrectFill--)
+ {
+ if ((pboxClipped->x1 = prect->x) < x1)
+ pboxClipped->x1 = x1;
+
+ if ((pboxClipped->y1 = prect->y) < y1)
+ pboxClipped->y1 = y1;
+
+ bx2 = (int) prect->x + (int) prect->width;
+ if (bx2 > x2)
+ bx2 = x2;
+ pboxClipped->x2 = bx2;
+
+ by2 = (int) prect->y + (int) prect->height;
+ if (by2 > y2)
+ by2 = y2;
+ pboxClipped->y2 = by2;
+
+ prect++;
+ if ((pboxClipped->x1 < pboxClipped->x2) &&
+ (pboxClipped->y1 < pboxClipped->y2))
+ {
+ pboxClipped++;
+ }
+ }
+ }
+ else
+ {
+ int x1, y1, x2, y2, bx2, by2;
+
+ pextent = REGION_EXTENTS(pGC->pScreen, prgnClip);
+ x1 = pextent->x1;
+ y1 = pextent->y1;
+ x2 = pextent->x2;
+ y2 = pextent->y2;
+ while (nrectFill--)
+ {
+ BoxRec box;
+
+ if ((box.x1 = prect->x) < x1)
+ box.x1 = x1;
+
+ if ((box.y1 = prect->y) < y1)
+ box.y1 = y1;
+
+ bx2 = (int) prect->x + (int) prect->width;
+ if (bx2 > x2)
+ bx2 = x2;
+ box.x2 = bx2;
+
+ by2 = (int) prect->y + (int) prect->height;
+ if (by2 > y2)
+ by2 = y2;
+ box.y2 = by2;
+
+ prect++;
+
+ if ((box.x1 >= box.x2) || (box.y1 >= box.y2))
+ continue;
+
+ n = REGION_NUM_RECTS (prgnClip);
+ pbox = REGION_RECTS(prgnClip);
+
+ /* clip the rectangle to each box in the clip region
+ this is logically equivalent to calling Intersect()
+ */
+ while(n--)
+ {
+ pboxClipped->x1 = max(box.x1, pbox->x1);
+ pboxClipped->y1 = max(box.y1, pbox->y1);
+ pboxClipped->x2 = min(box.x2, pbox->x2);
+ pboxClipped->y2 = min(box.y2, pbox->y2);
+ pbox++;
+
+ /* see if clipping left anything */
+ if(pboxClipped->x1 < pboxClipped->x2 &&
+ pboxClipped->y1 < pboxClipped->y2)
+ {
+ pboxClipped++;
+ }
+ }
+ }
+ }
+ if (pboxClipped != pboxClippedBase)
+ {
+ if (pGC->fillStyle == FillSolid)
+ s3FillBoxSolid(pDrawable,
+ pboxClipped-pboxClippedBase, pboxClippedBase,
+ pGC->fgPixel, pGC->alu, pGC->planemask);
+ else if (s3Priv->pPattern)
+ s3FillBoxPattern (pDrawable,
+ pboxClipped-pboxClippedBase, pboxClippedBase,
+ pGC->alu, pGC->planemask,
+ s3Priv->pPattern);
+ else
+ s3FillBoxLargeStipple (pDrawable, pGC,
+ pboxClipped-pboxClippedBase,
+ pboxClippedBase);
+ }
+ if (pboxClippedBase != stackRects)
+ DEALLOCATE_LOCAL(pboxClippedBase);
+}
+
+void
+_s3FillSpanLargeStipple (DrawablePtr pDrawable, GCPtr pGC,
+ int n, DDXPointPtr ppt, int *pwidth)
+{
+ SetupS3 (pDrawable->pScreen);
+ DrawablePtr pStipple = &pGC->stipple->drawable;
+ int xRot = pGC->patOrg.x + pDrawable->x;
+ int yRot = pGC->patOrg.y + pDrawable->y;
+ FbStip *stip;
+ FbStride stipStride;
+ int stipBpp;
+ int stipWidth, stipHeight;
+ int dstX, dstY, width, height;
+
+ stipWidth = pStipple->width;
+ stipHeight = pStipple->height;
+ fbGetStipDrawable (pStipple, stip, stipStride, stipBpp);
+ if (pGC->fillStyle == FillOpaqueStippled)
+ {
+ _s3SetOpaquePlaneBlt(s3,pGC->alu,pGC->planemask,
+ pGC->fgPixel, pGC->bgPixel);
+
+ }
+ else
+ {
+ _s3SetTransparentPlaneBlt(s3,pGC->alu,pGC->planemask, pGC->fgPixel);
+ }
+ while (n--)
+ {
+ int stipX, stipY, sx;
+ int w;
+ int x, y;
+
+ dstX = ppt->x;
+ dstY = ppt->y;
+ ppt++;
+ width = *pwidth++;
+ modulus (dstY - yRot, stipHeight, stipY);
+ modulus (dstX - xRot, stipWidth, stipX);
+ y = dstY;
+ x = dstX;
+ sx = stipX;
+ while (width)
+ {
+ w = (stipWidth - sx);
+ if (w > width)
+ w = width;
+ width -= w;
+ _s3Stipple (s3c,
+ stip,
+ stipStride,
+ sx, stipY,
+ x, y,
+ w, 1);
+ x += w;
+ sx = 0;
+ }
+ }
+}
+
+void
+s3FillSpans (DrawablePtr pDrawable, GCPtr pGC, int n,
+ DDXPointPtr ppt, int *pwidth, int fSorted)
+{
+ s3GCPrivate(pGC);
+ SetupS3(pDrawable->pScreen);
+ int x, y;
+ int width;
+ /* next three parameters are post-clip */
+ int nTmp;
+ int *pwidthFree;/* copies of the pointers to free */
+ DDXPointPtr pptFree;
+ FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC);
+ BoxPtr extents;
+ S3PatternCache *cache;
+
+ nTmp = n * miFindMaxBand(fbGetCompositeClip(pGC));
+ pwidthFree = (int *)ALLOCATE_LOCAL(nTmp * sizeof(int));
+ pptFree = (DDXPointRec *)ALLOCATE_LOCAL(nTmp * sizeof(DDXPointRec));
+ if(!pptFree || !pwidthFree)
+ {
+ if (pptFree) DEALLOCATE_LOCAL(pptFree);
+ if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree);
+ return;
+ }
+ n = miClipSpans(fbGetCompositeClip(pGC),
+ ppt, pwidth, n,
+ pptFree, pwidthFree, fSorted);
+ pwidth = pwidthFree;
+ ppt = pptFree;
+ if (pGC->fillStyle == FillSolid)
+ {
+ _s3SetSolidFill(s3,pGC->fgPixel,pGC->alu,pGC->planemask);
+ while (n--)
+ {
+ x = ppt->x;
+ y = ppt->y;
+ ppt++;
+ width = *pwidth++;
+ if (width)
+ {
+ _s3SolidRect(s3,x,y,width,1);
+ }
+ }
+ }
+ else if (s3Priv->pPattern)
+ {
+ _s3SetPattern (pDrawable->pScreen, pGC->alu, pGC->planemask,
+ s3Priv->pPattern);
+ cache = s3Priv->pPattern->cache;
+ while (n--)
+ {
+ x = ppt->x;
+ y = ppt->y;
+ ppt++;
+ width = *pwidth++;
+ if (width)
+ {
+ _s3PatRect(s3, cache->x, cache->y, x, y, width, 1);
+ }
+ }
+ }
+ else
+ {
+ _s3FillSpanLargeStipple (pDrawable, pGC, n, ppt, pwidth);
+ }
+ _s3WaitIdleEmpty (s3);
+ DEALLOCATE_LOCAL(pptFree);
+ DEALLOCATE_LOCAL(pwidthFree);
+}
+
+#include "mifillarc.h"
+
+#define FILLSPAN(s3,y,__x1,__x2) {\
+ DRAW_DEBUG ((DEBUG_ARCS, "FILLSPAN %d: %d->%d", y, __x1, __x2)); \
+ if ((__x2) >= (__x1)) {\
+ _s3SolidRect(s3,(__x1),(y),(__x2)-(__x1)+1,1); \
+ } \
+}
+
+#define FILLSLICESPANS(flip,__y) \
+ if (!flip) \
+ { \
+ FILLSPAN(s3,__y,xl,xr) \
+ } \
+ else \
+ { \
+ xc = xorg - x; \
+ FILLSPAN(s3, __y, xc, xr) \
+ xc += slw - 1; \
+ FILLSPAN(s3, __y, xl, xc) \
+ }
+
+static void
+_s3FillEllipse (DrawablePtr pDraw, S3Ptr s3, xArc *arc)
+{
+ int x, y, e;
+ int yk, xk, ym, xm, dx, dy, xorg, yorg;
+ int y_top, y_bot;
+ miFillArcRec info;
+ register int xpos;
+ int slw;
+
+ miFillArcSetup(arc, &info);
+ MIFILLARCSETUP();
+ y_top = pDraw->y + yorg - y;
+ y_bot = pDraw->y + yorg + y + dy;
+ xorg += pDraw->x;
+ while (y)
+ {
+ y_top++;
+ y_bot--;
+ MIFILLARCSTEP(slw);
+ if (!slw)
+ continue;
+ xpos = xorg - x;
+ _s3SolidRect (s3,xpos,y_top,slw,1);
+ if (miFillArcLower(slw))
+ _s3SolidRect (s3,xpos,y_bot,slw,1);
+ }
+}
+
+
+static void
+_s3FillArcSlice (DrawablePtr pDraw, GCPtr pGC, S3Ptr s3, xArc *arc)
+{
+ int yk, xk, ym, xm, dx, dy, xorg, yorg, slw;
+ register int x, y, e;
+ miFillArcRec info;
+ miArcSliceRec slice;
+ int xl, xr, xc;
+ int y_top, y_bot;
+
+ DRAW_DEBUG ((DEBUG_ARCS, "slice %dx%d+%d+%d %d->%d",
+ arc->width, arc->height, arc->x, arc->y,
+ arc->angle1, arc->angle2));
+ miFillArcSetup(arc, &info);
+ miFillArcSliceSetup(arc, &slice, pGC);
+ DRAW_DEBUG ((DEBUG_ARCS, "edge1.x %d edge2.x %d",
+ slice.edge1.x, slice.edge2.x));
+ MIFILLARCSETUP();
+ DRAW_DEBUG ((DEBUG_ARCS, "xorg %d yorg %d",
+ xorg, yorg));
+ xorg += pDraw->x;
+ yorg += pDraw->y;
+ y_top = yorg - y;
+ y_bot = yorg + y + dy;
+ slice.edge1.x += pDraw->x;
+ slice.edge2.x += pDraw->x;
+ DRAW_DEBUG ((DEBUG_ARCS, "xorg %d y_top %d y_bot %d",
+ xorg, y_top, y_bot));
+ while (y > 0)
+ {
+ y_top++;
+ y_bot--;
+ MIFILLARCSTEP(slw);
+ MIARCSLICESTEP(slice.edge1);
+ MIARCSLICESTEP(slice.edge2);
+ if (miFillSliceUpper(slice))
+ {
+ MIARCSLICEUPPER(xl, xr, slice, slw);
+ FILLSLICESPANS(slice.flip_top, y_top);
+ }
+ if (miFillSliceLower(slice))
+ {
+ MIARCSLICELOWER(xl, xr, slice, slw);
+ FILLSLICESPANS(slice.flip_bot, y_bot);
+ }
+ }
+}
+
+void
+s3PolyFillArcSolid (DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs)
+{
+ SetupS3(pDraw->pScreen);
+ xArc *arc;
+ int i;
+ int x, y;
+ BoxRec box;
+ RegionPtr pClip = fbGetCompositeClip(pGC);
+ BOOL set;
+
+ set = FALSE;
+ for (; --narcs >= 0; parcs++)
+ {
+ if (miFillArcEmpty(parcs))
+ continue;
+ if (miCanFillArc(parcs))
+ {
+ box.x1 = parcs->x + pDraw->x;
+ box.y1 = parcs->y + pDraw->y;
+ box.x2 = box.x1 + (int)parcs->width + 1;
+ box.y2 = box.y1 + (int)parcs->height + 1;
+ switch (RECT_IN_REGION(pDraw->pScreen, pClip, &box))
+ {
+ case rgnIN:
+ if (!set)
+ {
+ _s3SetSolidFill (s3, pGC->fgPixel, pGC->alu, pGC->planemask);
+ set = TRUE;
+ }
+ if ((parcs->angle2 >= FULLCIRCLE) ||
+ (parcs->angle2 <= -FULLCIRCLE))
+ {
+ DRAW_DEBUG ((DEBUG_ARCS, "Full circle ellipse %dx%d",
+ parcs->width, parcs->height));
+ _s3FillEllipse (pDraw, s3, parcs);
+ }
+ else
+ {
+ DRAW_DEBUG ((DEBUG_ARCS, "Partial ellipse %dx%d",
+ parcs->width, parcs->height));
+ _s3FillArcSlice (pDraw, pGC, s3, parcs);
+ }
+ /* fall through ... */
+ case rgnOUT:
+ continue;
+ case rgnPART:
+ break;
+ }
+ }
+ if (set)
+ {
+ _s3WaitIdleEmpty(s3);
+ set = FALSE;
+ }
+ miPolyFillArc(pDraw, pGC, 1, parcs);
+ }
+ if (set)
+ {
+ _s3WaitIdleEmpty(s3);
+ set = FALSE;
+ }
+}
+
+void
+s3FillPoly1Rect (DrawablePtr pDrawable, GCPtr pGC, int shape,
+ int mode, int countInit, DDXPointPtr ptsIn)
+{
+ SetupS3(pDrawable->pScreen);
+ FbGCPrivPtr fbPriv;
+ int nwidth;
+ int maxy;
+ int count;
+ register int vertex1, vertex2;
+ int c;
+ BoxPtr extents;
+ int y, sy;
+ int *vertex1p, *vertex2p;
+ int *endp;
+ int x1, x2, sx;
+ int dx1, dx2;
+ int dy1, dy2;
+ int e1, e2;
+ int step1, step2;
+ int sign1, sign2;
+ int h;
+ int l, r;
+ int nmiddle;
+
+ if (mode == CoordModePrevious)
+ {
+ miFillPolygon (pDrawable, pGC, shape, mode, countInit, ptsIn);
+ return;
+ }
+
+ fbPriv = fbGetGCPrivate(pGC);
+ sy = pDrawable->y;
+ sx = pDrawable->x;
+ extents = &fbGetCompositeClip(pGC)->extents;
+
+ y = 32767;
+ maxy = 0;
+ vertex2p = (int *) ptsIn;
+ endp = vertex2p + countInit;
+ if (shape == Convex)
+ {
+ count = countInit;
+ while (count--)
+ {
+ c = *vertex2p;
+ /*
+ * Check for negative or over S3 limits
+ */
+ if (c & 0xe000e000)
+ {
+ miFillPolygon (pDrawable, pGC, shape, mode, countInit, ptsIn);
+ return;
+ }
+ c = intToY(c);
+ DRAW_DEBUG ((DEBUG_POLYGON, "Y coordinate %d", c));
+ if (c < y)
+ {
+ y = c;
+ vertex1p = vertex2p;
+ }
+ vertex2p++;
+ if (c > maxy)
+ maxy = c;
+ }
+ }
+ else
+ {
+ int yFlip = 0;
+ dx1 = 1;
+ x2 = -1;
+ x1 = -1;
+ count = countInit;
+ while (count--)
+ {
+ c = *vertex2p;
+ /*
+ * Check for negative or over S3 limits
+ */
+ if (c & 0xe000e000)
+ {
+ miFillPolygon (pDrawable, pGC, shape, mode, countInit, ptsIn);
+ return;
+ }
+ c = intToY(c);
+ DRAW_DEBUG ((DEBUG_POLYGON, "Y coordinate %d", c));
+ if (c < y)
+ {
+ y = c;
+ vertex1p = vertex2p;
+ }
+ vertex2p++;
+ if (c > maxy)
+ maxy = c;
+ if (c == x1)
+ continue;
+ if (dx1 > 0)
+ {
+ if (x2 < 0)
+ x2 = c;
+ else
+ dx2 = dx1 = (c - x1) >> 31;
+ }
+ else
+ if ((c - x1) >> 31 != dx1)
+ {
+ dx1 = ~dx1;
+ yFlip++;
+ }
+ x1 = c;
+ }
+ x1 = (x2 - c) >> 31;
+ if (x1 != dx1)
+ yFlip++;
+ if (x1 != dx2)
+ yFlip++;
+ if (yFlip != 2)
+ {
+ miFillPolygon (pDrawable, pGC, shape, mode, countInit, ptsIn);
+ return;
+ }
+ }
+ if (y == maxy)
+ return;
+
+ _s3SetSolidFill(s3,pGC->fgPixel,pGC->alu,pGC->planemask);
+ _s3SetClip(s3,extents);
+
+ vertex2p = vertex1p;
+ vertex2 = vertex1 = *vertex2p++;
+ if (vertex2p == endp)
+ vertex2p = (int *) ptsIn;
+#define Setup(c,x,vertex,dx,dy,e,sign,step) {\
+ x = intToX(vertex); \
+ if (dy = intToY(c) - y) { \
+ dx = intToX(c) - x; \
+ step = 0; \
+ if (dx >= 0) \
+ { \
+ e = 0; \
+ sign = 1; \
+ if (dx >= dy) {\
+ step = dx / dy; \
+ dx = dx % dy; \
+ } \
+ } \
+ else \
+ { \
+ e = 1 - dy; \
+ sign = -1; \
+ dx = -dx; \
+ if (dx >= dy) { \
+ step = - (dx / dy); \
+ dx = dx % dy; \
+ } \
+ } \
+ } \
+ x += sx; \
+ vertex = c; \
+}
+
+#define Step(x,dx,dy,e,sign,step) {\
+ x += step; \
+ if ((e += dx) > 0) \
+ { \
+ x += sign; \
+ e -= dy; \
+ } \
+}
+ sy += y;
+ DRAW_DEBUG ((DEBUG_POLYGON, "Starting polygon at %d", sy));
+ for (;;)
+ {
+ DRAW_DEBUG ((DEBUG_POLYGON, "vertex1 0x%x vertex2 0x%x y %d vy1 %d vy2 %d",
+ vertex1, vertex2,
+ y, intToY(vertex1), intToY (vertex2)));
+ if (y == intToY(vertex1))
+ {
+ DRAW_DEBUG ((DEBUG_POLYGON, "Find next -- vertext"));
+ do
+ {
+ if (vertex1p == (int *) ptsIn)
+ vertex1p = endp;
+ c = *--vertex1p;
+ Setup (c,x1,vertex1,dx1,dy1,e1,sign1,step1);
+ DRAW_DEBUG ((DEBUG_POLYGON, "-- vertex 0x%x y %d",
+ vertex1, intToY(vertex1)));
+ } while (y >= intToY(vertex1));
+ h = dy1;
+ }
+ else
+ {
+ Step(x1,dx1,dy1,e1,sign1,step1)
+ h = intToY(vertex1) - y;
+ }
+ if (y == intToY(vertex2))
+ {
+ DRAW_DEBUG ((DEBUG_POLYGON, "Find next ++ vertext"));
+ do
+ {
+ c = *vertex2p++;
+ if (vertex2p == endp)
+ vertex2p = (int *) ptsIn;
+ Setup (c,x2,vertex2,dx2,dy2,e2,sign2,step2)
+ DRAW_DEBUG ((DEBUG_POLYGON, "++ vertex 0x%x y %d",
+ vertex1, intToY(vertex1)));
+ } while (y >= intToY(vertex2));
+ if (dy2 < h)
+ h = dy2;
+ }
+ else
+ {
+ Step(x2,dx2,dy2,e2,sign2,step2)
+ if ((c = (intToY(vertex2) - y)) < h)
+ h = c;
+ }
+ DRAW_DEBUG ((DEBUG_POLYGON, "This band %d", h));
+ /* fill spans for this segment */
+ for (;;)
+ {
+ nmiddle = x2 - x1;
+ DRAW_DEBUG ((DEBUG_POLYGON, "This span %d->%d", x1, x2));
+ if (nmiddle)
+ {
+ l = x1;
+ if (nmiddle < 0)
+ {
+ nmiddle = -nmiddle;
+ l = x2;
+ }
+ _s3SolidRect(s3,l,sy,nmiddle,1);
+ }
+ y++;
+ sy++;
+ if (!--h)
+ break;
+ Step(x1,dx1,dy1,e1,sign1,step1)
+ Step(x2,dx2,dy2,e2,sign2,step2)
+ }
+ if (y == maxy)
+ break;
+ }
+ _s3ResetClip (s3, pDrawable->pScreen);
+ _s3WaitIdleEmpty(s3);
+}
+
+void
+s3PolyGlyphBltClipped (DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x, int y,
+ unsigned int nglyph,
+ CharInfoPtr *ppciInit,
+ pointer pglyphBase)
+{
+ SetupS3(pDrawable->pScreen);
+ int h;
+ int w;
+ int xBack, yBack;
+ int hBack, wBack;
+ int lw;
+ FontPtr pfont = pGC->font;
+ CharInfoPtr pci;
+ unsigned long *bits;
+ BoxPtr extents;
+ BoxRec bbox;
+ CARD32 b;
+ CharInfoPtr *ppci;
+ FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC);
+ RegionPtr pClip = fbGetCompositeClip(pGC);
+ BoxPtr pBox;
+ int nbox;
+ int x1, y1, x2, y2;
+ unsigned char alu;
+ Bool locked;
+ PixTransDeclare;
+
+ x += pDrawable->x;
+ y += pDrawable->y;
+
+ if (pglyphBase == (pointer) 1)
+ {
+ xBack = x;
+ yBack = y - FONTASCENT(pGC->font);
+ wBack = 0;
+ hBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
+ if (hBack)
+ {
+ h = nglyph;
+ ppci = ppciInit;
+ while (h--)
+ wBack += (*ppci++)->metrics.characterWidth;
+ }
+ if (wBack < 0)
+ {
+ xBack = xBack + wBack;
+ wBack = -wBack;
+ }
+ if (hBack < 0)
+ {
+ yBack = yBack + hBack;
+ hBack = -hBack;
+ }
+ alu = GXcopy;
+ }
+ else
+ {
+ wBack = 0;
+ alu = pGC->alu;
+ }
+
+ if (wBack)
+ {
+ _s3SetSolidFill (s3, pGC->bgPixel, GXcopy, pGC->planemask);
+ for (nbox = REGION_NUM_RECTS (pClip),
+ pBox = REGION_RECTS (pClip);
+ nbox--;
+ pBox++)
+ {
+ x1 = xBack;
+ x2 = xBack + wBack;
+ y1 = yBack;
+ y2 = yBack + hBack;
+ if (x1 < pBox->x1) x1 = pBox->x1;
+ if (x2 > pBox->x2) x2 = pBox->x2;
+ if (y1 < pBox->y1) y1 = pBox->y1;
+ if (y2 > pBox->y2) y2 = pBox->y2;
+ if (x1 < x2 && y1 < y2)
+ {
+ _s3SolidRect (s3, x1, y1, x2 - x1, y2 - y1);
+ }
+ }
+ }
+ _s3SetTransparentPlaneBlt (s3, alu, pGC->planemask, pGC->fgPixel);
+ ppci = ppciInit;
+ locked = TRUE;
+ while (nglyph--)
+ {
+ pci = *ppci++;
+ h = pci->metrics.ascent + pci->metrics.descent;
+ w = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing;
+ x1 = x + pci->metrics.leftSideBearing;
+ y1 = y - pci->metrics.ascent;
+ bbox.x1 = x1;
+ bbox.y1 = y1;
+ bbox.x2 = x1 + w;
+ bbox.y2 = y1 + h;
+ switch (RECT_IN_REGION(pGC->pScreen, pClip, &bbox))
+ {
+ case rgnIN:
+ lw = h * ((w + 31) >> 5);
+ if (lw)
+ {
+ if (!locked)
+ {
+ _s3SetTransparentPlaneBlt (s3, alu, pGC->planemask, pGC->fgPixel);
+ locked = TRUE;
+ }
+ _s3PlaneBlt(s3,
+ x + pci->metrics.leftSideBearing,
+ y - pci->metrics.ascent,
+ w, h);
+ bits = (unsigned long *) pci->bits;
+ PixTransStart (lw);
+ while (lw--)
+ {
+ b = *bits++;
+ S3InvertBits32 (b);
+ PixTransStore(b);
+ }
+ }
+ break;
+ case rgnPART:
+ if (locked)
+ {
+ _s3WaitIdleEmpty(s3);
+ locked = FALSE;
+ }
+ fbPutXYImage (pDrawable,
+ pClip,
+ fbPriv->fg,
+ fbPriv->bg,
+ fbPriv->pm,
+ alu,
+ FALSE,
+ x1, y1,
+ w, h,
+ (FbStip *) pci->bits,
+ (w + 31) >> 5,
+ 0);
+ break;
+ case rgnOUT:
+ break;
+ }
+ x += pci->metrics.characterWidth;
+ }
+ _s3WaitIdleEmpty(s3);
+}
+
+/*
+ * Blt glyphs using S3 image transfer register, this does both
+ * poly glyph blt and image glyph blt (when pglyphBase == 1)
+ */
+
+void
+s3PolyGlyphBlt (DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x, int y,
+ unsigned int nglyph,
+ CharInfoPtr *ppciInit,
+ pointer pglyphBase)
+{
+ SetupS3(pDrawable->pScreen);
+ int h;
+ int w;
+ int xBack, yBack;
+ int hBack, wBack;
+ int lw;
+ FontPtr pfont = pGC->font;
+ CharInfoPtr pci;
+ unsigned long *bits;
+ BoxPtr extents;
+ BoxRec bbox;
+ CARD32 b;
+ CharInfoPtr *ppci;
+ unsigned char alu;
+ PixTransDeclare;
+
+ x += pDrawable->x;
+ y += pDrawable->y;
+
+ /* compute an approximate (but covering) bounding box */
+ ppci = ppciInit;
+ w = 0;
+ h = nglyph;
+ while (h--)
+ w += (*ppci++)->metrics.characterWidth;
+ if (w < 0)
+ {
+ bbox.x1 = x + w;
+ bbox.x2 = x;
+ }
+ else
+ {
+ bbox.x1 = x;
+ bbox.x2 = x + w;
+ }
+ w = FONTMINBOUNDS(pfont,leftSideBearing);
+ if (w < 0)
+ bbox.x1 += w;
+ w = FONTMAXBOUNDS(pfont, rightSideBearing) - FONTMINBOUNDS(pfont, characterWidth);
+ if (w > 0)
+ bbox.x2 += w;
+ bbox.y1 = y - FONTMAXBOUNDS(pfont,ascent);
+ bbox.y2 = y + FONTMAXBOUNDS(pfont,descent);
+
+ DRAW_DEBUG ((DEBUG_TEXT, "PolyGlyphBlt %d box is %d %d", nglyph,
+ bbox.x1, bbox.x2));
+ switch (RECT_IN_REGION(pGC->pScreen, fbGetCompositeClip(pGC), &bbox))
+ {
+ case rgnIN:
+ break;
+ case rgnPART:
+ s3PolyGlyphBltClipped(pDrawable, pGC, x - pDrawable->x,
+ y - pDrawable->y,
+ nglyph, ppciInit, pglyphBase);
+ case rgnOUT:
+ return;
+ }
+
+ if (pglyphBase == (pointer) 1)
+ {
+ xBack = x;
+ yBack = y - FONTASCENT(pGC->font);
+ wBack = 0;
+ hBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
+ if (hBack)
+ {
+ h = nglyph;
+ ppci = ppciInit;
+ while (h--)
+ wBack += (*ppci++)->metrics.characterWidth;
+ }
+ if (wBack < 0)
+ {
+ xBack = xBack + wBack;
+ wBack = -wBack;
+ }
+ if (hBack < 0)
+ {
+ yBack = yBack + hBack;
+ hBack = -hBack;
+ }
+ alu = GXcopy;
+ }
+ else
+ {
+ wBack = 0;
+ alu = pGC->alu;
+ }
+
+ if (wBack)
+ {
+ _s3SetSolidFill (s3, pGC->bgPixel, GXcopy, pGC->planemask);
+ _s3SolidRect (s3, xBack, yBack, wBack, hBack);
+ }
+ _s3SetTransparentPlaneBlt (s3, alu, pGC->planemask, pGC->fgPixel);
+ ppci = ppciInit;
+ while (nglyph--)
+ {
+ pci = *ppci++;
+ h = pci->metrics.ascent + pci->metrics.descent;
+ w = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing;
+ lw = h * ((w + 31) >> 5);
+ if (lw)
+ {
+ _s3PlaneBlt(s3,
+ x + pci->metrics.leftSideBearing,
+ y - pci->metrics.ascent,
+ w, h);
+ bits = (unsigned long *) pci->bits;
+ PixTransStart(lw);
+ while (lw--)
+ {
+ b = *bits++;
+ S3InvertBits32 (b);
+ PixTransStore(b);
+ }
+ }
+ x += pci->metrics.characterWidth;
+ }
+ _s3WaitIdleEmpty(s3);
+}
+
+void
+s3ImageGlyphBlt (DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x, int y,
+ unsigned int nglyph,
+ CharInfoPtr *ppci,
+ pointer pglyphBase)
+{
+ s3PolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, (pointer) 1);
+}
+
+/*
+ * Blt TE fonts using S3 image transfer. Differs from
+ * above in that it doesn't need to fill a solid rect for
+ * the background and it can draw multiple characters at a time
+ */
+
+void
+s3ImageTEGlyphBlt (DrawablePtr pDrawable, GCPtr pGC,
+ int xInit, int yInit,
+ unsigned int nglyph,
+ CharInfoPtr *ppci,
+ pointer pglyphBase)
+{
+ SetupS3(pDrawable->pScreen);
+ int x, y;
+ int h, lw, lwTmp;
+ int w;
+ FontPtr pfont = pGC->font;
+ unsigned long *char1, *char2, *char3, *char4;
+ int widthGlyphs, widthGlyph;
+ BoxRec bbox;
+ CARD32 tmp;
+ PixTransDeclare;
+
+ widthGlyph = FONTMAXBOUNDS(pfont,characterWidth);
+ if (!widthGlyph)
+ return;
+
+ h = FONTASCENT(pfont) + FONTDESCENT(pfont);
+ if (!h)
+ return;
+
+ DRAW_DEBUG ((DEBUG_TEXT, "ImageTEGlyphBlt chars are %d %d",
+ widthGlyph, h));
+
+ x = xInit + FONTMAXBOUNDS(pfont,leftSideBearing) + pDrawable->x;
+ y = yInit - FONTASCENT(pfont) + pDrawable->y;
+
+ bbox.x1 = x;
+ bbox.x2 = x + (widthGlyph * nglyph);
+ bbox.y1 = y;
+ bbox.y2 = y + h;
+
+ switch (RECT_IN_REGION(pGC->pScreen, fbGetCompositeClip(pGC), &bbox))
+ {
+ case rgnPART:
+ if (pglyphBase == (pointer) 1)
+ pglyphBase = 0;
+ else
+ pglyphBase = (pointer) 1;
+ s3PolyGlyphBltClipped(pDrawable, pGC,
+ xInit,
+ yInit,
+ nglyph, ppci,
+ pglyphBase);
+ case rgnOUT:
+ return;
+ }
+
+ if (pglyphBase == (pointer) 1)
+ {
+ _s3SetTransparentPlaneBlt (s3, pGC->alu, pGC->planemask, pGC->fgPixel);
+ }
+ else
+ {
+ _s3SetOpaquePlaneBlt (s3, GXcopy, pGC->planemask, pGC->fgPixel, pGC->bgPixel);
+ }
+
+#define LoopIt(count, w, loadup, fetch) \
+ while (nglyph >= count) \
+ { \
+ nglyph -= count; \
+ _s3PlaneBlt (s3, x, y, w, h); \
+ x += w; \
+ loadup \
+ lwTmp = h; \
+ PixTransStart(h); \
+ while (lwTmp--) { \
+ tmp = fetch; \
+ S3InvertBits32(tmp); \
+ PixTransStore(tmp); \
+ } \
+ }
+
+ if (widthGlyph <= 8)
+ {
+ widthGlyphs = widthGlyph << 2;
+ LoopIt(4, widthGlyphs,
+ char1 = (unsigned long *) (*ppci++)->bits;
+ char2 = (unsigned long *) (*ppci++)->bits;
+ char3 = (unsigned long *) (*ppci++)->bits;
+ char4 = (unsigned long *) (*ppci++)->bits;,
+ (*char1++ | ((*char2++ | ((*char3++ | (*char4++
+ << widthGlyph))
+ << widthGlyph))
+ << widthGlyph)))
+ }
+ else if (widthGlyph <= 10)
+ {
+ widthGlyphs = (widthGlyph << 1) + widthGlyph;
+ LoopIt(3, widthGlyphs,
+ char1 = (unsigned long *) (*ppci++)->bits;
+ char2 = (unsigned long *) (*ppci++)->bits;
+ char3 = (unsigned long *) (*ppci++)->bits;,
+ (*char1++ | ((*char2++ | (*char3++ << widthGlyph)) << widthGlyph)))
+ }
+ else if (widthGlyph <= 16)
+ {
+ widthGlyphs = widthGlyph << 1;
+ LoopIt(2, widthGlyphs,
+ char1 = (unsigned long *) (*ppci++)->bits;
+ char2 = (unsigned long *) (*ppci++)->bits;,
+ (*char1++ | (*char2++ << widthGlyph)))
+ }
+ lw = h * ((widthGlyph + 31) >> 5);
+ while (nglyph--)
+ {
+ _s3PlaneBlt (s3, x, y, widthGlyph, h);
+ x += widthGlyph;
+ char1 = (unsigned long *) (*ppci++)->bits;
+ lwTmp = lw;
+ PixTransStart(lw);
+ while (lwTmp--)
+ {
+ tmp = *char1++;
+ S3InvertBits32(tmp);
+ PixTransStore(tmp);
+ }
+ }
+ _s3WaitIdleEmpty (s3);
+}
+
+void
+s3PolyTEGlyphBlt (DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y,
+ unsigned int nglyph, CharInfoPtr *ppci,
+ pointer pglyphBase)
+{
+ s3ImageTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, (pointer) 1);
+}
+
+#define _s3ClipLine(s3,cmd,e1,e2,e,len) {\
+ DRAW_DEBUG ((DEBUG_RENDER, "clip line 0x%x 0x%x 0x%x 0x%x 0x%x", cmd,e1,e2,e,len)); \
+ _s3CmdWait(s3); \
+ _s3SetPcnt (s3, (len), 0); \
+ _s3SetStep (s3, e2, e1); \
+ _s3SetErr (s3, e); \
+ _s3SetCmd (s3, CMD_LINE | (cmd) | DRAW | WRTDATA); \
+}
+
+void
+_s3Segment (DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x1,
+ int y1,
+ int x2,
+ int y2,
+ Bool drawLast)
+{
+ SetupS3(pDrawable->pScreen);
+ FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
+ RegionPtr pClip = fbGetCompositeClip(pGC);
+ BoxPtr pBox;
+ int nBox;
+ int adx; /* abs values of dx and dy */
+ int ady;
+ int signdx; /* sign of dx and dy */
+ int signdy;
+ int e, e1, e2; /* bresenham error and increments */
+ int len; /* length of segment */
+ int axis; /* major axis */
+ int octant;
+ int cmd;
+ unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
+ unsigned int oc1; /* outcode of point 1 */
+ unsigned int oc2; /* outcode of point 2 */
+
+ nBox = REGION_NUM_RECTS (pClip);
+ pBox = REGION_RECTS (pClip);
+ CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy,
+ 1, 1, octant);
+
+ cmd = LASTPIX;
+
+ if (signdx > 0)
+ cmd |= INC_X;
+ if (signdy > 0)
+ cmd |= INC_Y;
+
+ if (adx > ady)
+ {
+ axis = X_AXIS;
+ e1 = ady << 1;
+ e2 = e1 - (adx << 1);
+ e = e1 - adx;
+ len = adx;
+ }
+ else
+ {
+ cmd |= YMAJAXIS;
+ axis = Y_AXIS;
+ e1 = adx << 1;
+ e2 = e1 - (ady << 1);
+ e = e1 - ady;
+ SetYMajorOctant(octant);
+ len = ady;
+ }
+
+ FIXUP_ERROR (e, octant, bias);
+
+ /* we have bresenham parameters and two points.
+ all we have to do now is clip and draw.
+ */
+
+ if (drawLast)
+ len++;
+ while(nBox--)
+ {
+ oc1 = 0;
+ oc2 = 0;
+ OUTCODES(oc1, x1, y1, pBox);
+ OUTCODES(oc2, x2, y2, pBox);
+ if ((oc1 | oc2) == 0)
+ {
+ _s3SetCur (s3, x1, y1);
+ _s3ClipLine (s3, cmd, e1, e2, e, len);
+ break;
+ }
+ else if (oc1 & oc2)
+ {
+ pBox++;
+ }
+ else
+ {
+ int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2;
+ int clip1 = 0, clip2 = 0;
+ int clipdx, clipdy;
+ int err;
+
+ if (miZeroClipLine(pBox->x1, pBox->y1, pBox->x2-1,
+ pBox->y2-1,
+ &new_x1, &new_y1, &new_x2, &new_y2,
+ adx, ady, &clip1, &clip2,
+ octant, bias, oc1, oc2) == -1)
+ {
+ pBox++;
+ continue;
+ }
+
+ if (axis == X_AXIS)
+ len = abs(new_x2 - new_x1);
+ else
+ len = abs(new_y2 - new_y1);
+ if (clip2 != 0 || drawLast)
+ len++;
+ if (len)
+ {
+ /* unwind bresenham error term to first point */
+ err = e;
+ if (clip1)
+ {
+ clipdx = abs(new_x1 - x1);
+ clipdy = abs(new_y1 - y1);
+ if (axis == X_AXIS)
+ err += (e2 - e1) * clipdy + e1 * clipdx;
+ else
+ err += (e2 - e1) * clipdx + e1 * clipdy;
+ }
+ _s3SetCur (s3, new_x1, new_y1);
+ _s3ClipLine (s3, cmd, e1, e2, err, len);
+ }
+ pBox++;
+ }
+ } /* while (nBox--) */
+}
+
+void
+s3Polylines (DrawablePtr pDrawable, GCPtr pGC,
+ int mode, int npt, DDXPointPtr ppt)
+{
+ SetupS3(pDrawable->pScreen);
+ int x, y, nx, ny;
+ int ox = pDrawable->x, oy = pDrawable->y;
+
+ if (!npt)
+ return;
+
+ _s3SetSolidFill (s3, pGC->fgPixel, pGC->alu, pGC->planemask);
+ x = ppt->x + ox;
+ y = ppt->y + oy;
+ while (--npt)
+ {
+ ++ppt;
+ if (mode == CoordModePrevious)
+ {
+ nx = x + ppt->x;
+ ny = y + ppt->y;
+ }
+ else
+ {
+ nx = ppt->x + ox;
+ ny = ppt->y + oy;
+ }
+ _s3Segment (pDrawable, pGC, x, y, nx, ny,
+ npt == 1 && pGC->capStyle != CapNotLast);
+ x = nx;
+ y = ny;
+ }
+ _s3WaitIdleEmpty(s3);
+}
+
+void
+s3PolySegment (DrawablePtr pDrawable, GCPtr pGC,
+ int nsegInit, xSegment *pSegInit)
+{
+ SetupS3(pDrawable->pScreen);
+ int x, y;
+ int ox = pDrawable->x, oy = pDrawable->y;
+ RegionPtr pClip = fbGetCompositeClip (pGC);
+ BoxPtr pBox;
+ int nbox;
+ int nseg;
+ xSegment *pSeg;
+ int dx, dy;
+ int maj, min, len, inc;
+ int t;
+ CARD32 cmd;
+ CARD32 init_cmd;
+ Bool drawLast;
+
+ drawLast = pGC->capStyle != CapNotLast;
+ _s3SetSolidFill (s3, pGC->fgPixel, pGC->alu, pGC->planemask);
+
+ for (nseg = nsegInit, pSeg = pSegInit; nseg--; pSeg++)
+ {
+ _s3Segment (pDrawable, pGC, pSeg->x1 + ox, pSeg->y1 + oy,
+ pSeg->x2 + ox, pSeg->y2 + oy, drawLast);
+
+ }
+ _s3WaitIdleEmpty(s3);
+}
+
+/*
+ * Check to see if a pattern can be painted with the S3
+ */
+
+#define _s3CheckPatternSize(s) ((s) <= S3_TILE_SIZE && ((s) & ((s) - 1)) == 0)
+#define s3CheckPattern(w,h) (_s3CheckPatternSize(w) && _s3CheckPatternSize(h))
+
+Bool
+s3AllocPattern (ScreenPtr pScreen,
+ PixmapPtr pPixmap,
+ int xorg, int yorg,
+ int fillStyle, Pixel fg, Pixel bg,
+ s3PatternPtr *ppPattern)
+{
+ KdScreenPriv(pScreen);
+ s3ScreenInfo(pScreenPriv);
+ s3PatternPtr pPattern;
+
+ if (s3s->patterns.cache && fillStyle != FillSolid &&
+ s3CheckPattern (pPixmap->drawable.width, pPixmap->drawable.height))
+ {
+ if (!(pPattern = *ppPattern))
+ {
+ pPattern = (s3PatternPtr) xalloc (sizeof (s3PatternRec));
+ if (!pPattern)
+ return FALSE;
+ *ppPattern = pPattern;
+ }
+
+ pPattern->cache = 0;
+ pPattern->id = 0;
+ pPattern->pPixmap = pPixmap;
+ pPattern->fillStyle = fillStyle;
+ pPattern->xrot = (-xorg) & (S3_TILE_SIZE-1);
+ pPattern->yrot = (-yorg) & (S3_TILE_SIZE-1);
+ pPattern->fore = fg;
+ pPattern->back = bg;
+ return TRUE;
+ }
+ else
+ {
+ if (*ppPattern)
+ {
+ xfree (*ppPattern);
+ *ppPattern = 0;
+ }
+ return FALSE;
+ }
+}
+
+void
+s3CheckGCFill (GCPtr pGC)
+{
+ s3PrivGCPtr s3Priv = s3GetGCPrivate (pGC);
+ PixmapPtr pPixmap;
+
+ switch (pGC->fillStyle) {
+ case FillSolid:
+ pPixmap = 0;
+ break;
+ case FillOpaqueStippled:
+ case FillStippled:
+ pPixmap = pGC->stipple;
+ break;
+ case FillTiled:
+ pPixmap = pGC->tile.pixmap;
+ break;
+ }
+ s3AllocPattern (pGC->pScreen,
+ pPixmap,
+ pGC->patOrg.x + pGC->lastWinOrg.x,
+ pGC->patOrg.y + pGC->lastWinOrg.y,
+ pGC->fillStyle, pGC->fgPixel, pGC->bgPixel,
+ &s3Priv->pPattern);
+}
+
+void
+s3MoveGCFill (GCPtr pGC)
+{
+ s3PrivGCPtr s3Priv = s3GetGCPrivate (pGC);
+ int xorg, yorg;
+ s3PatternPtr pPattern;
+
+ if (pPattern = s3Priv->pPattern)
+ {
+ /*
+ * Reset origin
+ */
+ xorg = pGC->patOrg.x + pGC->lastWinOrg.x;
+ yorg = pGC->patOrg.y + pGC->lastWinOrg.y;
+ pPattern->xrot = (-xorg) & (S3_TILE_SIZE - 1);
+ pPattern->yrot = (-yorg) & (S3_TILE_SIZE - 1);
+ /*
+ * Invalidate cache entry
+ */
+ pPattern->id = 0;
+ pPattern->cache = 0;
+ }
+}
+
+/*
+ * S3 Patterns. These are always full-depth images, stored in off-screen
+ * memory.
+ */
+
+Pixel
+s3FetchPatternPixel (s3PatternPtr pPattern, int x, int y)
+{
+ CARD8 *src;
+ CARD16 *src16;
+ CARD32 *src32;
+ PixmapPtr pPixmap = pPattern->pPixmap;
+
+ x = (x + pPattern->xrot) % pPixmap->drawable.width;
+ y = (y + pPattern->yrot) % pPixmap->drawable.height;
+ src = (CARD8 *) pPixmap->devPrivate.ptr + y * pPixmap->devKind;
+ switch (pPixmap->drawable.bitsPerPixel) {
+ case 1:
+ return (src[x>>3] >> (x & 7)) & 1 ? 0xffffffff : 0x00;
+ case 4:
+ if (x & 1)
+ return src[x>>1] >> 4;
+ else
+ return src[x>>1] & 0xf;
+ case 8:
+ return src[x];
+ case 16:
+ src16 = (CARD16 *) src;
+ return src16[x];
+ case 32:
+ src32 = (CARD32 *) src;
+ return src32[x];
+ }
+}
+
+/*
+ * Place pattern image on screen; done with S3 locked
+ */
+void
+_s3PutPattern (ScreenPtr pScreen, s3PatternPtr pPattern)
+{
+ SetupS3(pScreen);
+ int x, y;
+ CARD8 *dstLine, *dst8;
+ CARD16 *dst16;
+ CARD32 *dst32;
+ S3PatternCache *cache = pPattern->cache;
+
+ DRAW_DEBUG ((DEBUG_PATTERN, "_s3PutPattern 0x%x id %d to %d %d",
+ pPattern, pPattern->id, cache->x, cache->y));
+
+ dstLine = (pScreenPriv->screen->frameBuffer +
+ cache->y * pScreenPriv->screen->byteStride +
+ cache->x * pScreenPriv->bytesPerPixel);
+
+ for (y = 0; y < S3_TILE_SIZE; y++)
+ {
+ switch (pScreenPriv->screen->bitsPerPixel) {
+ case 8:
+ dst8 = dstLine;
+ for (x = 0; x < S3_TILE_SIZE; x++)
+ *dst8++ = s3FetchPatternPixel (pPattern, x, y);
+ DRAW_DEBUG ((DEBUG_PATTERN, "%c%c%c%c%c%c%c%c",
+ dstLine[0] ? 'X' : ' ',
+ dstLine[1] ? 'X' : ' ',
+ dstLine[2] ? 'X' : ' ',
+ dstLine[3] ? 'X' : ' ',
+ dstLine[4] ? 'X' : ' ',
+ dstLine[5] ? 'X' : ' ',
+ dstLine[6] ? 'X' : ' ',
+ dstLine[7] ? 'X' : ' '));
+ break;
+ case 16:
+ dst16 = (CARD16 *) dstLine;
+ for (x = 0; x < S3_TILE_SIZE; x++)
+ *dst16++ = s3FetchPatternPixel (pPattern, x, y);
+ break;
+ case 32:
+ dst32 = (CARD32 *) dstLine;
+ for (x = 0; x < S3_TILE_SIZE; x++)
+ *dst32++ = s3FetchPatternPixel (pPattern, x, y);
+ break;
+ }
+ dstLine += pScreenPriv->screen->byteStride;
+ }
+}
+
+/*
+ * Load a stipple to off-screen memory; done with S3 locked
+ */
+void
+_s3LoadPattern (ScreenPtr pScreen, s3PatternPtr pPattern)
+{
+ SetupS3(pScreen);
+ s3ScreenInfo(pScreenPriv);
+ S3PatternCache *cache;
+
+ DRAW_DEBUG((DEBUG_PATTERN,
+ "s3LoadPattern 0x%x id %d cache 0x%x cacheid %d",
+ pPattern, pPattern->id, pPattern->cache,
+ pPattern->cache ? pPattern->cache->id : -1));
+ /*
+ * Check to see if its still loaded
+ */
+ cache = pPattern->cache;
+ if (cache && cache->id == pPattern->id)
+ return;
+ /*
+ * Lame replacement strategy; assume we'll have plenty of room.
+ */
+ cache = &s3s->patterns.cache[s3s->patterns.last_used];
+ if (++s3s->patterns.last_used == s3s->patterns.ncache)
+ s3s->patterns.last_used = 0;
+ cache->id = ++s3s->patterns.last_id;
+ pPattern->id = cache->id;
+ pPattern->cache = cache;
+ _s3PutPattern (pScreen, pPattern);
+}
+
+void
+s3DestroyGC (GCPtr pGC)
+{
+ s3PrivGCPtr s3Priv = s3GetGCPrivate (pGC);
+
+ if (s3Priv->pPattern)
+ xfree (s3Priv->pPattern);
+ miDestroyGC (pGC);
+}
+
+GCFuncs s3GCFuncs = {
+ s3ValidateGC,
+ miChangeGC,
+ miCopyGC,
+ s3DestroyGC,
+ miChangeClip,
+ miDestroyClip,
+ miCopyClip
+};
+
+int
+s3CreateGC (GCPtr pGC)
+{
+ s3PrivGCPtr s3Priv;
+
+ if (!fbCreateGC (pGC))
+ return FALSE;
+
+ if (pGC->depth != 1)
+ pGC->funcs = &s3GCFuncs;
+
+ s3Priv = s3GetGCPrivate(pGC);
+ s3Priv->type = DRAWABLE_PIXMAP;
+ s3Priv->pPattern = 0;
+
+ return TRUE;
+}
+
+Bool
+s3CreateWindow (WindowPtr pWin)
+{
+ if (!KdCreateWindow (pWin))
+ return FALSE;
+ pWin->devPrivates[s3WindowPrivateIndex].ptr = 0;
+ return TRUE;
+}
+
+Bool
+s3DestroyWindow (WindowPtr pWin)
+{
+ s3PatternPtr pPattern;
+ if (pPattern = s3GetWindowPrivate(pWin))
+ xfree (pPattern);
+ return fbDestroyWindow (pWin);
+}
+
+Bool
+s3ChangeWindowAttributes (WindowPtr pWin, Mask mask)
+{
+ Bool ret;
+ s3PatternPtr pPattern;
+ PixmapPtr pPixmap;
+ int fillStyle;
+
+ ret = fbChangeWindowAttributes (pWin, mask);
+ if (mask & CWBackPixmap)
+ {
+ if (pWin->backgroundState == BackgroundPixmap)
+ {
+ pPixmap = pWin->background.pixmap;
+ fillStyle = FillTiled;
+ }
+ else
+ {
+ pPixmap = 0;
+ fillStyle = FillSolid;
+ }
+ pPattern = s3GetWindowPrivate(pWin);
+ s3AllocPattern (pWin->drawable.pScreen, pPixmap,
+ pWin->drawable.x, pWin->drawable.y,
+ fillStyle, 0, 0, &pPattern);
+ DRAW_DEBUG ((DEBUG_PAINT_WINDOW, "Background pattern 0x%x pixmap 0x%x style %d",
+ pPattern, pPixmap, fillStyle));
+ s3SetWindowPrivate (pWin, pPattern);
+ }
+ return ret;
+}
+
+void
+s3PaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
+{
+ KdScreenPriv(pWin->drawable.pScreen);
+ s3PatternPtr pPattern;
+
+ DRAW_DEBUG ((DEBUG_PAINT_WINDOW, "s3PaintWindow 0x%x extents %d %d %d %d n %d",
+ pWin->drawable.id,
+ pRegion->extents.x1, pRegion->extents.y1,
+ pRegion->extents.x2, pRegion->extents.y2,
+ REGION_NUM_RECTS(pRegion)));
+ if (!REGION_NUM_RECTS(pRegion))
+ return;
+ switch (what) {
+ case PW_BACKGROUND:
+ switch (pWin->backgroundState) {
+ case None:
+ return;
+ case ParentRelative:
+ do {
+ pWin = pWin->parent;
+ } while (pWin->backgroundState == ParentRelative);
+ (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion,
+ what);
+ return;
+ case BackgroundPixmap:
+ pPattern = s3GetWindowPrivate(pWin);
+ if (pPattern)
+ {
+ s3FillBoxPattern ((DrawablePtr)pWin,
+ (int)REGION_NUM_RECTS(pRegion),
+ REGION_RECTS(pRegion),
+ GXcopy, ~0, pPattern);
+ return;
+ }
+ break;
+ case BackgroundPixel:
+ s3FillBoxSolid((DrawablePtr)pWin,
+ (int)REGION_NUM_RECTS(pRegion),
+ REGION_RECTS(pRegion),
+ pWin->background.pixel, GXcopy, ~0);
+ return;
+ }
+ break;
+ case PW_BORDER:
+ if (pWin->borderIsPixel)
+ {
+ s3FillBoxSolid((DrawablePtr)pWin,
+ (int)REGION_NUM_RECTS(pRegion),
+ REGION_RECTS(pRegion),
+ pWin->border.pixel, GXcopy, ~0);
+ return;
+ }
+ break;
+ }
+ fbPaintWindow (pWin, pRegion, what);
+}
+
+void
+s3CopyWindowProc (DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ BoxPtr pbox,
+ int nbox,
+ int dx,
+ int dy,
+ Bool reverse,
+ Bool upsidedown,
+ Pixel bitplane,
+ void *closure)
+{
+ SetupS3(pDstDrawable->pScreen);
+ int srcX, srcY, dstX, dstY;
+ int w, h;
+ int flags;
+
+ _s3SetBlt(s3,GXcopy,~0);
+ while (nbox--)
+ {
+ w = pbox->x2 - pbox->x1;
+ h = pbox->y2 - pbox->y1;
+ flags = 0;
+ if (reverse)
+ {
+ dstX = pbox->x2 - 1;
+ }
+ else
+ {
+ dstX = pbox->x1;
+ flags |= INC_X;
+ }
+ srcX = dstX + dx;
+
+ if (upsidedown)
+ {
+ dstY = pbox->y2 - 1;
+ }
+ else
+ {
+ dstY = pbox->y1;
+ flags |= INC_Y;
+ }
+ srcY = dstY + dy;
+
+ _s3Blt (s3, srcX, srcY, dstX, dstY, w, h, flags);
+ pbox++;
+ }
+ _s3WaitIdleEmpty(s3);
+}
+
+void
+s3CopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ KdScreenPriv(pScreen);
+ RegionRec rgnDst;
+ int dx, dy;
+ WindowPtr pwinRoot;
+
+ pwinRoot = WindowTable[pWin->drawable.pScreen->myNum];
+
+ dx = ptOldOrg.x - pWin->drawable.x;
+ dy = ptOldOrg.y - pWin->drawable.y;
+ REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
+
+ REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0);
+
+ REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
+
+ fbCopyRegion ((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot,
+ 0,
+ &rgnDst, dx, dy, s3CopyWindowProc, 0, 0);
+
+ REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
+}
+
+Bool
+s3DrawInit (ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ s3ScreenInfo(pScreenPriv);
+ int ncache_w, ncache_h, ncache;
+ int px, py;
+ S3PatternCache *cache;
+
+ switch (pScreenPriv->screen->bitsPerPixel) {
+ case 8:
+ case 16:
+ case 32:
+ break;
+ default:
+ return FALSE;
+ }
+ if (serverGeneration != s3Generation)
+ {
+ s3GCPrivateIndex = AllocateGCPrivateIndex ();
+ s3WindowPrivateIndex = AllocateWindowPrivateIndex ();
+ s3Generation = serverGeneration;
+ }
+ if (!AllocateWindowPrivate(pScreen, s3WindowPrivateIndex, 0))
+ return FALSE;
+ if (!AllocateGCPrivate(pScreen, s3GCPrivateIndex, sizeof (s3PrivGCRec)))
+ return FALSE;
+ /*
+ * Replace various fb screen functions
+ */
+ pScreen->CreateGC = s3CreateGC;
+ pScreen->CreateWindow = s3CreateWindow;
+ pScreen->ChangeWindowAttributes = s3ChangeWindowAttributes;
+ pScreen->DestroyWindow = s3DestroyWindow;
+ pScreen->PaintWindowBackground = s3PaintWindow;
+ pScreen->PaintWindowBorder = s3PaintWindow;
+ pScreen->CopyWindow = s3CopyWindow;
+
+ /*
+ * Initialize patterns
+ */
+ ncache_w = s3s->offscreen_width / S3_TILE_SIZE;
+ ncache_h = s3s->offscreen_height / S3_TILE_SIZE;
+ ncache = ncache_w * ncache_h;
+ DRAW_DEBUG ((DEBUG_S3INIT, "ncache_w %d ncache_h %d ncache %d",
+ ncache_w, ncache_h, ncache));
+ s3s->patterns.cache = (S3PatternCache *) xalloc (ncache * sizeof (S3PatternCache));
+ if (s3s->patterns.cache)
+ {
+ DRAW_DEBUG ((DEBUG_S3INIT, "Have pattern cache"));
+ s3s->patterns.ncache = ncache;
+ s3s->patterns.last_used = 0;
+ s3s->patterns.last_id = 0;
+ cache = s3s->patterns.cache;
+ for (py = 0; py < ncache_h; py++)
+ for (px = 0; px < ncache_w; px++)
+ {
+ cache->id = 0;
+ cache->x = s3s->offscreen_x + px * S3_TILE_SIZE;
+ cache->y = s3s->offscreen_y + py * S3_TILE_SIZE;
+ cache++;
+ }
+ }
+ return TRUE;
+}
+
+void
+s3DrawEnable (ScreenPtr pScreen)
+{
+ SetupS3(pScreen);
+ s3ScreenInfo(pScreenPriv);
+ int c;
+
+ /*
+ * Flush pattern cache
+ */
+ for (c = 0; c < s3s->patterns.ncache; c++)
+ s3s->patterns.cache[c].id = 0;
+
+ _s3WaitIdleEmpty(s3);
+ _s3SetScissorsTl(s3, 0, 0);
+ _s3SetScissorsBr(s3, pScreenPriv->screen->width - 1, pScreenPriv->screen->height - 1);
+ _s3SetSolidFill(s3, pScreen->blackPixel, GXcopy, ~0);
+ _s3SolidRect (s3, 0, 0, pScreenPriv->screen->width, pScreenPriv->screen->height);
+ _s3WaitIdleEmpty (s3);
+}
+
+void
+s3DrawDisable (ScreenPtr pScreen)
+{
+}
+
+void
+s3DrawFini (ScreenPtr pScreen)
+{
+ SetupS3(pScreen);
+ s3ScreenInfo(pScreenPriv);
+
+ if (s3s->patterns.cache)
+ {
+ xfree (s3s->patterns.cache);
+ s3s->patterns.cache = 0;
+ s3s->patterns.ncache = 0;
+ }
+}
diff --git a/hw/kdrive/savage/s3draw.h b/hw/kdrive/savage/s3draw.h
new file mode 100644
index 000000000..14dd1688e
--- /dev/null
+++ b/hw/kdrive/savage/s3draw.h
@@ -0,0 +1,372 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999 SuSE, Inc.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+/* $XFree86: $ */
+
+#ifndef _S3DRAW_H_
+#define _S3DRAW_H_
+
+extern int s3GCPrivateIndex;
+extern int s3WindowPrivateIndex;
+
+typedef struct _s3Pattern {
+ S3PatternCache *cache;
+ int id;
+ PixmapPtr pPixmap;
+ int fillStyle;
+ int xrot, yrot;
+ unsigned int fore, back;
+} s3PatternRec, *s3PatternPtr;
+
+typedef struct _s3PrivGC {
+ int type; /* type of drawable validated against */
+ s3PatternPtr pPattern; /* pattern */
+} s3PrivGCRec, *s3PrivGCPtr;
+
+#define s3GetGCPrivate(g) ((s3PrivGCPtr) \
+ (g)->devPrivates[s3GCPrivateIndex].ptr)
+
+#define s3GCPrivate(g) s3PrivGCPtr s3Priv = s3GetGCPrivate(g)
+
+#define s3GetWindowPrivate(w) ((s3PatternPtr) \
+ (w)->devPrivates[s3WindowPrivateIndex].ptr)
+
+#define s3SetWindowPrivate(w,p) (\
+ (w)->devPrivates[s3WindowPrivateIndex].ptr = (pointer) p)
+
+
+void _s3LoadPattern (ScreenPtr pScreen, s3PatternPtr pPattern);
+
+#define SetupS3(s) KdScreenPriv(s); \
+ s3CardInfo(pScreenPriv); \
+ S3Ptr s3 = s3c->s3
+
+#define WIDEN(x) ((unsigned long) (x))
+#define MERGE(a,b) ((WIDEN(a) << 16) | WIDEN(b))
+
+#define _s3SetFg(s3,_fg) { \
+ DRAW_DEBUG ((DEBUG_REGISTERS, " fg <- 0x%x", _fg));\
+ s3->fg = (_fg); \
+}
+
+#define _s3SetBg(s3,_bg) { \
+ DRAW_DEBUG ((DEBUG_REGISTERS, " bg <- 0x%x", _bg));\
+ s3->bg = (_bg); \
+}
+
+#define _s3SetWriteMask(s3,_mask) {\
+ DRAW_DEBUG((DEBUG_REGISTERS," write_mask <- 0x%x", _mask)); \
+ s3->write_mask = (_mask); \
+}
+
+#define _s3SetReadMask(s3,_mask) {\
+ DRAW_DEBUG((DEBUG_REGISTERS," read_mask <- 0x%x", _mask)); \
+ s3->read_mask = (_mask); \
+}
+
+#define _s3SetPixelControl(s3,_ctl) { \
+ DRAW_DEBUG((DEBUG_REGISTERS, " pix_cntl <- 0x%x", PIX_CNTL | (_ctl))); \
+ s3->pix_cntl = PIX_CNTL | (_ctl); \
+}
+
+#define _s3SetFgMix(s3,_mix) { \
+ DRAW_DEBUG((DEBUG_REGISTERS, " fg_mix <- 0x%x", _mix)); \
+ s3->enh_fg_mix = (_mix); \
+}
+
+#define _s3SetBgMix(s3,_mix) { \
+ DRAW_DEBUG((DEBUG_REGISTERS, " bg_mix <- 0x%x", _mix)); \
+ s3->enh_bg_mix = (_mix); \
+}
+
+#define _s3SetMix(s3,fg_mix,bg_mix) { \
+ DRAW_DEBUG((DEBUG_REGISTERS, " alt_mix <- 0x%x", MERGE(fg_mix,bg_mix))); \
+ s3->alt_mix = MERGE(fg_mix,bg_mix); \
+}
+
+#define _s3SetCur(s3,_x,_y) { \
+ DRAW_DEBUG ((DEBUG_REGISTERS, " alt_curxy <- 0x%x", MERGE(_x,_y))); \
+ s3->alt_curxy = MERGE(_x,_y); \
+}
+
+#define _s3SetStep(s3,_x,_y) { \
+ DRAW_DEBUG ((DEBUG_REGISTERS, " alt_step <- 0x%x", MERGE(_x,_y))); \
+ s3->alt_step = MERGE(_x,_y); \
+}
+
+#define _s3SetErr(s3,_e) { \
+ DRAW_DEBUG ((DEBUG_REGISTERS, " err_term <- 0x%x", _e)); \
+ s3->err_term = (_e); \
+}
+
+#define _s3SetPcnt(s3,_x,_y) { \
+ DRAW_DEBUG ((DEBUG_REGISTERS, " alt_pcnt <- 0x%x", MERGE(_x,_y))); \
+ s3->alt_pcnt = MERGE(_x,_y); \
+}
+
+#define _s3SetScissorsTl(s3,t,l) {\
+ DRAW_DEBUG ((DEBUG_REGISTERS, " scissors_tl <- 0x%x", MERGE(t,l))); \
+ s3->scissors_tl = MERGE(t,l); \
+}
+
+#define _s3SetScissorsBr(s3,b,r) {\
+ DRAW_DEBUG ((DEBUG_REGISTERS, " scissors_br <- 0x%x", MERGE(b,r))); \
+ s3->scissors_br = MERGE(b,r); \
+}
+
+#define _s3CmdWait(s3)
+
+#define _s3SetCmd(s3,_cmd) { \
+ DRAW_DEBUG((DEBUG_REGISTERS, " cmd <- 0x%x", _cmd)); \
+ _s3CmdWait(s3); \
+ s3->cmd_gp_stat = (_cmd); \
+ { CARD32 __junk__; __junk__ = s3->cmd_gp_stat; } \
+}
+
+#define _s3SetSolidFill(s3,pix,alu,mask) { \
+ DRAW_DEBUG((DEBUG_SET,"set fill 0x%x %d 0x%x",pix,alu,mask)); \
+ _s3SetFg (s3, pix); \
+ _s3SetWriteMask(s3,mask); \
+ _s3SetMix (s3, FSS_FRGDCOL | s3alu[alu], BSS_BKGDCOL | MIX_SRC); \
+ _s3SetPixelControl (s3, MIXSEL_FRGDMIX); \
+ DRAW_DEBUG((DEBUG_SET," done")); \
+}
+
+#define _s3SolidRect(s3,x,y,w,h) {\
+ DRAW_DEBUG((DEBUG_RENDER,"solid rect %d,%d %dx%d",x,y,w,h)); \
+ _s3CmdWait(s3); \
+ _s3SetCur(s3, x, y); \
+ _s3SetPcnt (s3, (w)-1, (h)-1); \
+ _s3SetCmd (s3, CMD_RECT|INC_X|INC_Y|DRAW|WRTDATA); \
+ DRAW_DEBUG((DEBUG_RENDER," done")); \
+}
+
+#define _s3SolidLine(s3,maj,min,len,cmd) { \
+ DRAW_DEBUG ((DEBUG_RENDER, "solid line 0x%x 0x%x 0x%x", maj, min, cmd)); \
+ _s3CmdWait(s3); \
+ _s3SetPcnt(s3, (len), 0); \
+ _s3SetStep(s3, 2*((min) - (maj)), 2*(min)); \
+ _s3SetErr(s3, 2*(min) - (maj)); \
+ _s3SetCmd (s3, CMD_LINE | (cmd) | DRAW | WRTDATA); \
+}
+
+#define _s3SetTile(s3,alu,mask) { \
+ DRAW_DEBUG ((DEBUG_SET,"set tile %d 0x%x", alu, mask)); \
+ _s3SetWriteMask(s3, mask); \
+ _s3SetMix(s3, FSS_BITBLT | s3alu[alu], BSS_BITBLT|s3alu[alu]); \
+ _s3SetPixelControl (s3, MIXSEL_FRGDMIX); \
+ DRAW_DEBUG((DEBUG_SET," done")); \
+}
+
+/*
+ * For some reason, MIX_DST doesn't work in this mode; use MIX_OR with
+ * an explicit 0 pixel value
+ */
+#define _s3SetStipple(s3,alu,mask,_fg) {\
+ DRAW_DEBUG ((DEBUG_SET,"set stipple 0x%x %d 0x%x", _fg, alu, mask)); \
+ _s3SetFg (s3, _fg); \
+ _s3SetBg (s3, 0); \
+ _s3SetWriteMask(s3,mask); \
+ _s3SetMix (s3, FSS_FRGDCOL | s3alu[alu], BSS_BKGDCOL|MIX_OR); \
+ _s3SetPixelControl (s3, MIXSEL_EXPBLT); \
+ DRAW_DEBUG((DEBUG_SET," done")); \
+}
+
+#define _s3SetOpaqueStipple(s3,alu,mask,_fg,_bg) {\
+ DRAW_DEBUG ((DEBUG_SET,"set opaque stipple 0x%x 0x%x %d 0x%x", _fg, _bg, alu, mask)); \
+ _s3SetFg (s3, _fg); \
+ _s3SetBg (s3, _bg); \
+ _s3SetWriteMask(s3,mask); \
+ _s3SetMix (s3, FSS_FRGDCOL | s3alu[alu], BSS_BKGDCOL|s3alu[alu]); \
+ _s3SetPixelControl (s3, MIXSEL_EXPBLT); \
+ DRAW_DEBUG((DEBUG_SET," done")); \
+}
+
+#define _s3PatRect(s3,px,py,x,y,w,h) {\
+ DRAW_DEBUG ((DEBUG_RENDER, "pat rect %d,%d %dx%d", x,y,w,h)); \
+ _s3CmdWait(s3); \
+ _s3SetCur (s3, px, py); \
+ _s3SetStep (s3, x, y); \
+ _s3SetPcnt (s3, (w)-1, (h)-1); \
+ _s3SetCmd (s3, CMD_PATBLT|INC_X|INC_Y|DRAW|PLANAR|WRTDATA); \
+ DRAW_DEBUG((DEBUG_RENDER," done")); \
+}
+
+#define _s3SetBlt(s3,alu,mask) { \
+ DRAW_DEBUG ((DEBUG_SET,"set blt %d 0x%x", alu, mask)); \
+ _s3SetPixelControl (s3, MIXSEL_FRGDMIX); \
+ _s3SetMix(s3, FSS_BITBLT | s3alu[alu], BSS_BITBLT | s3alu[alu]); \
+ _s3SetWriteMask(s3, mask); \
+ DRAW_DEBUG((DEBUG_SET," done")); \
+}
+
+#define _s3Blt(s3,_sx,_sy,_dx,_dy,_w,_h,_dir) { \
+ DRAW_DEBUG ((DEBUG_RENDER, "blt %d,%d -> %d,%d %dx%d 0x%x", \
+ _sx,_sy,_dx,_dy,_w,_h,_dir)); \
+ _s3CmdWait(s3); \
+ _s3SetCur(s3,_sx,_sy); \
+ _s3SetStep(s3,_dx,_dy); \
+ _s3SetPcnt(s3,(_w)-1,(_h)-1); \
+ _s3SetCmd (s3, CMD_BITBLT | (_dir) | DRAW | WRTDATA); \
+ DRAW_DEBUG((DEBUG_RENDER," done")); \
+}
+
+#define _s3SetOpaquePlaneBlt(s3,alu,mask,_fg,_bg) {\
+ DRAW_DEBUG ((DEBUG_SET,"set opaque plane blt 0x%x 0x%x %d 0x%x", \
+ _fg, _bg, alu, mask)); \
+ _s3SetFg(s3,_fg); \
+ _s3SetBg(s3,_bg); \
+ _s3SetWriteMask(s3,mask); \
+ _s3SetMix(s3,FSS_FRGDCOL|s3alu[alu], BSS_BKGDCOL|s3alu[alu]); \
+ _s3SetPixelControl(s3,MIXSEL_EXPPC); \
+ DRAW_DEBUG((DEBUG_SET," done")); \
+}
+
+#define _s3SetTransparentPlaneBlt(s3,alu,mask,_fg) {\
+ DRAW_DEBUG ((DEBUG_SET,"set transparent plane blt 0x%x %d 0x%x", \
+ _fg, alu, mask)); \
+ _s3SetFg(s3,_fg); \
+ _s3SetWriteMask(s3,mask); \
+ _s3SetMix(s3,FSS_FRGDCOL|s3alu[alu], BSS_BKGDCOL|MIX_DST); \
+ _s3SetPixelControl(s3,MIXSEL_EXPPC); \
+ DRAW_DEBUG((DEBUG_SET," done")); \
+}
+
+/* Across the plane blt */
+#define _s3PlaneBlt(s3,x,y,w,h) {\
+ DRAW_DEBUG ((DEBUG_RENDER, "plane blt %d,%d %dx%d", x,y,w,h)); \
+ _s3CmdWait(s3); \
+ _s3SetCur(s3, x, y); \
+ _s3SetPcnt (s3, (w)-1, (h)-1); \
+ _s3SetCmd (s3, \
+ CMD_RECT| /* Fill rectangle */ \
+ BYTSEQ| /* LSB byte order */ \
+ _32BIT| /* 32 bit data on 32 bit boundaries */ \
+ PCDATA| /* Data from CPU */ \
+ INC_X|INC_Y| /* X and Y both increasing */ \
+ DRAW| /* Draw, not move */ \
+ PLANAR| /* multi pixel */ \
+ WRTDATA); \
+ DRAW_DEBUG((DEBUG_RENDER," done")); \
+}
+
+#define _s3SetClip(s3,pbox) {\
+ DRAW_DEBUG ((DEBUG_SET, "set clip %dx%d -> %dx%d ", \
+ pbox->x1, pbox->y1, pbox->x2, pbox->y2)); \
+ _s3WaitEmpty(s3); \
+ _s3SetScissorsTl(s3,(pbox)->x1, (pbox)->y1); \
+ _s3SetScissorsBr(s3,(pbox)->x2 - 1, (pbox)->y2 - 1); \
+ DRAW_DEBUG((DEBUG_SET," done")); \
+}
+
+#define _s3ResetClip(s3,pScreen) { \
+ DRAW_DEBUG ((DEBUG_SET, "reset clip")); \
+ _s3WaitEmpty(s3); \
+ _s3SetScissorsTl(s3,0,0); \
+ _s3SetScissorsBr(s3,pScreen->width - 1, pScreen->height - 1); \
+ DRAW_DEBUG((DEBUG_SET," done")); \
+}
+
+RegionPtr
+s3CopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
+ int srcx, int srcy, int width, int height, int dstx, int dsty);
+
+RegionPtr
+s3CopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
+ int srcx, int srcy, int width, int height,
+ int dstx, int dsty, unsigned long bitPlane);
+
+void
+s3FillBoxSolid (DrawablePtr pDrawable, int nBox, BoxPtr pBox,
+ unsigned long pixel, int alu, unsigned long planemask);
+
+void
+s3FillBoxPattern (DrawablePtr pDrawable, int nBox, BoxPtr pBox,
+ int alu, unsigned long planemask, s3PatternPtr pPattern);
+
+void
+s3PolyFillRect (DrawablePtr pDrawable, GCPtr pGC,
+ int nrectFill, xRectangle *prectInit);
+
+void
+s3FillSpans (DrawablePtr pDrawable, GCPtr pGC, int n,
+ DDXPointPtr ppt, int *pwidth, int fSorted);
+
+void
+s3PolyFillArcSolid (DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs);
+
+void
+s3FillPoly1Rect (DrawablePtr pDrawable, GCPtr pGC, int shape,
+ int mode, int count, DDXPointPtr ptsIn);
+
+void
+s3PolyGlyphBlt (DrawablePtr pDrawable,
+ GCPtr pGC,
+ int xInit, int y,
+ unsigned int nglyphInit,
+ CharInfoPtr *ppciInit,
+ pointer pglyphBase);
+
+void
+s3ImageGlyphBlt (DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x, int y,
+ unsigned int nglyph,
+ CharInfoPtr *ppci,
+ pointer pglyphBase);
+
+void
+s3ImageTEGlyphBlt (DrawablePtr pDrawable, GCPtr pGC,
+ int xInit, int y,
+ unsigned int nglyphInit,
+ CharInfoPtr *ppciInit,
+ pointer pglyphBase);
+
+void
+s3PolyTEGlyphBlt (DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y,
+ unsigned int nglyph, CharInfoPtr *ppci,
+ pointer pglyphBase);
+
+void
+s3Polylines (DrawablePtr pDrawable, GCPtr pGC,
+ int mode, int nptInit, DDXPointPtr pptInit);
+
+void
+s3PolySegment (DrawablePtr pDrawable, GCPtr pGC,
+ int nsegInit, xSegment *pSegInit);
+
+void
+s3FillBoxSolid (DrawablePtr pDrawable, int nBox, BoxPtr pBox,
+ unsigned long pixel, int alu, unsigned long planemask);
+
+void s3ValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable);
+
+void
+s3CheckGCFill (GCPtr pGC);
+
+void
+s3MoveGCFill (GCPtr pGC);
+
+#endif
diff --git a/hw/kdrive/savage/s3gc.c b/hw/kdrive/savage/s3gc.c
new file mode 100644
index 000000000..245dfc483
--- /dev/null
+++ b/hw/kdrive/savage/s3gc.c
@@ -0,0 +1,388 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999 SuSE, Inc.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+/* $XFree86: $ */
+
+#include "s3.h"
+#include "s3draw.h"
+
+#include "Xmd.h"
+#include "gcstruct.h"
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "regionstr.h"
+#include "mistruct.h"
+#include "fontstruct.h"
+#include "dixfontstr.h"
+#include "migc.h"
+
+/*
+ * Common op groups. Common assumptions:
+ *
+ * lineWidth 0
+ * lineStyle LineSolid
+ * fillStyle FillSolid
+ * rop GXcopy
+ * font <= 32 pixels wide
+ */
+
+/* TE font, >= 4 pixels wide, one clip rectangle */
+static GCOps s3TEOps1Rect = {
+ s3FillSpans,
+ fbSetSpans,
+ fbPutImage,
+ s3CopyArea,
+ s3CopyPlane,
+ fbPolyPoint,
+ s3Polylines,
+ s3PolySegment,
+ miPolyRectangle,
+ fbPolyArc,
+ s3FillPoly1Rect,
+ s3PolyFillRect,
+ s3PolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ s3ImageTEGlyphBlt,
+ s3PolyTEGlyphBlt,
+ fbPushPixels,
+#ifdef NEED_LINEHELPER
+ ,NULL
+#endif
+};
+
+extern GCOps fbGCOps;
+
+/* Non TE font, one clip rectangle */
+static GCOps s3NonTEOps1Rect = {
+ s3FillSpans,
+ fbSetSpans,
+ fbPutImage,
+ s3CopyArea,
+ s3CopyPlane,
+ fbPolyPoint,
+ s3Polylines,
+ s3PolySegment,
+ miPolyRectangle,
+ fbPolyArc,
+ s3FillPoly1Rect,
+ s3PolyFillRect,
+ s3PolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ s3ImageGlyphBlt,
+ s3PolyGlyphBlt,
+ fbPushPixels
+#ifdef NEED_LINEHELPER
+ ,NULL
+#endif
+};
+
+/* TE font, != 1 clip rect (including 0) */
+static GCOps s3TEOps = {
+ s3FillSpans,
+ fbSetSpans,
+ fbPutImage,
+ s3CopyArea,
+ s3CopyPlane,
+ fbPolyPoint,
+ s3Polylines,
+ s3PolySegment,
+ miPolyRectangle,
+ fbPolyArc,
+ miFillPolygon,
+ s3PolyFillRect,
+ s3PolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ s3ImageTEGlyphBlt,
+ s3PolyTEGlyphBlt,
+ fbPushPixels
+#ifdef NEED_LINEHELPER
+ ,NULL
+#endif
+};
+
+/* Non TE font, != 1 clip rect (including 0) */
+static GCOps s3NonTEOps = {
+ s3FillSpans,
+ fbSetSpans,
+ fbPutImage,
+ s3CopyArea,
+ s3CopyPlane,
+ fbPolyPoint,
+ s3Polylines,
+ s3PolySegment,
+ miPolyRectangle,
+ fbPolyArc,
+ miFillPolygon,
+ s3PolyFillRect,
+ s3PolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ s3ImageGlyphBlt,
+ s3PolyGlyphBlt,
+ fbPushPixels
+#ifdef NEED_LINEHELPER
+ ,NULL
+#endif
+};
+
+static GCOps *
+s3MatchCommon (DrawablePtr pDraw, GCPtr pGC, FbGCPrivPtr fbPriv)
+{
+ KdScreenPriv (pDraw->pScreen);
+
+ if (!REGION_NOTEMPTY(pDraw->pScreen,fbGetCompositeClip(pGC)))
+ {
+ DRAW_DEBUG ((DEBUG_CLIP, "Empty composite clip, clipping all ops"));
+ return &kdNoopOps;
+ }
+
+ if (pDraw->type != DRAWABLE_WINDOW)
+ return (GCOps *) &fbGCOps;
+
+ if (pGC->lineWidth != 0)
+ return 0;
+ if (pGC->lineStyle != LineSolid)
+ return 0;
+ if (pGC->fillStyle != FillSolid)
+ return 0;
+ if (fbPriv->and != 0)
+ return 0;
+ if (pGC->font)
+ {
+ if (TERMINALFONT(pGC->font))
+ {
+ if (fbPriv->oneRect)
+ return &s3TEOps1Rect;
+ else
+ return &s3TEOps;
+ }
+ else
+ {
+ if (fbPriv->oneRect)
+ return &s3NonTEOps1Rect;
+ else
+ return &s3NonTEOps;
+ }
+ }
+ return 0;
+}
+
+void
+s3ValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable)
+{
+ int new_type; /* drawable type has changed */
+ int new_onerect; /* onerect value has changed */
+ int new_origin;
+
+ /* flags for changing the proc vector */
+ FbGCPrivPtr fbPriv;
+ s3PrivGCPtr s3Priv;
+ int oneRect;
+
+ fbPriv = fbGetGCPrivate(pGC);
+ s3Priv = s3GetGCPrivate(pGC);
+
+ new_type = FALSE;
+ new_onerect = FALSE;
+ new_origin = FALSE;
+
+ /*
+ * If the type of drawable has changed, fix up accelerated functions
+ */
+ if (s3Priv->type != pDrawable->type)
+ {
+ new_type = TRUE;
+ s3Priv->type = pDrawable->type;
+ }
+
+ /*
+ * Check tile/stipple origin
+ */
+ if (pGC->lastWinOrg.x != pDrawable->x || pGC->lastWinOrg.y != pDrawable->y)
+ new_origin = TRUE;
+
+ /*
+ * Call down to FB to set clip list and rrop values
+ */
+ oneRect = fbPriv->oneRect;
+
+ fbValidateGC (pGC, changes, pDrawable);
+
+ if (oneRect != fbPriv->oneRect)
+ new_onerect = TRUE;
+
+ /*
+ * Check accelerated pattern if necessary
+ */
+ if (changes & (GCFillStyle|GCStipple|GCTile))
+ s3CheckGCFill (pGC);
+ else if (s3Priv->pPattern &&
+ (new_origin || changes & (GCTileStipXOrigin|GCTileStipYOrigin)))
+ s3MoveGCFill (pGC);
+
+ /*
+ * Try to match common vector
+ */
+
+ if (new_type || new_onerect ||
+ (changes & (GCLineWidth|GCLineStyle|GCFillStyle|
+ GCFont|GCForeground|GCFunction|GCPlaneMask)))
+ {
+ GCOps *newops;
+
+ if (newops = s3MatchCommon (pDrawable, pGC, fbPriv))
+ {
+ if (pGC->ops->devPrivate.val)
+ miDestroyGCOps (pGC->ops);
+ pGC->ops = newops;
+ return;
+ }
+ }
+
+ /*
+ * No common vector matched, create private ops vector and
+ * fill it in
+ */
+ if (!pGC->ops->devPrivate.val)
+ {
+ /*
+ * Switch from noop vector by first switching to fb
+ * vector and fixing it up
+ */
+ if (pGC->ops == &kdNoopOps)
+ {
+ pGC->ops = (GCOps *) &fbGCOps;
+ new_type = TRUE;
+ }
+ pGC->ops = miCreateGCOps (pGC->ops);
+ pGC->ops->devPrivate.val = 1;
+ }
+
+ /*
+ * Fills
+ */
+ if (new_type || (changes & (GCFillStyle|GCTile|GCStipple)))
+ {
+ pGC->ops->FillSpans = fbFillSpans;
+ pGC->ops->PolyFillRect = fbPolyFillRect;
+ if (s3Priv->type == DRAWABLE_WINDOW &&
+ (pGC->fillStyle != FillTiled || s3Priv->pPattern))
+ {
+ pGC->ops->FillSpans = s3FillSpans;
+ pGC->ops->PolyFillRect = s3PolyFillRect;
+ }
+ }
+
+ /*
+ * Blt
+ */
+ if (new_type)
+ {
+ pGC->ops->CopyArea = fbCopyArea;
+ pGC->ops->CopyPlane = fbCopyPlane;
+ if (s3Priv->type == DRAWABLE_WINDOW)
+ {
+ pGC->ops->CopyArea = s3CopyArea;
+ pGC->ops->CopyPlane = s3CopyPlane;
+ }
+ }
+
+ /*
+ * Lines
+ */
+ if (new_type || (changes & (GCLineStyle|GCLineWidth|GCFillStyle)))
+ {
+ pGC->ops->Polylines = fbPolyLine;
+ pGC->ops->PolySegment = fbPolySegment;
+ if (pGC->lineStyle == LineSolid &&
+ pGC->lineWidth == 0 &&
+ pGC->fillStyle == FillSolid &&
+ s3Priv->type == DRAWABLE_WINDOW)
+ {
+ pGC->ops->Polylines = s3Polylines;
+ pGC->ops->PolySegment = s3PolySegment;
+ }
+ }
+
+ /*
+ * Polygons
+ */
+ if (new_type || new_onerect || (changes & (GCFillStyle)))
+ {
+ pGC->ops->FillPolygon = miFillPolygon;
+ if (s3Priv->type == DRAWABLE_WINDOW &&
+ fbPriv->oneRect &&
+ pGC->fillStyle == FillSolid)
+ {
+ pGC->ops->FillPolygon = s3FillPoly1Rect;
+ }
+ }
+
+ /*
+ * Filled arcs
+ */
+ if (new_type || (changes & GCFillStyle))
+ {
+ pGC->ops->PolyFillArc = fbPolyFillArc;
+ if (s3Priv->type == DRAWABLE_WINDOW &&
+ pGC->fillStyle == FillSolid)
+ {
+ pGC->ops->PolyFillArc = s3PolyFillArcSolid;
+ }
+ }
+
+ /*
+ * Text
+ */
+ if (new_type || (changes & (GCFont|GCFillStyle)))
+ {
+ pGC->ops->PolyGlyphBlt = fbPolyGlyphBlt;
+ pGC->ops->ImageGlyphBlt = fbImageGlyphBlt;
+ if (s3Priv->type == DRAWABLE_WINDOW && pGC->font)
+ {
+ if (pGC->fillStyle == FillSolid)
+ {
+ if (TERMINALFONT(pGC->font))
+ pGC->ops->PolyGlyphBlt = s3PolyTEGlyphBlt;
+ else
+ pGC->ops->PolyGlyphBlt = s3PolyGlyphBlt;
+ }
+ if (TERMINALFONT(pGC->font))
+ pGC->ops->ImageGlyphBlt = s3ImageTEGlyphBlt;
+ else
+ pGC->ops->ImageGlyphBlt = s3ImageGlyphBlt;
+ }
+ }
+}
diff --git a/hw/kdrive/savage/s3reg.c b/hw/kdrive/savage/s3reg.c
new file mode 100644
index 000000000..38ca2e804
--- /dev/null
+++ b/hw/kdrive/savage/s3reg.c
@@ -0,0 +1,1144 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999 SuSE, Inc.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+/* $XFree86: $ */
+
+#include "s3reg.h"
+
+#define CR00 S3_CR+0x00
+#define CR01 S3_CR+0x01
+#define CR02 S3_CR+0x02
+#define CR03 S3_CR+0x03
+#define CR04 S3_CR+0x04
+#define CR05 S3_CR+0x05
+#define CR06 S3_CR+0x06
+#define CR07 S3_CR+0x07
+#define CR08 S3_CR+0x08
+#define CR09 S3_CR+0x09
+#define CR0A S3_CR+0x0A
+#define CR0B S3_CR+0x0B
+#define CR0C S3_CR+0x0C
+#define CR0D S3_CR+0x0D
+#define CR0E S3_CR+0x0E
+#define CR0F S3_CR+0x0F
+#define CR10 S3_CR+0x10
+#define CR11 S3_CR+0x11
+#define CR12 S3_CR+0x12
+#define CR13 S3_CR+0x13
+#define CR14 S3_CR+0x14
+#define CR15 S3_CR+0x15
+#define CR16 S3_CR+0x16
+#define CR17 S3_CR+0x17
+#define CR18 S3_CR+0x18
+#define CR19 S3_CR+0x19
+#define CR1A S3_CR+0x1A
+#define CR1B S3_CR+0x1B
+#define CR1C S3_CR+0x1C
+#define CR1D S3_CR+0x1D
+#define CR1E S3_CR+0x1E
+#define CR1F S3_CR+0x1F
+#define CR20 S3_CR+0x20
+#define CR21 S3_CR+0x21
+#define CR22 S3_CR+0x22
+#define CR23 S3_CR+0x23
+#define CR24 S3_CR+0x24
+#define CR25 S3_CR+0x25
+#define CR26 S3_CR+0x26
+#define CR27 S3_CR+0x27
+#define CR28 S3_CR+0x28
+#define CR29 S3_CR+0x29
+#define CR2A S3_CR+0x2A
+#define CR2B S3_CR+0x2B
+#define CR2C S3_CR+0x2C
+#define CR2D S3_CR+0x2D
+#define CR2E S3_CR+0x2E
+#define CR2F S3_CR+0x2F
+#define CR30 S3_CR+0x30
+#define CR31 S3_CR+0x31
+#define CR32 S3_CR+0x32
+#define CR33 S3_CR+0x33
+#define CR34 S3_CR+0x34
+#define CR35 S3_CR+0x35
+#define CR36 S3_CR+0x36
+#define CR37 S3_CR+0x37
+#define CR38 S3_CR+0x38
+#define CR39 S3_CR+0x39
+#define CR3A S3_CR+0x3A
+#define CR3B S3_CR+0x3B
+#define CR3C S3_CR+0x3C
+#define CR3D S3_CR+0x3D
+#define CR3E S3_CR+0x3E
+#define CR3F S3_CR+0x3F
+#define CR40 S3_CR+0x40
+#define CR41 S3_CR+0x41
+#define CR42 S3_CR+0x42
+#define CR43 S3_CR+0x43
+#define CR44 S3_CR+0x44
+#define CR45 S3_CR+0x45
+#define CR46 S3_CR+0x46
+#define CR47 S3_CR+0x47
+#define CR48 S3_CR+0x48
+#define CR49 S3_CR+0x49
+#define CR4A S3_CR+0x4A
+#define CR4B S3_CR+0x4B
+#define CR4C S3_CR+0x4C
+#define CR4D S3_CR+0x4D
+#define CR4E S3_CR+0x4E
+#define CR4F S3_CR+0x4F
+#define CR50 S3_CR+0x50
+#define CR51 S3_CR+0x51
+#define CR52 S3_CR+0x52
+#define CR53 S3_CR+0x53
+#define CR54 S3_CR+0x54
+#define CR55 S3_CR+0x55
+#define CR56 S3_CR+0x56
+#define CR57 S3_CR+0x57
+#define CR58 S3_CR+0x58
+#define CR59 S3_CR+0x59
+#define CR5A S3_CR+0x5A
+#define CR5B S3_CR+0x5B
+#define CR5C S3_CR+0x5C
+#define CR5D S3_CR+0x5D
+#define CR5E S3_CR+0x5E
+#define CR5F S3_CR+0x5F
+#define CR60 S3_CR+0x60
+#define CR61 S3_CR+0x61
+#define CR62 S3_CR+0x62
+#define CR63 S3_CR+0x63
+#define CR64 S3_CR+0x64
+#define CR65 S3_CR+0x65
+#define CR66 S3_CR+0x66
+#define CR67 S3_CR+0x67
+#define CR68 S3_CR+0x68
+#define CR69 S3_CR+0x69
+#define CR6A S3_CR+0x6A
+#define CR6B S3_CR+0x6B
+#define CR6C S3_CR+0x6C
+#define CR6D S3_CR+0x6D
+#define CR6E S3_CR+0x6E
+#define CR6F S3_CR+0x6F
+#define CR70 S3_CR+0x70
+#define CR71 S3_CR+0x71
+#define CR72 S3_CR+0x72
+#define CR73 S3_CR+0x73
+#define CR74 S3_CR+0x74
+#define CR75 S3_CR+0x75
+#define CR76 S3_CR+0x76
+#define CR77 S3_CR+0x77
+#define CR78 S3_CR+0x78
+#define CR79 S3_CR+0x79
+#define CR7A S3_CR+0x7A
+#define CR7B S3_CR+0x7B
+#define CR7C S3_CR+0x7C
+#define CR7D S3_CR+0x7D
+#define CR7E S3_CR+0x7E
+#define CR7F S3_CR+0x7F
+#define CR80 S3_CR+0x80
+#define CR81 S3_CR+0x81
+#define CR82 S3_CR+0x82
+#define CR83 S3_CR+0x83
+#define CR84 S3_CR+0x84
+#define CR85 S3_CR+0x85
+#define CR86 S3_CR+0x86
+#define CR87 S3_CR+0x87
+#define CR88 S3_CR+0x88
+#define CR89 S3_CR+0x89
+#define CR8A S3_CR+0x8A
+#define CR8B S3_CR+0x8B
+#define CR8C S3_CR+0x8C
+#define CR8D S3_CR+0x8D
+#define CR8E S3_CR+0x8E
+#define CR8F S3_CR+0x8F
+#define CR90 S3_CR+0x90
+#define CR91 S3_CR+0x91
+#define CR92 S3_CR+0x92
+#define CR93 S3_CR+0x93
+#define CR94 S3_CR+0x94
+#define CR95 S3_CR+0x95
+#define CR96 S3_CR+0x96
+#define CR97 S3_CR+0x97
+#define CR98 S3_CR+0x98
+#define CR99 S3_CR+0x99
+#define CR9A S3_CR+0x9A
+#define CR9B S3_CR+0x9B
+#define CR9C S3_CR+0x9C
+#define CR9D S3_CR+0x9D
+#define CR9E S3_CR+0x9E
+#define CR9F S3_CR+0x9F
+#define CRA0 S3_CR+0xA0
+#define CRA1 S3_CR+0xA1
+#define CRA2 S3_CR+0xA2
+#define CRA3 S3_CR+0xA3
+#define CRA4 S3_CR+0xA4
+#define CRA5 S3_CR+0xA5
+#define CRA6 S3_CR+0xA6
+#define CRA7 S3_CR+0xA7
+#define CRA8 S3_CR+0xA8
+#define CRA9 S3_CR+0xA9
+#define CRAA S3_CR+0xAA
+#define CRAB S3_CR+0xAB
+#define CRAC S3_CR+0xAC
+#define CRAD S3_CR+0xAD
+#define CRAE S3_CR+0xAE
+#define CRAF S3_CR+0xAF
+#define CRB0 S3_CR+0xB0
+#define CRB1 S3_CR+0xB1
+#define CRB2 S3_CR+0xB2
+#define CRB3 S3_CR+0xB3
+#define CRB4 S3_CR+0xB4
+#define CRB5 S3_CR+0xB5
+#define CRB6 S3_CR+0xB6
+#define CRB7 S3_CR+0xB7
+#define CRB8 S3_CR+0xB8
+#define CRB9 S3_CR+0xB9
+#define CRBA S3_CR+0xBA
+#define CRBB S3_CR+0xBB
+#define CRBC S3_CR+0xBC
+#define CRBD S3_CR+0xBD
+#define CRBE S3_CR+0xBE
+#define CRBF S3_CR+0xBF
+
+#define CR_FIRST CR00
+
+VgaReg s3_h_total[] = {
+ CR00, 0, 8,
+ CR5D, 0, 1,
+ CR5F, 0, 2,
+ VGA_REG_END
+};
+
+VgaReg s3_h_display_end[] = {
+ CR01, 0, 8,
+ CR5D, 1, 1,
+ CR5F, 2, 2,
+ VGA_REG_END
+};
+
+VgaReg s3_h_blank_start[] = {
+ CR02, 0, 8,
+ CR5D, 2, 1,
+ CR5F, 4, 2,
+ VGA_REG_END
+};
+
+VgaReg s3_h_blank_end[] = {
+ CR03, 0, 5,
+ CR05, 7, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_display_skew[] = {
+ CR03, 5, 2,
+ VGA_REG_END
+};
+
+VgaReg s3_h_sync_start[] = {
+ CR04, 0, 8,
+ CR5D, 4, 1,
+ CR5F, 6, 2,
+ VGA_REG_END
+};
+
+VgaReg s3_h_sync_end[] = {
+ CR05, 0, 5,
+ VGA_REG_END
+};
+
+VgaReg s3_h_skew[] = {
+ CR05, 5, 2,
+ VGA_REG_END
+};
+
+VgaReg s3_v_total[] = {
+ CR06, 0, 8,
+ CR07, 0, 1,
+ CR07, 5, 1,
+ CR5E, 0, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_preset_row_scan[] = {
+ CR08, 0, 8,
+ VGA_REG_END
+};
+
+VgaReg s3_max_scan_line[] = {
+ CR09, 0, 5,
+ VGA_REG_END
+};
+
+VgaReg s3_start_address[] = {
+ CR0D, 0, 8,
+ CR0C, 0, 8,
+ CR69, 0, 7,
+ VGA_REG_END
+};
+
+VgaReg s3_v_retrace_start[] = {
+ CR10, 0, 8,
+ CR07, 2, 1,
+ CR07, 7, 1,
+ CR5E, 4, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_v_retrace_end[] = {
+ CR11, 0, 4,
+ VGA_REG_END
+};
+
+VgaReg s3_clear_v_retrace_int[] = {
+ CR11, 4, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_disable_v_retrace_int[] = {
+ CR11, 5, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_lock_crtc[] = {
+ CR11, 7, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_v_display_end[] = {
+ CR12, 0, 8,
+ CR07, 1, 1,
+ CR07, 6, 1,
+ CR5E, 1, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_screen_offset[] = {
+ CR13, 0, 8,
+ CR51, 4, 2,
+ VGA_REG_END
+};
+
+VgaReg s3_count_by_4_mode[] = {
+ CR14, 5, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_doubleword_mode[] = {
+ CR14, 6, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_v_blank_start[] = {
+ CR15, 0, 8,
+ CR07, 3, 1,
+ CR09, 5, 1,
+ CR5E, 2, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_v_blank_end[] = {
+ CR16, 0, 8,
+ VGA_REG_END
+};
+
+VgaReg s3_v_total_double[] = {
+ CR17, 2, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_word_mode[] = {
+ CR17, 3, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_byte_mode[] = {
+ CR17, 6, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_line_compare[] = {
+ CR18, 0, 8,
+ CR07, 4, 1,
+ CR09, 6, 1,
+ CR5E, 6, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_device_id[] = {
+ CR2E, 0, 8,
+ CR2D, 0, 8,
+ VGA_REG_END
+};
+
+VgaReg s3_revision[] = {
+ CR2F, 0, 8,
+ VGA_REG_END
+};
+
+VgaReg s3_enable_vga_16bit[] = {
+ CR31, 2, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_enhanced_memory_mapping[] = {
+ CR31, 3, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_lock_dac_writes[] = {
+ CR33, 4, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_border_select[] = {
+ CR33, 5, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_enable_sff[] = {
+ CR34, 4, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_lock_vert[] = {
+ CR35, 4, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_lock_horz[] = {
+ CR35, 5, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_io_disable[] = {
+ CR36, 4, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_mem_size[] = {
+ CR36, 5, 3,
+ VGA_REG_END
+};
+
+VgaReg s3_register_lock_1 [] = {
+ CR38, 0, 8, /* load with 0x48 */
+ VGA_REG_END
+};
+
+VgaReg s3_register_lock_2 [] = {
+ CR39, 0, 8, /* load with 0xa0 */
+ VGA_REG_END
+};
+
+VgaReg s3_refresh_control[] = {
+ CR3A, 0, 2,
+ VGA_REG_END
+};
+
+VgaReg s3_enable_256[] = {
+ CR3A, 4, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_disable_pci_read_bursts[] = {
+ CR3A, 7, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_h_start_fifo_fetch[] = {
+ CR3B, 0, 8,
+ CR5D, 6, 1,
+ CR5B, 2, 2,
+ VGA_REG_END
+};
+
+VgaReg s3_enable_2d_access[] = {
+ CR40, 0, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_interlace[] = {
+ CR42, 5, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_old_screen_off_8[] = {
+ CR43, 2, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_h_counter_double_mode[] = {
+ CR43, 7, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_cursor_enable[] = {
+ CR45, 0, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_cursor_right[] = {
+ CR45, 4, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_cursor_xhigh[] = {
+ CR46, 0, 3,
+ VGA_REG_END
+};
+
+VgaReg s3_cursor_xlow[] = {
+ CR47, 0, 8,
+ VGA_REG_END
+};
+
+VgaReg s3_cursor_yhigh[] = {
+ CR48, 0, 3,
+ VGA_REG_END
+};
+
+VgaReg s3_cursor_ylow[] = {
+ CR49, 0, 8,
+ VGA_REG_END
+};
+
+VgaReg s3_cursor_fg[] = {
+ CR4A, 0, 8,
+ VGA_REG_END
+};
+
+VgaReg s3_cursor_bg[] = {
+ CR4B, 0, 8,
+ VGA_REG_END
+};
+
+VgaReg s3_cursor_address[] = {
+ CR4D, 0, 8,
+ CR4C, 0, 8,
+ VGA_REG_END
+};
+
+VgaReg s3_cursor_xoff[] = {
+ CR4E, 0, 6,
+ VGA_REG_END
+};
+
+VgaReg s3_cursor_yoff[] = {
+ CR4F, 0, 6,
+ VGA_REG_END
+};
+
+VgaReg s3_ge_screen_width[] = {
+ CR50, 6, 2,
+ CR50, 0, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_pixel_length[] = {
+ CR50, 4, 2,
+ VGA_REG_END
+};
+
+VgaReg s3_big_endian_linear[] = {
+ CR53, 1, 2,
+ VGA_REG_END
+};
+
+VgaReg s3_mmio_select[] = {
+ CR53, 3, 2,
+ VGA_REG_END
+};
+
+VgaReg s3_mmio_window[] = {
+ CR53, 5, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_swap_nibbles[] = {
+ CR53, 6, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_cursor_ms_x11[] = {
+ CR55, 4, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_linear_window_size[] = {
+ CR58, 0, 2,
+ VGA_REG_END
+};
+
+VgaReg s3_enable_linear[] = {
+ CR58, 4, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_h_blank_extend[] = {
+ CR5D, 3, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_h_sync_extend[] = {
+ CR5D, 5, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_sdclk_skew[] = {
+ CR60, 0, 4,
+ VGA_REG_END
+};
+
+VgaReg s3_delay_blank[] = {
+ CR65, 3, 2,
+ VGA_REG_END
+};
+
+VgaReg s3_delay_h_enable[] = {
+ CR65, 6, 2,
+ CR65, 0, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_enable_2d_3d[] = {
+ CR66, 0, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_pci_disconnect_enable[] = {
+ CR66, 3, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_pci_retry_enable[] = {
+ CR66, 7, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_color_mode[] = {
+ CR67, 4, 4,
+ VGA_REG_END
+};
+
+VgaReg s3_master_control_unit_timeout[] = {
+ CR74, 0, 8,
+ VGA_REG_END
+};
+
+VgaReg s3_command_buffer_timeout[] = {
+ CR75, 0, 8,
+ VGA_REG_END
+};
+
+VgaReg s3_lpb_timeout[] = {
+ CR76, 0, 8,
+ VGA_REG_END
+};
+
+VgaReg s3_cpu_timeout[] = {
+ CR78, 0, 8,
+ VGA_REG_END
+};
+
+VgaReg s3_2d_graphics_engine_timeout[] = {
+ CR79, 0, 8,
+ VGA_REG_END
+};
+
+VgaReg s3_fifo_drain_delay[] = {
+ CR85, 0, 3,
+ VGA_REG_END
+};
+
+VgaReg s3_fifo_fetch_timing[] = {
+ CR85, 4, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_primary_stream_l1[] = {
+ CR91, 0, 8,
+ CR90, 0, 3,
+ VGA_REG_END
+};
+
+#define CR_LAST CR91
+
+#define SR00 S3_SR+0x00
+#define SR01 S3_SR+0x01
+#define SR02 S3_SR+0x02
+#define SR03 S3_SR+0x03
+#define SR04 S3_SR+0x04
+#define SR05 S3_SR+0x05
+#define SR06 S3_SR+0x06
+#define SR07 S3_SR+0x07
+#define SR08 S3_SR+0x08
+#define SR09 S3_SR+0x09
+#define SR0A S3_SR+0x0A
+#define SR0B S3_SR+0x0B
+#define SR0C S3_SR+0x0C
+#define SR0D S3_SR+0x0D
+#define SR0E S3_SR+0x0E
+#define SR0F S3_SR+0x0F
+#define SR10 S3_SR+0x10
+#define SR11 S3_SR+0x11
+#define SR12 S3_SR+0x12
+#define SR13 S3_SR+0x13
+#define SR14 S3_SR+0x14
+#define SR15 S3_SR+0x15
+#define SR16 S3_SR+0x16
+#define SR17 S3_SR+0x17
+#define SR18 S3_SR+0x18
+#define SR19 S3_SR+0x19
+#define SR1A S3_SR+0x1A
+#define SR1B S3_SR+0x1B
+#define SR1C S3_SR+0x1C
+#define SR1D S3_SR+0x1D
+#define SR1E S3_SR+0x1E
+#define SR1F S3_SR+0x1F
+#define SR20 S3_SR+0x20
+#define SR21 S3_SR+0x21
+#define SR22 S3_SR+0x22
+#define SR23 S3_SR+0x23
+#define SR24 S3_SR+0x24
+#define SR25 S3_SR+0x25
+#define SR26 S3_SR+0x26
+#define SR27 S3_SR+0x27
+#define SR28 S3_SR+0x28
+#define SR29 S3_SR+0x29
+#define SR2A S3_SR+0x2A
+#define SR2B S3_SR+0x2B
+#define SR2C S3_SR+0x2C
+#define SR2D S3_SR+0x2D
+#define SR2E S3_SR+0x2E
+#define SR2F S3_SR+0x2F
+#define SR30 S3_SR+0x30
+#define SR31 S3_SR+0x31
+#define SR32 S3_SR+0x32
+#define SR33 S3_SR+0x33
+#define SR34 S3_SR+0x34
+#define SR35 S3_SR+0x35
+#define SR36 S3_SR+0x36
+#define SR37 S3_SR+0x37
+#define SR38 S3_SR+0x38
+#define SR39 S3_SR+0x39
+#define SR3A S3_SR+0x3A
+#define SR3B S3_SR+0x3B
+#define SR3C S3_SR+0x3C
+#define SR3D S3_SR+0x3D
+#define SR3E S3_SR+0x3E
+#define SR3F S3_SR+0x3F
+#define SR40 S3_SR+0x40
+#define SR41 S3_SR+0x41
+#define SR42 S3_SR+0x42
+#define SR43 S3_SR+0x43
+#define SR44 S3_SR+0x44
+#define SR45 S3_SR+0x45
+#define SR46 S3_SR+0x46
+#define SR47 S3_SR+0x47
+#define SR48 S3_SR+0x48
+#define SR49 S3_SR+0x49
+#define SR4A S3_SR+0x4A
+#define SR4B S3_SR+0x4B
+#define SR4C S3_SR+0x4C
+#define SR4D S3_SR+0x4D
+#define SR4E S3_SR+0x4E
+#define SR4F S3_SR+0x4F
+#define SR50 S3_SR+0x50
+#define SR51 S3_SR+0x51
+#define SR52 S3_SR+0x52
+#define SR53 S3_SR+0x53
+#define SR54 S3_SR+0x54
+#define SR55 S3_SR+0x55
+#define SR56 S3_SR+0x56
+#define SR57 S3_SR+0x57
+#define SR58 S3_SR+0x58
+#define SR59 S3_SR+0x59
+#define SR5A S3_SR+0x5A
+#define SR5B S3_SR+0x5B
+#define SR5C S3_SR+0x5C
+#define SR5D S3_SR+0x5D
+#define SR5E S3_SR+0x5E
+#define SR5F S3_SR+0x5F
+#define SR60 S3_SR+0x60
+#define SR61 S3_SR+0x61
+#define SR62 S3_SR+0x62
+#define SR63 S3_SR+0x63
+#define SR64 S3_SR+0x64
+#define SR65 S3_SR+0x65
+#define SR66 S3_SR+0x66
+#define SR67 S3_SR+0x67
+#define SR68 S3_SR+0x68
+#define SR69 S3_SR+0x69
+#define SR6A S3_SR+0x6A
+#define SR6B S3_SR+0x6B
+#define SR6C S3_SR+0x6C
+#define SR6D S3_SR+0x6D
+#define SR6E S3_SR+0x6E
+#define SR6F S3_SR+0x6F
+
+#define SR_FIRST SR02
+
+VgaReg s3_dot_clock_8[] = {
+ SR01, 0, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_screen_off[] = {
+ SR01, 5, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_enable_write_plane[] = {
+ SR02, 0, 4,
+ VGA_REG_END
+};
+
+VgaReg s3_extended_memory_access[] = {
+ SR04, 1, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_sequential_addressing_mode[] = {
+ SR04, 2, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_select_chain_4_mode[] = {
+ SR04, 3, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_unlock_extended_sequencer[] = {
+ SR08, 0, 8, /* write 0x06 */
+ VGA_REG_END
+};
+
+VgaReg s3_linear_addressing_control[] = {
+ SR09, 0, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_disable_io_ports[] = {
+ SR09, 7, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_hsync_control[] = {
+ SR0D, 4, 2,
+ VGA_REG_END
+};
+
+VgaReg s3_vsync_control[] = {
+ SR0D, 6, 2,
+ VGA_REG_END
+};
+
+VgaReg s3_mclk_n[] = {
+ SR10, 0, 5,
+ VGA_REG_END
+};
+
+VgaReg s3_mclk_r[] = {
+ SR10, 5, 2,
+ VGA_REG_END
+};
+
+VgaReg s3_mclk_m[] = {
+ SR11, 0, 7,
+ VGA_REG_END
+};
+
+VgaReg s3_dclk_n[] = {
+ SR12, 0, 6,
+ SR29, 4, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_dclk_r[] = {
+ SR12, 6, 2,
+ SR29, 2, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_dclk_m[] = {
+ SR13, 0, 8,
+ SR29, 3, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_mclk_load[] = {
+ SR15, 0, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_dclk_load[] = {
+ SR15, 1, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_dclk_over_2[] = {
+ SR15, 4, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_clock_load_imm[] = {
+ SR15, 5, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_dclk_invert[] = {
+ SR15, 6, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_enable_clock_double[] = {
+ SR18, 7, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_dclk_double_15_16_invert[] = {
+ SR1A, 0, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_enable_gamma_correction[] = {
+ SR1B, 3, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_enable_8_bit_luts[] = {
+ SR1B, 4, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_dclk_control[] = {
+ SR1B, 7, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_vga_dclk_n[] = {
+ SR36, 0, 6,
+ SR39, 4, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_vga_dclk_r[] = {
+ SR36, 6, 2,
+ SR39, 2, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_vga_dclk_m1[] = {
+ SR37, 0, 8,
+ SR39, 3, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_vga_dclk_m2[] = {
+ SR38, 0, 8,
+ SR39, 3, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_vga_clk_select[] = {
+ SR39, 0, 1,
+ VGA_REG_END
+};
+
+#define SR_LAST SR39
+
+#define AR00 (S3_AR+0x00)
+#define AR10 (S3_AR+0x10)
+#define AR11 (S3_AR+0x11)
+#define AR12 (S3_AR+0x12)
+#define AR13 (S3_AR+0x13)
+#define AR14 (S3_AR+0x14)
+
+#define AR_FIRST AR00
+
+VgaReg s3_select_graphics_mode[] = {
+ AR10, 0, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_enable_blinking[] = {
+ AR10, 3, 1,
+ VGA_REG_END
+};
+
+#define AR_LAST AR10
+
+VgaReg s3_clock_select[] = {
+ S3_MISC_OUT, 2, 2,
+ VGA_REG_END
+};
+
+VgaReg s3_horz_sync_neg[] = {
+ S3_MISC_OUT, 6, 1,
+ VGA_REG_END
+};
+
+VgaReg s3_vert_sync_neg[] = {
+ S3_MISC_OUT, 7, 1,
+ VGA_REG_END
+};
+
+VGA8
+_s3Inb (VgaCard *card, VGA16 port)
+{
+ VGAVOL8 *reg;
+
+ if (card->closure)
+ return *(((VGAVOL8 *) card->closure) + port);
+ else
+ return VgaInb (port);
+}
+
+void
+_s3Outb (VgaCard *card, VGA8 value, VGA16 port)
+{
+ VGAVOL8 *reg;
+
+ if (card->closure)
+ *(((VGAVOL8 *) card->closure) + port) = value;
+ else
+ VgaOutb (value, port);
+}
+
+void
+_s3RegMap (VgaCard *card, VGA16 reg, VgaMap *map, VGABOOL write)
+{
+
+ if (reg < S3_SR + S3_NSR)
+ {
+ map->access = VgaAccessIndIo;
+ map->port = 0x3c4;
+ map->addr = 0;
+ map->value = 1;
+ map->index = reg - S3_SR;
+ }
+ else if (reg < S3_GR + S3_NGR)
+ {
+ map->access = VgaAccessIndIo;
+ map->port = 0x3ce;
+ map->addr = 0;
+ map->value = 1;
+ map->index = reg - S3_GR;
+ }
+ else if (reg < S3_AR + S3_NAR)
+ {
+ reg -= S3_AR;
+ map->access = VgaAccessDone;
+ /* reset AFF to index */
+ (void) _s3Inb (card, 0x3da);
+ _s3Outb (card, reg, 0x3c0);
+ if (write)
+ _s3Outb (card, map->value, 0x3c0);
+ else
+ map->value = _s3Inb (card, 0x3c1);
+ /* enable video display again */
+ (void) _s3Inb (card, 0x3da);
+ _s3Outb (card, 0x20, 0x3c0);
+ return;
+ }
+ else if (reg < S3_CR + S3_NCR)
+ {
+ map->access = VgaAccessIndIo;
+ map->port = 0x3d4;
+ map->addr = 0;
+ map->value = 1;
+ map->index = reg - S3_CR;
+ }
+ else switch (reg) {
+ case S3_MISC_OUT:
+ map->access = VgaAccessIo;
+ if (write)
+ map->port = 0x3c2;
+ else
+ map->port = 0x3cc;
+ break;
+ }
+ if (card->closure)
+ {
+ map->port = map->port + (VGA32) card->closure;
+ if (map->access == VgaAccessIo)
+ map->access = VgaAccessMem;
+ if (map->access == VgaAccessIndIo)
+ map->access = VgaAccessIndMem;
+ }
+}
+
+VgaSave s3Saves[] = {
+ CR_FIRST, CR18,
+ CR31, CR_LAST,
+ SR_FIRST, SR15,
+ SR18, SR_LAST,
+ AR_FIRST, AR_LAST,
+ S3_MISC_OUT, S3_MISC_OUT,
+ VGA_SAVE_END
+};
+
+void
+s3RegInit (S3Vga *s3vga, VGAVOL8 *mmio)
+{
+ s3vga->card.map = _s3RegMap;
+ s3vga->card.closure = (void *) mmio;
+ s3vga->card.max = S3_NREG;
+ s3vga->card.values = s3vga->values;
+ s3vga->card.saves = s3Saves;
+}
+
+void
+s3Save (S3Vga *s3vga)
+{
+ s3vga->save_lock_crtc = s3Get(s3vga, s3_lock_crtc);
+ s3SetImm (s3vga, s3_lock_crtc, 0);
+ s3vga->save_register_lock_1 = s3Get (s3vga, s3_register_lock_1);
+ s3SetImm (s3vga, s3_register_lock_1, 0x48);
+ s3vga->save_register_lock_2 = s3Get (s3vga, s3_register_lock_2);
+ s3SetImm (s3vga, s3_register_lock_2, 0xa0);
+ s3vga->save_unlock_extended_sequencer = s3Get (s3vga, s3_unlock_extended_sequencer);
+ s3SetImm (s3vga, s3_unlock_extended_sequencer, 0x06);
+ s3vga->save_lock_horz = s3Get (s3vga, s3_lock_horz);
+ s3SetImm (s3vga, s3_lock_horz, 0);
+ s3vga->save_lock_vert = s3Get (s3vga, s3_lock_vert);
+ s3SetImm (s3vga, s3_lock_vert, 0);
+ s3vga->save_dot_clock_8 = s3Get (s3vga, s3_dot_clock_8);
+ VgaPreserve (&s3vga->card);
+}
+
+void
+s3Reset (S3Vga *s3vga)
+{
+ VgaRestore (&s3vga->card);
+ s3SetImm (s3vga, s3_clock_load_imm, 1);
+ s3SetImm (s3vga, s3_clock_load_imm, 0);
+ s3SetImm (s3vga, s3_dot_clock_8, s3vga->save_dot_clock_8);
+ s3SetImm (s3vga, s3_lock_vert, s3vga->save_lock_vert);
+ s3SetImm (s3vga, s3_lock_horz, s3vga->save_lock_horz);
+ s3SetImm (s3vga, s3_lock_dac_writes, s3vga->save_lock_dac_writes);
+ s3SetImm (s3vga, s3_unlock_extended_sequencer, s3vga->save_unlock_extended_sequencer);
+ s3SetImm (s3vga, s3_register_lock_2, s3vga->save_register_lock_2);
+ s3SetImm (s3vga, s3_register_lock_1, s3vga->save_register_lock_1);
+ s3SetImm (s3vga, s3_lock_crtc, s3vga->save_lock_crtc);
+ VgaFinish (&s3vga->card);
+}
diff --git a/hw/kdrive/savage/s3reg.h b/hw/kdrive/savage/s3reg.h
new file mode 100644
index 000000000..f1ac18d03
--- /dev/null
+++ b/hw/kdrive/savage/s3reg.h
@@ -0,0 +1,195 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999 SuSE, Inc.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+/* $XFree86: $ */
+
+#ifndef _S3REG_H_
+#define _S3REG_H_
+
+#include "vga.h"
+
+#define S3_SR 0
+#define S3_NSR 0x70
+#define S3_GR (S3_SR+S3_NSR)
+#define S3_NGR 0x09
+#define S3_AR (S3_GR+S3_NGR)
+#define S3_NAR 0x15
+#define S3_CR (S3_AR+S3_NAR)
+#define S3_NCR 0xc0
+#define S3_MISC_OUT (S3_CR+S3_NCR)
+#define S3_NREG (S3_MISC_OUT+1)
+
+extern VgaReg s3_h_total[];
+extern VgaReg s3_h_display_end[];
+extern VgaReg s3_h_blank_start[];
+extern VgaReg s3_h_blank_end[];
+extern VgaReg s3_display_skew[];
+extern VgaReg s3_h_sync_start[];
+extern VgaReg s3_h_sync_end[];
+extern VgaReg s3_h_skew[];
+extern VgaReg s3_v_total[];
+extern VgaReg s3_preset_row_scan[];
+extern VgaReg s3_max_scan_line[];
+extern VgaReg s3_start_address[];
+extern VgaReg s3_v_retrace_start[];
+extern VgaReg s3_v_retrace_end[];
+extern VgaReg s3_clear_v_retrace_int[];
+extern VgaReg s3_disable_v_retrace_int[];
+extern VgaReg s3_lock_crtc[];
+extern VgaReg s3_v_display_end[];
+extern VgaReg s3_screen_offset[];
+extern VgaReg s3_count_by_4_mode[];
+extern VgaReg s3_doubleword_mode[];
+extern VgaReg s3_v_blank_start[];
+extern VgaReg s3_v_blank_end[];
+extern VgaReg s3_v_total_double[];
+extern VgaReg s3_word_mode[];
+extern VgaReg s3_byte_mode[];
+extern VgaReg s3_line_compare[];
+extern VgaReg s3_device_id[];
+extern VgaReg s3_revision[];
+extern VgaReg s3_enable_vga_16bit[];
+extern VgaReg s3_enhanced_memory_mapping[];
+extern VgaReg s3_enable_sff[];
+extern VgaReg s3_lock_dac_writes[];
+extern VgaReg s3_border_select[];
+extern VgaReg s3_lock_vert[];
+extern VgaReg s3_lock_horz[];
+extern VgaReg s3_io_disable[];
+extern VgaReg s3_mem_size[];
+extern VgaReg s3_register_lock_1 [];
+extern VgaReg s3_register_lock_2 [];
+extern VgaReg s3_refresh_control[];
+extern VgaReg s3_enable_256[];
+extern VgaReg s3_disable_pci_read_bursts[];
+extern VgaReg s3_h_start_fifo_fetch[];
+extern VgaReg s3_enable_2d_access[];
+extern VgaReg s3_interlace[];
+extern VgaReg s3_old_screen_off_8[];
+extern VgaReg s3_h_counter_double_mode[];
+extern VgaReg s3_cursor_enable[];
+extern VgaReg s3_cursor_right[];
+extern VgaReg s3_cursor_xhigh[];
+extern VgaReg s3_cursor_xlow[];
+extern VgaReg s3_cursor_yhigh[];
+extern VgaReg s3_cursor_ylow[];
+extern VgaReg s3_cursor_fg[];
+extern VgaReg s3_cursor_bg[];
+extern VgaReg s3_cursor_address[];
+extern VgaReg s3_cursor_xoff[];
+extern VgaReg s3_cursor_yoff[];
+extern VgaReg s3_ge_screen_width[];
+extern VgaReg s3_pixel_length[];
+extern VgaReg s3_big_endian_linear[];
+extern VgaReg s3_mmio_select[];
+extern VgaReg s3_mmio_window[];
+extern VgaReg s3_swap_nibbles[];
+extern VgaReg s3_cursor_ms_x11[];
+extern VgaReg s3_linear_window_size[];
+extern VgaReg s3_enable_linear[];
+extern VgaReg s3_h_blank_extend[];
+extern VgaReg s3_h_sync_extend[];
+extern VgaReg s3_sdclk_skew[];
+extern VgaReg s3_delay_blank[];
+extern VgaReg s3_delay_h_enable[];
+extern VgaReg s3_enable_2d_3d[];
+extern VgaReg s3_pci_disconnect_enable[];
+extern VgaReg s3_pci_retry_enable[];
+extern VgaReg s3_color_mode[];
+extern VgaReg s3_master_control_unit_timeout[];
+extern VgaReg s3_command_buffer_timeout[];
+extern VgaReg s3_lpb_timeout[];
+extern VgaReg s3_cpu_timeout[];
+extern VgaReg s3_2d_graphics_engine_timeout[];
+extern VgaReg s3_fifo_drain_delay[];
+extern VgaReg s3_fifo_fetch_timing[];
+extern VgaReg s3_primary_stream_l1[];
+
+extern VgaReg s3_dot_clock_8[];
+extern VgaReg s3_screen_off[];
+extern VgaReg s3_enable_write_plane[];
+extern VgaReg s3_extended_memory_access[];
+extern VgaReg s3_sequential_addressing_mode[];
+extern VgaReg s3_select_chain_4_mode[];
+
+extern VgaReg s3_unlock_extended_sequencer[];
+extern VgaReg s3_linear_addressing_control[];
+extern VgaReg s3_disable_io_ports[];
+extern VgaReg s3_hsync_control[];
+extern VgaReg s3_vsync_control[];
+extern VgaReg s3_mclk_n[];
+extern VgaReg s3_mclk_r[];
+extern VgaReg s3_mclk_m[];
+extern VgaReg s3_dclk_n[];
+extern VgaReg s3_dclk_r[];
+extern VgaReg s3_dclk_m[];
+extern VgaReg s3_mclk_load[];
+extern VgaReg s3_dclk_load[];
+extern VgaReg s3_dclk_over_2[];
+extern VgaReg s3_clock_load_imm[];
+extern VgaReg s3_dclk_invert[];
+extern VgaReg s3_enable_clock_double[];
+extern VgaReg s3_dclk_double_15_16_invert[];
+extern VgaReg s3_enable_gamma_correction[];
+extern VgaReg s3_enable_8_bit_luts[];
+extern VgaReg s3_dclk_control[];
+extern VgaReg s3_vga_dclk_n[];
+extern VgaReg s3_vga_dclk_r[];
+extern VgaReg s3_vga_dclk_m1[];
+extern VgaReg s3_vga_dclk_m2[];
+extern VgaReg s3_vga_clk_select[];
+extern VgaReg s3_select_graphics_mode[];
+extern VgaReg s3_enable_blinking[];
+extern VgaReg s3_clock_select[];
+extern VgaReg s3_horz_sync_neg[];
+extern VgaReg s3_vert_sync_neg[];
+
+#define s3Get(sv,r) VgaGet(&(sv)->card, (r))
+#define s3GetImm(sv,r) VgaGetImm(&(sv)->card, (r))
+#define s3Set(sv,r,v) VgaSet(&(sv)->card, (r), (v))
+#define s3SetImm(sv,r,v) VgaSetImm(&(sv)->card, (r), (v))
+
+typedef struct _s3Vga {
+ VgaCard card;
+ VgaValue values[S3_NREG];
+ VGA32 save_lock_crtc;
+ VGA32 save_register_lock_1;
+ VGA32 save_register_lock_2;
+ VGA32 save_unlock_extended_sequencer;
+ VGA32 save_lock_dac_writes;
+ VGA32 save_lock_horz;
+ VGA32 save_lock_vert;
+ VGA32 save_dot_clock_8;
+} S3Vga;
+
+void
+s3RegInit (S3Vga *s3vga, VGAVOL8 *mmio);
+
+void
+s3Save (S3Vga *s3vga);
+
+void
+s3Reset (S3Vga *s3vga);
+
+#endif /* _S3REG_H_ */
diff --git a/hw/kdrive/savage/s3rtst.c b/hw/kdrive/savage/s3rtst.c
new file mode 100644
index 000000000..c3989f216
--- /dev/null
+++ b/hw/kdrive/savage/s3rtst.c
@@ -0,0 +1,141 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999 SuSE, Inc.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+/* $XFree86: $ */
+
+#include <stdio.h>
+#include "s3reg.h"
+
+typedef struct {
+ VgaReg *reg;
+ char *name;
+} NamedVgaReg;
+
+NamedVgaReg s3VRegs[] = {
+ s3_h_total, "h_total",
+ s3_h_display_end, "h_display_end",
+ s3_h_blank_start, "h_blank_start",
+ s3_h_blank_end, "h_blank_end",
+ s3_display_skew, "display_skew",
+ s3_h_sync_start, "h_sync_start",
+ s3_h_sync_end, "h_sync_end",
+ s3_h_skew, "h_skew",
+ s3_v_total, "v_total",
+ s3_preset_row_scan, "preset_row_scan",
+ s3_max_scan_line, "max_scan_line",
+ s3_start_address, "start_address",
+ s3_v_retrace_start, "v_retrace_start",
+ s3_v_retrace_end, "v_retrace_end",
+ s3_clear_v_retrace_int, "clear_v_retrace_int",
+ s3_disable_v_retrace_int, "disable_v_retrace_int",
+ s3_lock_crtc, "lock_crtc",
+ s3_v_display_end, "v_display_end",
+ s3_screen_offset, "screen_offset",
+ s3_count_by_4_mode, "count_by_4_mode",
+ s3_doubleword_mode, "doubleword_mode",
+ s3_v_blank_start, "v_blank_start",
+ s3_v_blank_end, "v_blank_end",
+ s3_v_total_double, "v_total_double",
+ s3_word_mode, "word_mode",
+ s3_byte_mode, "byte_mode",
+ s3_line_compare, "line_compare",
+ s3_device_id, "device_id",
+ s3_revision, "revision",
+ s3_lock_vert, "lock_vert",
+ s3_lock_horz, "lock_horz",
+ s3_io_disable, "io_disable",
+ s3_mem_size, "mem_size",
+ s3_register_lock_1 , "register_lock_1 ",
+ s3_register_lock_2 , "register_lock_2 ",
+ s3_refresh_control, "refresh_control",
+ s3_enable_256, "enable_256",
+ s3_enable_pci_read_bursts, "enable_pci_read_bursts",
+ s3_h_start_fifo_fetch, "h_start_fifo_fetch",
+ s3_interlace, "interlace",
+ s3_old_screen_off_8, "old_screen_off_8",
+ s3_h_counter_double_mode, "h_counter_double_mode",
+ s3_hardware_cursor_enable, "hardware_cursor_enable",
+ s3_hardware_cursor_right, "hardware_cursor_right",
+ s3_hardware_cursor_x, "hardware_cursor_x",
+ s3_hardware_cursor_y, "hardware_cursor_y",
+ s3_hardware_cursor_fg, "hardware_cursor_fg",
+ s3_cursor_address, "cursor_address",
+ s3_cursor_start_x, "cursor_start_x",
+ s3_cursor_start_y, "cursor_start_y",
+ s3_ge_screen_width, "ge_screen_width",
+ s3_pixel_length, "pixel_length",
+ s3_big_endian_linear, "big_endian_linear",
+ s3_mmio_select, "mmio_select",
+ s3_mmio_window, "mmio_window",
+ s3_swap_nibbles, "swap_nibbles",
+ s3_hardware_cursor_ms_x11, "hardware_cursor_ms_x11",
+ s3_h_blank_extend, "h_blank_extend",
+ s3_h_sync_extend, "h_sync_extend",
+ s3_enable_2d_3d, "enable_2d_3d",
+ s3_pci_disconnect_enable, "pci_disconnect_enable",
+ s3_pci_retry_enable, "pci_retry_enable",
+ s3_color_mode, "color_mode",
+ s3_screen_off, "screen_off",
+ s3_unlock_extended_sequencer, "unlock_extended_sequencer",
+ s3_disable_io_ports, "disable_io_ports",
+ s3_hsync_control, "hsync_control",
+ s3_vsync_control, "vsync_control",
+ s3_mclk_n, "mclk_n",
+ s3_mclk_r, "mclk_r",
+ s3_mclk_m, "mclk_m",
+ s3_dclk_n, "dclk_n",
+ s3_dclk_r, "dclk_r",
+ s3_dclk_m, "dclk_m",
+ s3_mclk_load, "mclk_load",
+ s3_dclk_load, "dclk_load",
+ s3_dclk_over_2, "dclk_over_2",
+ s3_clock_load_imm, "clock_load_imm",
+ s3_dclk_invert, "dclk_invert",
+ s3_enable_clock_double, "enable_clock_double",
+ s3_dclk_double_15_16_invert, "dclk_double_15_16_invert",
+ s3_enable_gamma_correction, "enable_gamma_correction",
+ s3_enable_8_bit_luts, "enable_8_bit_luts",
+ s3_dclk_control, "dclk_control",
+ s3_vga_dclk_n, "vga_dclk_n",
+ s3_vga_dclk_r, "vga_dclk_r",
+ s3_vga_dclk_m1, "vga_dclk_m1",
+ s3_vga_dclk_m2, "vga_dclk_m2",
+ s3_vga_clk_select, "vga_clk_select",
+ s3_clock_select, "clock_select",
+};
+
+#define NUM_S3_VREGS (sizeof (s3VRegs)/ sizeof (s3VRegs[0]))
+
+main (int argc, char **argv)
+{
+ int i;
+
+ iopl(3);
+ s3SetImm(s3_register_lock_1, 0x48);
+ s3SetImm(s3_register_lock_2, 0xa0);
+ s3SetImm(s3_unlock_extended_sequencer, 0x06);
+ for (i = 0; i < NUM_S3_VREGS; i++)
+ printf ("%-20.20s %8x\n", s3VRegs[i].name, s3Get (s3VRegs[i].reg));
+ s3Restore ();
+}
diff --git a/hw/kdrive/savage/s3stub.c b/hw/kdrive/savage/s3stub.c
new file mode 100644
index 000000000..59e187984
--- /dev/null
+++ b/hw/kdrive/savage/s3stub.c
@@ -0,0 +1,60 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999 SuSE, Inc.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+/* $XFree86: $ */
+
+#include "s3.h"
+
+void
+InitCard (char *name)
+{
+ KdCardAttr attr;
+ CARD32 count;
+
+ count = 0;
+ while (LinuxFindPci (0x5333, 0x8a22, count, &attr))
+ {
+ KdCardInfoAdd (&s3Funcs, &attr, 0);
+ count++;
+ }
+}
+
+void
+InitOutput (ScreenInfo *pScreenInfo, int argc, char **argv)
+{
+ KdInitOutput (pScreenInfo, argc, argv);
+}
+
+void
+InitInput (int argc, char **argv)
+{
+ KdInitInput (&Ps2MouseFuncs, &LinuxKeyboardFuncs);
+}
+
+void
+OsVendorInit (void)
+{
+ KdOsInit (&LinuxFuncs);
+}
+
diff --git a/hw/kdrive/sis530/Imakefile b/hw/kdrive/sis530/Imakefile
new file mode 100644
index 000000000..28568ab5c
--- /dev/null
+++ b/hw/kdrive/sis530/Imakefile
@@ -0,0 +1,15 @@
+XCOMM $XConsortium: Imakefile /main/10 1996/12/02 10:20:33 lehors $
+XCOMM $XFree86: xc/programs/Xserver/hw/nvfb/Imakefile,v 3.8 1996/12/23 06:30:19 dawes Exp $
+#include <Server.tmpl>
+
+SRCS = sis.c sisclock.c siscmap.c siscurs.c sisdraw.c sisio.c sisstub.c
+
+OBJS = sis.o sisclock.o siscmap.o siscurs.o sisdraw.o sisio.o sisstub.o
+
+INCLUDES = -I.. -I. -I$(XBUILDINCDIR) -I$(FONTINCSRC) \
+ -I../../../fb -I../../../mi -I../../../include -I../../../os \
+ -I$(EXTINCSRC) -I$(XINCLUDESRC)
+
+NormalLibraryObjectRule()
+NormalLibraryTarget(sis530,$(OBJS))
+DependTarget()
diff --git a/hw/kdrive/sis530/sis.c b/hw/kdrive/sis530/sis.c
new file mode 100644
index 000000000..e79ce1a4a
--- /dev/null
+++ b/hw/kdrive/sis530/sis.c
@@ -0,0 +1,953 @@
+/*
+ * $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 "sis.h"
+
+#define MAX_FB_SIZE (4096 * 1024)
+
+#define MMIO_SIZE (64 * 1024)
+
+#define SIS_TIMING_BAIL 2
+
+SisTiming sisTimings[] = {
+ /* FP BP BLANK */
+ { 640, 480, 85,
+ 56, 80, 192, /* horizontal 43.265 KHz */
+ 1, 25, 29, /* vertical 85.000 Hz */
+ /* pixel 35.996 MHz */
+ },
+
+ { 640, 480, 75,
+ 16, 120, 200, /* horizontal 37.500 KHz */
+ 1, 16, 20, /* vertical 75.000 Hz */
+ /* pixel 31.500 MHz */
+ },
+
+ { 640, 480, 60,
+ 16, 48, 160, /* horizontal 31.321 KHz */
+ 10, 33, 45, /* vertical 59.568 Hz */
+ /* pixel 25.057 MHz */
+ },
+
+ { 800, 600, 85,
+ 32, 152, 248, /* horizontal 53.673 KHz */
+ 1, 27, 31, /* vertical 85.060 Hz */
+ /* pixel 56.249 MHz */
+ },
+ { 800, 600, 75,
+ 16, 160, 256, /* horizontal 46.891 KHz */
+ 1, 21, 25, /* vertical 75.025 Hz */
+ /* pixel 49.516 MHz */
+ },
+ { 800, 600, 72,
+ 56, 64, 240, /* horizontal 48.186 KHz */
+ 37, 23, 66, /* vertical 72.351 Hz */
+ /* pixel 50.113 MHz */
+ },
+
+ { 1024, 768, 85,
+ 48, 208, 352, /* horizontal 68.676 KHz */
+ 1, 36, 40, /* vertical 84.996 Hz */
+ /* pixel 94.499 MHz */
+ },
+ { 1024, 768, 75,
+ 16, 176, 288, /* horizontal 60.022 KHz */
+ 1, 28, 32, /* vertical 75.028 Hz */
+ /* pixel 78.749 MHz */
+ },
+ { 1024, 768, 70,
+ 24, 144, 304, /* horizontal 56.604 KHz */
+ 3, 29, 38, /* vertical 70.227 Hz */
+ /* pixel 75.170 MHz */
+ },
+ { 1024, 768, 66,
+ 24, 144, 304, /* horizontal 53.234 KHz */
+ 3, 29, 38, /* vertical 66.047 Hz */
+ /* pixel 70.695 MHz */
+ },
+
+ { 1152, 900, 85,
+ 48, 208, 384, /* horizontal 79.900 KHz */
+ 1, 32, 38, /* vertical 85.181 Hz */
+ /* pixel 122.726 MHz */
+ },
+ { 1152, 900, 75,
+ 32, 208, 384, /* horizontal 70.495 Khz */
+ 1, 32, 38, /* vertical 75.154 Hz */
+ /* pixel 108.280 MHz */
+ },
+ { 1152, 900, 70,
+ 32, 208, 384, /* horizontal 65.251 KHz */
+ 2, 32, 38, /* vertical 69.564 Hz */
+ /* pixel 100.226 MHz */
+ },
+ { 1152, 900, 66,
+ 32, 208, 384, /* horizontal 61.817 KHz */
+ 1, 32, 38, /* vertical 65.903 Hz */
+ /* pixel 94.951 MHz */
+ },
+ { 1280, 1024, 85,
+ 16, 248, 416, /* horizontal 90.561 KHz */
+ 1, 40, 45, /* vertical 84.717 Hz */
+ /* pixel 153.593 MHz */
+ },
+ { 1280, 1024, 75,
+ 16, 248, 408, /* horizontal 80.255 KHz */
+ 1, 38, 42, /* vertical 75.285 Hz */
+ /* pixel 134.828 MHz */
+ },
+ { 1280, 1024, 70,
+ 32, 248, 400, /* horizontal 74.573 KHz */
+ 0, 36, 39, /* vertical 70.153 Hz */
+ /* pixel 125.283 MHz */
+ },
+ { 1280, 1024, 66,
+ 32, 248, 400, /* horizontal 70.007 KHz */
+ 0, 36, 39, /* vertical 65.858 Hz */
+ /* pixel 117.612 MHz */
+ },
+
+ { 1600, 1200, 85,
+ 64, 304, 560, /* horizontal 106.059 KHz */
+ 1, 46, 50, /* vertical 84.847 Hz */
+ /* pixel 229.088 MHz */
+ },
+ { 1600, 1200, 75,
+ 64, 304, 560, /* horizontal 93.748 KHz */
+ 1, 46, 50, /* vertical 74.999 Hz */
+ /* pixel 202.497 MHz */
+ },
+ { 1600, 1200, 70,
+ 56, 304, 588, /* horizontal 87.524 KHz */
+ 1, 46, 50, /* vertical 70.019 Hz */
+ /* pixel 191.503 MHz */
+ },
+ { 1600, 1200, 65,
+ 56, 308, 524, /* horizontal 80.050 KHz */
+ 1, 38, 42, /* vertical 64.453 Hz */
+ /* pixel 170.026 MHz */
+ },
+};
+
+#define NUM_SIS_TIMINGS (sizeof (sisTimings) / sizeof (sisTimings[0]))
+
+Bool
+sisCardInit (KdCardInfo *card)
+{
+ SisCardInfo *sisc;
+ SisPtr sis;
+ int size;
+ CARD8 *registers;
+ CARD8 *temp_buffer;
+
+ sisc = (SisCardInfo *) xalloc (sizeof (SisCardInfo));
+ if (!sisc)
+ goto bail0;
+
+ temp_buffer = KdMapDevice (card->attr.address[0], MAX_FB_SIZE);
+ if (!temp_buffer)
+ goto bail1;
+
+ sisc->memory = KdFrameBufferSize (temp_buffer, MAX_FB_SIZE);
+
+ KdUnmapDevice (temp_buffer, MAX_FB_SIZE);
+
+ if (!sisc->memory)
+ {
+ ErrorF ("Can't detect SiS530 frame buffer\n");
+ goto bail1;
+ }
+
+ /*
+ * Map frame buffer and MMIO registers
+ */
+ sisc->frameBuffer = KdMapDevice (card->attr.address[0], sisc->memory);
+ if (!sisc->frameBuffer)
+ goto bail1;
+
+ sisc->registers = KdMapDevice (card->attr.address[1], MMIO_SIZE);
+ if (!sisc->registers)
+ goto bail2;
+
+ /*
+ * Offset from base of MMIO to registers
+ */
+ sisc->sis = (SisPtr) (sisc->registers + SIS_MMIO_OFFSET);
+ sisc->cpu_bitblt = (VOL32 *) sisc->registers;
+ sisc->io_base = card->attr.io;
+
+ /*
+ * enable access to SiS ports (no MMIO available)
+ */
+ ioperm (sisc->io_base, 0x80, 1);
+ card->driver = sisc;
+
+ return TRUE;
+bail2:
+ KdUnmapDevice (sisc->frameBuffer, sisc->memory);
+bail1:
+ xfree (sisc);
+bail0:
+ return FALSE;
+}
+
+SisTiming *
+sisGetTiming (int width, int height, int rate)
+{
+ int i;
+ SisTiming *t;
+
+ for (i = 0; i < NUM_SIS_TIMINGS; i++)
+ {
+ t = &sisTimings[i];
+ if (t->horizontal >= width &&
+ t->vertical >= height &&
+ (!rate || t->rate <= rate))
+ return t;
+ }
+ return &sisTimings[SIS_TIMING_BAIL];
+}
+
+Bool
+sisScreenInit (KdScreenInfo *screen)
+{
+ KdCardInfo *card = screen->card;
+ SisCardInfo *sisc = (SisCardInfo *) card->driver;
+ SisScreenInfo *siss;
+ int i;
+ SisTiming *t;
+ CARD32 memory;
+ int byte_width, pixel_width, screen_size;
+
+ siss = (SisScreenInfo *) xalloc (sizeof (SisScreenInfo));
+ if (!siss)
+ return FALSE;
+
+ memset (siss, '\0', sizeof (SisScreenInfo));
+
+ if (!screen->width || !screen->height)
+ {
+ screen->width = 800;
+ screen->height = 600;
+ screen->rate = 72;
+ }
+ if (!screen->depth)
+ screen->depth = 8;
+
+ for (;;)
+ {
+ if (screen->depth >= 24)
+ {
+ screen->depth = 24;
+ screen->bitsPerPixel = 24;
+ }
+ else if (screen->depth >= 16)
+ {
+ screen->depth = 16;
+ screen->bitsPerPixel = 16;
+ }
+ else if (screen->depth >= 15)
+ {
+ screen->depth = 15;
+ screen->bitsPerPixel = 16;
+ }
+ else
+ {
+ screen->depth = 8;
+ screen->bitsPerPixel = 8;
+ }
+
+ /* Normalize width to supported values */
+
+ if (screen->width >= 1600)
+ screen->width = 1600;
+ else if (screen->width >= 1280)
+ screen->width = 1280;
+ else if (screen->width >= 1152)
+ screen->width = 1152;
+ else if (screen->width >= 1024)
+ screen->width = 1024;
+ else if (screen->width >= 800)
+ screen->width = 800;
+ else
+ screen->width = 640;
+
+ byte_width = screen->width * (screen->bitsPerPixel >> 3);
+ pixel_width = screen->width;
+ screen->pixelStride = pixel_width;
+ screen->byteStride = byte_width;
+
+ screen_size = byte_width * screen->height;
+
+ if (screen_size <= sisc->memory)
+ break;
+
+ /*
+ * Fix requested depth and geometry until it works
+ */
+ if (screen->depth > 16)
+ screen->depth = 16;
+ else if (screen->depth > 8)
+ screen->depth = 8;
+ else if (screen->width > 1152)
+ {
+ screen->width = 1152;
+ screen->height = 900;
+ }
+ else if (screen->width > 1024)
+ {
+ screen->width = 1024;
+ screen->height = 768;
+ }
+ else if (screen->width > 800)
+ {
+ screen->width = 800;
+ screen->height = 600;
+ }
+ else if (screen->width > 640)
+ {
+ screen->width = 640;
+ screen->height = 480;
+ }
+ else
+ {
+ xfree (siss);
+ return FALSE;
+ }
+ }
+
+ t = sisGetTiming (screen->width, screen->height, screen->rate);
+ screen->rate = t->rate;
+ screen->width = t->horizontal;
+ screen->height = t->vertical;
+
+ /*
+ * Take requested geometry and adjust to fit possible geometries
+ */
+ switch (screen->depth) {
+ case 4:
+ screen->bitsPerPixel = 4;
+ break;
+ case 8:
+ screen->bitsPerPixel = 8;
+ break;
+ case 15:
+ case 16:
+ screen->bitsPerPixel = 16;
+ break;
+ case 24:
+ case 32:
+ screen->bitsPerPixel = 24;
+ screen->dumb = TRUE;
+ break;
+ }
+
+ screen->byteStride = screen->width * (screen->bitsPerPixel >> 3);
+ screen->pixelStride = screen->width;
+
+ memory = sisc->memory - screen_size;
+
+ screen->frameBuffer = sisc->frameBuffer;
+
+ /*
+ * Cursor lives in the last 16k of memory
+ */
+ if (memory >= 16384 && !screen->softCursor)
+ {
+ siss->cursor_base = sisc->frameBuffer + (sisc->memory - 16384);
+ siss->cursor_off = siss->cursor_base - sisc->frameBuffer;
+ memory -= 16384;
+ }
+ else
+ {
+ screen->softCursor = TRUE;
+ siss->cursor_base = 0;
+ siss->cursor_off = 0;
+ }
+
+ if (memory > 8192)
+ {
+ siss->expand = screen->frameBuffer + screen_size;
+ siss->expand_off = siss->expand - sisc->frameBuffer;
+ siss->expand_len = memory;
+ memory = 0;
+ }
+ else
+ {
+ siss->expand = 0;
+ siss->expand_len = 0;
+ }
+
+ switch (screen->depth) {
+ case 8:
+ screen->visuals = ((1 << StaticGray) |
+ (1 << GrayScale) |
+ (1 << StaticColor) |
+ (1 << PseudoColor) |
+ (1 << TrueColor) |
+ (1 << DirectColor));
+ screen->blueMask = 0x00;
+ screen->greenMask = 0x00;
+ screen->redMask = 0x00;
+ break;
+ case 15:
+ screen->visuals = (1 << TrueColor);
+ screen->blueMask = 0x001f;
+ screen->greenMask = 0x03e0;
+ screen->redMask = 0x7c00;
+ break;
+ case 16:
+ screen->visuals = (1 << TrueColor);
+ screen->blueMask = 0x001f;
+ screen->greenMask = 0x07e0;
+ screen->redMask = 0xf800;
+ break;
+ case 24:
+ screen->visuals = (1 << TrueColor);
+ screen->blueMask = 0x0000ff;
+ screen->greenMask = 0x00ff00;
+ screen->redMask = 0xff0000;
+ break;
+ }
+
+ screen->driver = siss;
+
+ return TRUE;
+}
+
+static void
+_sisGetCrtc (SisCardInfo *sisc, SisCrtc *crtc)
+{
+ crtc->misc_output = _sisInb(sisc->io_base+0x4c);
+ crtc->h_total_0_7 = GetCrtc (sisc, 0x00);
+ crtc->h_display_end_0_7 = GetCrtc (sisc, 0x01);
+ crtc->h_blank_start_0_7 = GetCrtc (sisc, 0x02);
+ crtc->_h_blank_end = GetCrtc (sisc, 0x03);
+ crtc->h_sync_start_0_7 = GetCrtc (sisc, 0x04);
+ crtc->_h_sync_end = GetCrtc (sisc, 0x05);
+ crtc->v_total_0_7 = GetCrtc (sisc, 0x06);
+ crtc->crtc_overflow = GetCrtc (sisc, 0x07);
+ crtc->preset_row_scan = GetCrtc (sisc, 0x08);
+ crtc->_max_scan_line = GetCrtc (sisc, 0x09);
+
+ crtc->start_address_8_15 = GetCrtc (sisc, 0x0c);
+ crtc->start_address_0_7 = GetCrtc (sisc, 0x0d);
+
+ crtc->v_retrace_start_0_7 = GetCrtc (sisc, 0x10);
+ crtc->_v_retrace_end = GetCrtc (sisc, 0x11);
+ crtc->v_display_end_0_7 = GetCrtc (sisc, 0x12);
+ crtc->screen_off_0_7 = GetCrtc (sisc, 0x13);
+ crtc->_underline_location = GetCrtc (sisc, 0x14);
+ crtc->v_blank_start_0_7 = GetCrtc (sisc, 0x15);
+ crtc->v_blank_end_0_7 = GetCrtc (sisc, 0x16);
+ crtc->crtc_mode = GetCrtc (sisc, 0x17);
+
+ crtc->line_compare_0_7 = GetCrtc (sisc, 0x18);
+
+ crtc->mode_control = GetArtc (sisc, 0x10);
+ crtc->screen_border_color = GetArtc (sisc, 0x11);
+ crtc->enable_color_plane = GetArtc (sisc, 0x12);
+ crtc->horizontal_pixel_pan = GetArtc (sisc, 0x13);
+
+ crtc->mode_register = GetGrtc (sisc, 0x5);
+
+ crtc->clock_mode = GetSrtc (sisc, 0x1);
+
+ crtc->graphics_mode = GetSrtc (sisc, 0x6);
+ crtc->misc_control_0 = GetSrtc (sisc, 0x7);
+ crtc->crt_cpu_threshold_control_0 = GetSrtc (sisc, 0x8);
+ crtc->crt_cpu_threshold_control_1 = GetSrtc (sisc, 0x9);
+ crtc->extended_crt_overflow = GetSrtc (sisc, 0xa);
+ crtc->misc_control_1 = GetSrtc (sisc, 0xb);
+ crtc->misc_control_2 = GetSrtc (sisc, 0xc);
+
+ crtc->ddc_and_power_control = GetSrtc (sisc, 0x11);
+ crtc->extended_horizontal_overflow = GetSrtc (sisc, 0x12);
+ crtc->extended_clock_generator = GetSrtc (sisc, 0x13);
+ crtc->cursor_0_red = GetSrtc (sisc, 0x14);
+ crtc->cursor_0_green = GetSrtc (sisc, 0x15);
+ crtc->cursor_0_blue = GetSrtc (sisc, 0x16);
+ crtc->cursor_1_red = GetSrtc (sisc, 0x17);
+ crtc->cursor_1_green = GetSrtc (sisc, 0x18);
+ crtc->cursor_1_blue = GetSrtc (sisc, 0x19);
+ crtc->cursor_h_start_0_7 = GetSrtc (sisc, 0x1a);
+ crtc->cursor_h_start_1 = GetSrtc (sisc, 0x1b);
+ crtc->cursor_h_preset_0_5 = GetSrtc (sisc, 0x1c);
+ crtc->cursor_v_start_0_7 = GetSrtc (sisc, 0x1d);
+ crtc->cursor_v_start_1 = GetSrtc (sisc, 0x1e);
+ crtc->cursor_v_preset_0_5 = GetSrtc (sisc, 0x1f);
+ crtc->linear_base_19_26 = GetSrtc (sisc, 0x20);
+ crtc->linear_base_1 = GetSrtc (sisc, 0x21);
+
+ crtc->graphics_engine_0 = GetSrtc (sisc, 0x26);
+ crtc->graphics_engine_1 = GetSrtc (sisc, 0x27);
+ crtc->internal_mclk_0 = GetSrtc (sisc, 0x28);
+ crtc->internal_mclk_1 = GetSrtc (sisc, 0x29);
+ crtc->internal_vclk_0 = GetSrtc (sisc, 0x2A);
+ crtc->internal_vclk_1 = GetSrtc (sisc, 0x2B);
+
+ crtc->misc_control_7 = GetSrtc (sisc, 0x38);
+
+ crtc->misc_control_11 = GetSrtc (sisc, 0x3E);
+ crtc->misc_control_12 = GetSrtc (sisc, 0x3F);
+}
+
+static void
+_sisSetBlank (SisCardInfo *sisc, Bool blank)
+{
+ CARD8 clock;
+
+ clock = GetSrtc (sisc, 0x01);
+ if (blank)
+ clock |= 0x20;
+ else
+ clock &= ~0x20;
+ PutSrtc (sisc, 0x01, clock);
+}
+
+static void
+_sisSetCrtc (SisCardInfo *sisc, SisCrtc *crtc)
+{
+ _sisOutb(crtc->misc_output, sisc->io_base+0x4c);
+ _sisSetBlank (sisc, TRUE);
+ PutCrtc (sisc, 0x00, crtc->h_total_0_7);
+ PutCrtc (sisc, 0x01, crtc->h_display_end_0_7);
+ PutCrtc (sisc, 0x02, crtc->h_blank_start_0_7);
+ PutCrtc (sisc, 0x03, crtc->_h_blank_end);
+ PutCrtc (sisc, 0x04, crtc->h_sync_start_0_7);
+ PutCrtc (sisc, 0x05, crtc->_h_sync_end);
+ PutCrtc (sisc, 0x06, crtc->v_total_0_7);
+ PutCrtc (sisc, 0x07, crtc->crtc_overflow);
+ PutCrtc (sisc, 0x08, crtc->preset_row_scan);
+ PutCrtc (sisc, 0x09, crtc->_max_scan_line);
+
+ PutCrtc (sisc, 0x0c, crtc->start_address_8_15);
+ PutCrtc (sisc, 0x0d, crtc->start_address_0_7);
+
+ PutCrtc (sisc, 0x10, crtc->v_retrace_start_0_7);
+ PutCrtc (sisc, 0x11, crtc->_v_retrace_end);
+ PutCrtc (sisc, 0x12, crtc->v_display_end_0_7);
+ PutCrtc (sisc, 0x13, crtc->screen_off_0_7);
+ PutCrtc (sisc, 0x14, crtc->_underline_location);
+ PutCrtc (sisc, 0x15, crtc->v_blank_start_0_7);
+ PutCrtc (sisc, 0x16, crtc->v_blank_end_0_7);
+ PutCrtc (sisc, 0x17, crtc->crtc_mode);
+ PutCrtc (sisc, 0x18, crtc->line_compare_0_7);
+
+ PutArtc (sisc, 0x10, crtc->mode_control);
+ PutArtc (sisc, 0x11, crtc->screen_border_color);
+ PutArtc (sisc, 0x12, crtc->enable_color_plane);
+ PutArtc (sisc, 0x13, crtc->horizontal_pixel_pan);
+
+ PutGrtc (sisc, 0x5, crtc->mode_register);
+
+ PutSrtc (sisc, 0x1, crtc->clock_mode | 0x20);
+
+ PutSrtc (sisc, 0x6, crtc->graphics_mode);
+ PutSrtc (sisc, 0x7, crtc->misc_control_0);
+ PutSrtc (sisc, 0x8, crtc->crt_cpu_threshold_control_0);
+ PutSrtc (sisc, 0x9, crtc->crt_cpu_threshold_control_1);
+ PutSrtc (sisc, 0xa, crtc->extended_crt_overflow);
+ PutSrtc (sisc, 0xb, crtc->misc_control_1);
+ PutSrtc (sisc, 0xc, crtc->misc_control_2);
+
+ PutSrtc (sisc, 0x11, crtc->ddc_and_power_control);
+ PutSrtc (sisc, 0x12, crtc->extended_horizontal_overflow);
+ PutSrtc (sisc, 0x13, crtc->extended_clock_generator);
+ PutSrtc (sisc, 0x14, crtc->cursor_0_red);
+ PutSrtc (sisc, 0x15, crtc->cursor_0_green);
+ PutSrtc (sisc, 0x16, crtc->cursor_0_blue);
+ PutSrtc (sisc, 0x17, crtc->cursor_1_red);
+ PutSrtc (sisc, 0x18, crtc->cursor_1_green);
+ PutSrtc (sisc, 0x19, crtc->cursor_1_blue);
+ PutSrtc (sisc, 0x1a, crtc->cursor_h_start_0_7);
+ PutSrtc (sisc, 0x1b, crtc->cursor_h_start_1);
+ PutSrtc (sisc, 0x1c, crtc->cursor_h_preset_0_5);
+ PutSrtc (sisc, 0x1d, crtc->cursor_v_start_0_7);
+ PutSrtc (sisc, 0x1e, crtc->cursor_v_start_1);
+ PutSrtc (sisc, 0x1f, crtc->cursor_v_preset_0_5);
+ PutSrtc (sisc, 0x20, crtc->linear_base_19_26);
+ PutSrtc (sisc, 0x21, crtc->linear_base_1);
+
+ PutSrtc (sisc, 0x26, crtc->graphics_engine_0);
+ PutSrtc (sisc, 0x27, crtc->graphics_engine_1);
+ PutSrtc (sisc, 0x28, crtc->internal_mclk_0);
+ PutSrtc (sisc, 0x29, crtc->internal_mclk_1);
+ PutSrtc (sisc, 0x2A, crtc->internal_vclk_0);
+ PutSrtc (sisc, 0x2B, crtc->internal_vclk_1);
+
+ PutSrtc (sisc, 0x38, crtc->misc_control_7);
+
+ PutSrtc (sisc, 0x3E, crtc->misc_control_11);
+ PutSrtc (sisc, 0x3F, crtc->misc_control_12);
+
+ _sisSetBlank (sisc, FALSE);
+}
+
+CARD8
+_sisReadIndexRegister (CARD32 base, CARD8 index)
+{
+ CARD8 ret;
+
+ _sisOutb (index, base);
+ ret = _sisInb (base+1);
+ return ret;
+}
+
+void
+_sisWriteIndexRegister (CARD32 base, CARD8 index, CARD8 value)
+{
+ _sisOutb (index, base);
+ _sisOutb (value, base+1);
+}
+
+void
+sisPreserve (KdCardInfo *card)
+{
+ SisCardInfo *sisc = card->driver;
+ CARD8 *r = sisc->registers;
+ int a, i, l;
+ CARD8 line[16];
+ CARD8 prev[16];
+ BOOL gotone;
+
+ sisc->save.sr5 = GetSrtc(sisc,0x5);
+ if (sisc->save.sr5 != 0x21)
+ sisc->save.sr5 = 0x86;
+ /* unlock extension registers */
+ PutSrtc(sisc,0x5,0x86);
+
+ /* enable MMIO access to registers */
+ sisc->save.srb = GetSrtc(sisc,0xb);
+ PutSrtc(sisc, 0xb, sisc->save.srb | 0x60);
+ _sisGetCrtc (sisc, &sisc->save.crtc);
+}
+
+void
+sisEnable (ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ KdCardInfo *card = pScreenPriv->card;
+ SisCardInfo *sisc = card->driver;
+ SisScreenInfo *siss = screen->driver;
+ SisTiming *t;
+ SisCrtc crtc;
+ unsigned long pixel;
+
+ int hactive;
+ int hblank;
+ int hfp;
+ int hbp;
+
+ int vactive;
+ int vblank;
+ int vfp;
+ int vbp;
+
+ int h_total;
+ int h_display_end;
+ int h_blank_start;
+ int h_blank_end;
+ int h_sync_start;
+ int h_sync_end;
+ int h_screen_off;
+
+ int h_adjust;
+
+ int v_total;
+ int v_retrace_start;
+ int v_retrace_end;
+ int v_display_end;
+ int v_blank_start;
+ int v_blank_end;
+
+ crtc = sisc->save.crtc;
+
+ t = sisGetTiming (screen->width, screen->height, screen->rate);
+
+ /* CR11 */
+ crtc.disable_v_retrace_int = 1;
+
+ /* 3CC/3C2 */
+ crtc.io_address_select = 1;
+ crtc.display_ram_enable = 1;
+ crtc.clock_select = 3;
+
+ /* SR6 */
+ crtc.graphics_mode = 0;
+ crtc.graphics_mode_linear = 1;
+ crtc.enhanced_graphics_mode = 1;
+
+ /* SRB */
+ crtc.cpu_bitblt_enable = 1;
+ crtc.memory_mapped_mode = 3;
+
+ /* SRC */
+ crtc.graphics_mode_32bit_enable = 1;
+ crtc.text_mode_16bit_enable = 0;
+ crtc.read_ahead_enable = 1;
+
+ /* SR11 */
+ crtc.acpi_enable = 0;
+ crtc.kbd_cursor_activate = 0;
+ crtc.video_memory_activate = 0;
+ crtc.vga_standby = 0;
+ crtc.vga_suspend = 0;
+
+ /* AR10 */
+ crtc.mode_control = 0;
+ crtc.graphics_mode_enable = 1;
+ /* AR11 */
+ crtc.screen_border_color = 0;
+ /* AR12 */
+ crtc.enable_color_plane = 0xf;
+ /* AR13 */
+ crtc.horizontal_pixel_pan = 0;
+
+ /* SR27 */
+ crtc.logical_screen_width = 3;
+ crtc.graphics_prog_enable = 1;
+
+ /* SR38 */
+ crtc.extended_clock_select = 0;
+
+ if (siss->cursor_base)
+ {
+ crtc_set_cursor_start_addr (&crtc, siss->cursor_off);
+ crtc.graphics_mode_hw_cursor = 0;
+ }
+
+ hactive = t->horizontal;
+ hblank = t->hblank;
+ hbp = t->hbp;
+ hfp = t->hfp;
+
+ vactive = t->vertical;
+ vblank = t->vblank;
+ vbp = t->vbp;
+ vfp = t->vfp;
+
+ pixel = (hactive + hblank) * (vactive + vblank) * t->rate;
+
+ switch (screen->bitsPerPixel) {
+ case 8:
+ hactive /= 8;
+ hblank /= 8;
+ hfp /= 8;
+ hbp /= 8;
+
+ crtc.color_mode_256 = 1;
+ h_screen_off = hactive;
+ h_adjust = 1;
+
+ break;
+ case 16:
+ hactive /= 8;
+ hblank /= 8;
+ hfp /= 8;
+ hbp /= 8;
+
+ h_screen_off = hactive * 2;
+ h_adjust = 1;
+
+ crtc.color_mode_256 = 0;
+
+ if (screen->depth == 15)
+ crtc.graphics_mode_32k = 1;
+ else
+ crtc.graphics_mode_64k = 1;
+ break;
+ case 24:
+ hactive /= 8;
+ hblank /= 8;
+ hfp /= 8;
+ hbp /= 8;
+
+ h_screen_off = hactive * 3;
+ h_adjust = 1;
+
+ crtc.color_mode_256 = 0;
+
+ /* SR6 */
+ crtc.graphics_mode_true = 1;
+ /* SR7 */
+ crtc.direct_color_24bit = 0;
+ /* SR9 */
+ crtc.true_color_32bpp = 0;
+ /* SRB */
+ crtc.true_color_order = 1;
+ break;
+ case 32:
+ hactive /= 8;
+ hblank /= 8;
+ hfp /= 8;
+ hbp /= 8;
+
+ h_screen_off = hactive * 4;
+ h_adjust = 1;
+
+ crtc.color_mode_256 = 0;
+
+ /* SR6 */
+ crtc.graphics_mode_true = 1;
+ /* SR7 */
+ crtc.direct_color_24bit = 0;
+ /* SR9 */
+ crtc.true_color_32bpp = 1;
+ /* SRB */
+ crtc.true_color_order = 1;
+ break;
+ }
+
+ sisGetClock (pixel, &crtc);
+
+ crtc.high_speed_dac_0 = crtc.high_speed_dac_1 = pixel > 135000000;
+
+ sisEngThresh (&crtc, pixel, screen->bitsPerPixel);
+
+ /*
+ * Compute horizontal register values from timings
+ */
+ h_total = hactive + hblank - 5;
+ h_display_end = hactive - 1;
+ h_blank_start = h_display_end;
+ h_blank_end = h_blank_start + hblank;
+
+ h_sync_start = hactive + hfp + h_adjust;
+ h_sync_end = h_sync_start + hblank - hbp - hfp;
+
+ crtc_set_h_total(&crtc, h_total);
+ crtc_set_h_display_end (&crtc, h_display_end);
+ crtc_set_h_blank_start (&crtc, h_blank_start);
+ crtc_set_h_blank_end (&crtc, h_blank_end);
+ crtc_set_h_sync_start (&crtc, h_sync_start);
+ crtc_set_h_sync_end (&crtc, h_sync_end);
+ crtc_set_screen_off (&crtc, h_screen_off);
+
+ v_total = vactive + vblank - 2;
+ v_retrace_start = vactive + vfp - 1;
+ v_retrace_end = v_retrace_start + vblank - vbp - vfp;
+ v_display_end = vactive - 1;
+ v_blank_start = vactive - 1;
+ v_blank_end = v_blank_start + vblank /* - 1 */;
+
+ crtc_set_v_total(&crtc, v_total);
+ crtc_set_v_retrace_start (&crtc, v_retrace_start);
+ crtc.v_retrace_end_0_3 = v_retrace_end;
+ crtc_set_v_display_end (&crtc, v_display_end);
+ crtc_set_v_blank_start (&crtc, v_blank_start);
+ crtc.v_blank_end_0_7 = v_blank_end;
+
+ _sisSetCrtc (sisc, &crtc);
+}
+
+Bool
+sisDPMS (ScreenPtr pScreen, int mode)
+{
+ KdScreenPriv(pScreen);
+ sisCardInfo(pScreenPriv);
+ union ddc_and_power_control_u _ddc_and_power_control_u;
+
+ ddc_and_power_control = sisc->save.crtc.ddc_and_power_control;
+
+ kbd_cursor_activate = 0;
+ video_memory_activate = 0;
+ vga_standby = 0;
+ vga_suspend = 0;
+ acpi_enable = 0;
+ switch (mode) {
+ case KD_DPMS_NORMAL:
+ break;
+ case KD_DPMS_STANDBY:
+ vga_standby = 1;
+ break;
+ case KD_DPMS_SUSPEND:
+ vga_suspend = 1;
+ break;
+ case KD_DPMS_POWERDOWN:
+ acpi_enable = 1;
+ break;
+ }
+ PutSrtc (sisc, 0x11, ddc_and_power_control);
+ return TRUE;
+}
+
+void
+sisDisable (ScreenPtr pScreen)
+{
+}
+
+void
+sisRestore (KdCardInfo *card)
+{
+ SisCardInfo *sisc = (SisCardInfo *) card->driver;
+
+ _sisSetCrtc (sisc, &sisc->save.crtc);
+ PutSrtc (sisc, 0xb, sisc->save.srb);
+ PutSrtc (sisc, 0x5, sisc->save.sr5);
+}
+
+void
+sisScreenFini (KdScreenInfo *screen)
+{
+ SisScreenInfo *siss = (SisScreenInfo *) screen->driver;
+
+ xfree (siss);
+ screen->driver = 0;
+}
+
+void
+sisCardFini (KdCardInfo *card)
+{
+ SisCardInfo *sisc = (SisCardInfo *) card->driver;
+
+ KdUnmapDevice (sisc->frameBuffer, sisc->memory);
+ KdUnmapDevice (sisc->registers, sizeof (SisRec));
+ ioperm (sisc->io_base, 0x80, 0);
+}
+
+KdCardFuncs sisFuncs = {
+ sisCardInit,
+ sisScreenInit,
+ sisPreserve,
+ sisEnable,
+ sisDPMS,
+ sisDisable,
+ sisRestore,
+ sisScreenFini,
+ sisCardFini,
+ sisCursorInit,
+ sisCursorEnable,
+ sisCursorDisable,
+ sisCursorFini,
+ 0,
+ sisDrawInit,
+ sisDrawEnable,
+ sisDrawDisable,
+ sisDrawFini,
+ sisGetColors,
+ sisPutColors,
+};
diff --git a/hw/kdrive/sis530/sis.h b/hw/kdrive/sis530/sis.h
new file mode 100644
index 000000000..4e19ef62b
--- /dev/null
+++ b/hw/kdrive/sis530/sis.h
@@ -0,0 +1,1152 @@
+/*
+ * $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: $ */
+
+#ifndef _SIS_H_
+#define _SIS_H_
+#include "kdrive.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <asm/io.h>
+#include <stdio.h>
+
+/*
+ * Linear Addressing 000 0000 - 0ff ffff (16m)
+ * Image data transfer 100 0000 - 100 7fff (32k)
+ * Empty 100 8000 - 100 81ff
+ * MMIO registers 100 8200 - 100 8480
+ *
+ * We don't care about the image transfer or PCI regs, so
+ * this structure starts at the MMIO regs
+ */
+
+typedef volatile CARD32 VOL32;
+typedef volatile CARD16 VOL16;
+typedef volatile CARD8 VOL8;
+
+#define SIS_MMIO_OFFSET 0x8200
+
+typedef struct _sis530General {
+ VOL32 src_base; /* 8200 */
+ VOL16 src_pitch; /* 8204 */
+ VOL16 _pad0; /* 8206 */
+ VOL16 src_y; /* 8208 */
+ VOL16 src_x; /* 820a */
+ VOL16 dst_y; /* 820c */
+ VOL16 dst_x; /* 820e */
+ VOL32 dst_base; /* 8210 */
+ VOL16 dst_pitch; /* 8214 */
+ VOL16 dst_height; /* 8216 */
+ VOL16 rect_width; /* 8218 */
+ VOL16 rect_height; /* 821a */
+ VOL32 pattern_fg; /* 821c */
+ VOL32 pattern_bg; /* 8220 */
+ VOL32 src_fg; /* 8224 */
+ VOL32 src_bg; /* 8228 */
+ VOL8 mask[8]; /* 822c */
+ VOL16 clip_left; /* 8234 */
+ VOL16 clip_top; /* 8236 */
+ VOL16 clip_right; /* 8238 */
+ VOL16 clip_bottom; /* 823a */
+ VOL32 command; /* 823c */
+ VOL32 status; /* 8240 */
+ VOL8 _pad1[0xbc]; /* 8244 */
+ VOL8 pattern[256]; /* 8300 */
+ /* 8400 */
+} SisGeneral;
+
+typedef struct _sis530Line {
+ VOL8 _pad0[8]; /* 8200 */
+ VOL16 x0; /* 8208 */
+ VOL16 y0; /* 820a */
+ VOL16 x1; /* 820c */
+ VOL16 y1; /* 820e */
+ VOL32 dst_base; /* 8210 */
+ VOL16 dst_pitch; /* 8214 */
+ VOL16 dst_height; /* 8216 */
+ VOL16 count; /* 8218 */
+ VOL16 style_period; /* 821a */
+ VOL32 fg; /* 821c */
+ VOL32 bg; /* 8220 */
+ VOL8 _pad1[8]; /* 8224 */
+ VOL32 style0; /* 822c */
+ VOL32 style1; /* 8228 */
+ VOL16 clip_left; /* 8234 */
+ VOL16 clip_top; /* 8236 */
+ VOL16 clip_right; /* 8238 */
+ VOL16 clip_bottom; /* 823a */
+ VOL32 command; /* 823c */
+ VOL32 status; /* 8240 */
+ VOL8 _pad2[0xbc]; /* 8244 */
+ struct {
+ VOL16 x;
+ VOL16 y;
+ } data[96]; /* 8300 */
+ /* 8480 */
+} SisLine;
+
+typedef struct _sis530Transparent {
+ VOL32 src_base; /* 8200 */
+ VOL16 src_pitch; /* 8204 */
+ VOL16 _pad0; /* 8206 */
+ VOL16 src_y; /* 8208 */
+ VOL16 src_x; /* 820a */
+ VOL16 dst_y; /* 820c */
+ VOL16 dst_x; /* 820e */
+ VOL32 dst_base; /* 8210 */
+ VOL16 dst_pitch; /* 8214 */
+ VOL16 dst_height; /* 8216 */
+ VOL16 rect_width; /* 8218 */
+ VOL16 rect_height; /* 821a */
+ VOL32 dst_key_high; /* 821c */
+ VOL32 dst_key_low; /* 8220 */
+ VOL32 src_key_high; /* 8224 */
+ VOL32 src_key_low; /* 8228 */
+ VOL8 _pad1[8]; /* 822c */
+ VOL16 clip_left; /* 8234 */
+ VOL16 clip_top; /* 8236 */
+ VOL16 clip_right; /* 8238 */
+ VOL16 clip_bottom; /* 823a */
+ VOL32 command; /* 823c */
+ VOL32 status; /* 8240 */
+ /* 8244 */
+} SisTransparent;
+
+typedef struct _sis530Multiple {
+ VOL8 _pad0[8]; /* 8200 */
+ VOL16 count; /* 8208 */
+ VOL16 y; /* 820a */
+ VOL16 x0_start; /* 820c */
+ VOL16 x0_end; /* 820e */
+ VOL32 dst_base; /* 8210 */
+ VOL16 dst_pitch; /* 8214 */
+ VOL16 dst_height; /* 8216 */
+ VOL8 _pad1[4]; /* 8218 */
+ VOL32 fg; /* 821c */
+ VOL32 bg; /* 8220 */
+ VOL8 _pad2[8]; /* 8224 */
+ VOL8 mask[8]; /* 822c */
+ VOL16 clip_left; /* 8234 */
+ VOL16 clip_top; /* 8236 */
+ VOL16 clip_right; /* 8238 */
+ VOL16 clip_bottom; /* 823a */
+ VOL32 command; /* 823c */
+ VOL32 status; /* 8240 */
+ VOL16 x1_start; /* 8244 */
+ VOL16 x1_end; /* 8246 */
+ VOL8 _pad3[0xb8]; /* 8248 */
+ VOL8 pattern[64]; /* 8300 */
+ struct {
+ VOL16 x_start;
+ VOL16 y_end;
+ } data[80]; /* 8340 */
+ /* 8480 */
+} SisMultiple;
+
+typedef struct _sis530Trapezoid {
+ VOL8 _pad0[8]; /* 8200 */
+ VOL16 height; /* 8208 */
+ VOL16 y; /* 820a */
+ VOL16 left_x; /* 820c */
+ VOL16 right_x; /* 820e */
+ VOL32 dst_base; /* 8210 */
+ VOL16 dst_pitch; /* 8214 */
+ VOL16 dst_height; /* 8216 */
+ VOL8 _pad1[4]; /* 8218 */
+ VOL32 fg; /* 821c */
+ VOL32 bg; /* 8220 */
+ VOL8 _pad2[8]; /* 8224 */
+ VOL8 mask[8]; /* 822c */
+ VOL16 clip_left; /* 8234 */
+ VOL16 clip_top; /* 8236 */
+ VOL16 clip_right; /* 8238 */
+ VOL16 clip_bottom; /* 823a */
+ VOL32 command; /* 823c */
+ VOL32 status; /* 8240 */
+ VOL16 left_dx; /* 8244 */
+ VOL16 left_dy; /* 8246 */
+ VOL16 right_dx; /* 8248 */
+ VOL16 right_dy; /* 824a */
+ VOL32 left_error; /* 824c */
+ VOL32 right_error; /* 8250 */
+ /* 8254 */
+} SisTrapezoid;
+
+typedef struct _sis530 {
+ union {
+ SisGeneral general;
+ SisLine line;
+ SisTransparent transparent;
+ SisMultiple multiple;
+ SisTrapezoid trapezoid;
+ } u;
+} SisRec, *SisPtr;
+
+typedef struct _sisCursor {
+ int width, height;
+ int xhot, yhot;
+ Bool has_cursor;
+ CursorPtr pCursor;
+} SisCursor;
+
+#define SIS_CURSOR_WIDTH 64
+#define SIS_CURSOR_HEIGHT 64
+
+typedef struct _sisClock {
+ CARD32 vclk_numerator;
+ BOOL vclk_divide_by_2;
+ CARD32 vclk_denominator;
+ CARD32 vclk_post_scale;
+ BOOL vclk_post_scale_2;
+ BOOL high_speed_dac;
+} SisClockRec, *SisClockPtr;
+
+typedef struct _crtc {
+
+ union {
+ struct {
+ CARD8 _io_address_select : 1;
+ CARD8 _display_ram_enable : 1;
+ CARD8 _clock_select : 2;
+ CARD8 : 1;
+ CARD8 _odd_even_page : 1;
+ CARD8 _h_sync_polarity : 1;
+ CARD8 _v_sync_polarity : 1;
+ } _misc_output_s;
+ CARD8 _misc_output;
+ } _misc_output_u; /* 3CC/3C2 */
+
+#define misc_output _misc_output_u._misc_output
+#define io_address_select _misc_output_u._misc_output_s._io_address_select
+#define display_ram_enable _misc_output_u._misc_output_s._display_ram_enable
+#define clock_select _misc_output_u._misc_output_s._clock_select
+#define odd_even_page _misc_output_u._misc_output_s._odd_even_page
+#define h_sync_polarity _misc_output_u._misc_output_s._h_sync_polarity
+#define v_sync_polarity _misc_output_u._misc_output_s._v_sync_polarity
+
+ CARD8 h_total_0_7; /* CR0 */
+ CARD8 h_display_end_0_7; /* CR1 */
+ CARD8 h_blank_start_0_7; /* CR2 */
+ union {
+ struct {
+ CARD8 _h_blank_end_0_4 : 5;
+ CARD8 _display_skew : 2;
+ CARD8 : 1;
+ } _h_blank_end_s;
+ CARD8 __h_blank_end; /* CR3 */
+ } _h_blank_end_u;
+#define h_blank_end_0_4 _h_blank_end_u._h_blank_end_s._h_blank_end_0_4
+#define display_skew _h_blank_end_u._h_blank_end_s._display_skew
+#define _h_blank_end _h_blank_end_u.__h_blank_end
+
+ CARD8 h_sync_start_0_7; /* CR4 */
+
+ union {
+ struct {
+ CARD8 _h_sync_end_0_4 : 5;
+ CARD8 _horizontal_skew : 2;
+ CARD8 _h_blank_end_5 : 1;
+ } _h_sync_end_s;
+ CARD8 __h_sync_end; /* CR5 */
+ } _h_sync_end_u;
+
+#define h_sync_end_0_4 _h_sync_end_u._h_sync_end_s._h_sync_end_0_4
+#define horizontal_skew _h_sync_end_u._h_sync_end_s._horizontal_skew
+#define h_blank_end_5 _h_sync_end_u._h_sync_end_s._h_blank_end_5
+#define _h_sync_end _h_sync_end_u.__h_sync_end
+
+ CARD8 v_total_0_7; /* CR6 */
+
+ union {
+ struct {
+ CARD8 _v_total_8 : 1;
+ CARD8 _v_display_end_8 : 1;
+ CARD8 _v_retrace_start_8 : 1;
+ CARD8 _v_blank_start_8 : 1;
+ CARD8 _line_compare_8 : 1;
+ CARD8 _v_total_9 : 1;
+ CARD8 _v_display_end_9 : 1;
+ CARD8 _v_retrace_start_9 : 1;
+ } _crtc_overflow_s;
+ CARD8 _crtc_overflow; /* CR7 */
+ } _crtc_overflow_u;
+
+#define v_total_8 _crtc_overflow_u._crtc_overflow_s._v_total_8
+#define v_display_end_8 _crtc_overflow_u._crtc_overflow_s._v_display_end_8
+#define v_retrace_start_8 _crtc_overflow_u._crtc_overflow_s._v_retrace_start_8
+#define v_blank_start_8 _crtc_overflow_u._crtc_overflow_s._v_blank_start_8
+#define line_compare_8 _crtc_overflow_u._crtc_overflow_s._line_compare_8
+#define v_total_9 _crtc_overflow_u._crtc_overflow_s._v_total_9
+#define v_display_end_9 _crtc_overflow_u._crtc_overflow_s._v_display_end_9
+#define v_retrace_start_9 _crtc_overflow_u._crtc_overflow_s._v_retrace_start_9
+#define crtc_overflow _crtc_overflow_u._crtc_overflow
+
+ CARD8 preset_row_scan; /* CR8 (unused) */
+
+ union {
+ struct {
+ CARD8 _max_scan_line : 5;
+ CARD8 _v_blank_start_9 : 1;
+ CARD8 _line_compare_9 : 1;
+ CARD8 _double_scan : 1;
+ } _max_scan_line_s;
+ CARD8 __max_scan_line; /* CR9 */
+ } _max_scan_line_u;
+
+#define max_scan_line _max_scan_line_u._max_scan_line_s._max_scan_line
+#define v_blank_start_9 _max_scan_line_u._max_scan_line_s._v_blank_start_9
+#define line_compare_9 _max_scan_line_u._max_scan_line_s._line_compare_9
+#define double_scan _max_scan_line_u._max_scan_line_s._double_scan
+#define _max_scan_line _max_scan_line_u.__max_scan_line
+
+ CARD8 cursor_start;
+ CARD8 cursor_end;
+
+ CARD8 start_address_8_15; /* CRC */
+ CARD8 start_address_0_7; /* CRD */
+
+ CARD8 cursor_loc_high;
+ CARD8 cursor_loc_low;
+
+ CARD8 v_retrace_start_0_7; /* CR10 */
+ union {
+ struct {
+ CARD8 _v_retrace_end_0_3 : 4;
+ CARD8 _clear_v_retrace_int : 1;
+ CARD8 _disable_v_retrace_int : 1;
+ CARD8 _refresh_cycle_select : 1;
+ CARD8 _lock_crtc : 1;
+ } _v_retrace_end_s;
+ CARD8 __v_retrace_end; /* CR11 */
+ } _v_retrace_end_u;
+
+#define v_retrace_end_0_3 _v_retrace_end_u._v_retrace_end_s._v_retrace_end_0_3
+#define clear_v_retrace_int _v_retrace_end_u._v_retrace_end_s._clear_v_retrace_int
+#define disable_v_retrace_int _v_retrace_end_u._v_retrace_end_s._disable_v_retrace_int
+#define refresh_cycle_select _v_retrace_end_u._v_retrace_end_s._refresh_cycle_select
+#define lock_crtc _v_retrace_end_u._v_retrace_end_s._lock_crtc
+#define _v_retrace_end _v_retrace_end_u.__v_retrace_end
+
+ CARD8 v_display_end_0_7; /* CR12 */
+
+ CARD8 screen_off_0_7; /* CR13 */
+
+ union {
+ struct {
+ CARD8 _underline_location : 5;
+ CARD8 _count_by_four : 1;
+ CARD8 _doubleword_mode : 1;
+ CARD8 : 1;
+ } _underline_location_s;
+ CARD8 __underline_location; /* CR14 */
+ } _underline_location_u;
+
+#define underline_location _underline_location_u._underline_location_s._underline_location
+#define count_by_four _underline_location_u._underline_location_s._count_by_four
+#define doubleword_mode _underline_location_u._underline_location_s._doubleword_mode
+#define _underline_location _underline_location_u.__underline_location
+
+ CARD8 v_blank_start_0_7; /* CR15 */
+ CARD8 v_blank_end_0_7; /* CR16 */
+
+ union {
+ struct {
+ CARD8 _two_bk_cga : 1;
+ CARD8 _four_bk_cga : 1;
+ CARD8 _v_total_double : 1;
+ CARD8 _count_by_two : 1;
+ CARD8 : 1;
+ CARD8 _address_wrap : 1;
+ CARD8 _byte_mode : 1;
+ CARD8 _hardware_reset : 1;
+ } _crtc_mode_s;
+ CARD8 _crtc_mode; /* CR17 */
+ } _crtc_mode_u;
+
+#define crtc_mode _crtc_mode_u._crtc_mode
+#define two_bk_cga _crtc_mode_u._crtc_mode_s._two_bk_cga
+#define four_bk_cga _crtc_mode_u._crtc_mode_s._four_bk_cga
+#define v_total_double _crtc_mode_u._crtc_mode_s._v_total_double
+#define count_by_two _crtc_mode_u._crtc_mode_s._count_by_two
+#define address_wrap _crtc_mode_u._crtc_mode_s._address_wrap
+#define byte_mode _crtc_mode_u._crtc_mode_s._byte_mode
+#define hardware_reset _crtc_mode_u._crtc_mode_s._hardware_reset
+
+ CARD8 line_compare_0_7; /* CR18 (unused) */
+
+ union {
+ struct {
+ CARD8 _graphics_mode_enable : 1;
+ CARD8 _attribute_byte_mda : 1;
+ CARD8 _line_graphics_enable : 1;
+ CARD8 _background_blink : 1;
+ CARD8 : 1;
+ CARD8 _pel_panning_compat : 1;
+ CARD8 _pixel_clock_double : 1;
+ CARD8 p4_p5_source_select : 1;
+ } _mode_control_s;
+ CARD8 _mode_control;
+ } _mode_control_u; /* AR10 */
+
+#define mode_control _mode_control_u._mode_control
+#define graphics_mode_enable _mode_control_u._mode_control_s._graphics_mode_enable
+#define pixel_clock_double _mode_control_u._mode_control_s._pixel_clock_double
+
+ CARD8 screen_border_color; /* AR11 */
+ CARD8 enable_color_plane; /* AR12 */
+ CARD8 horizontal_pixel_pan; /* AR13 */
+
+ union {
+ struct {
+ CARD8 _write_mode : 2;
+ CARD8 : 1;
+ CARD8 _read_mode : 1;
+ CARD8 _odd_even_addressing : 1;
+ CARD8 _shift_register_mode : 1;
+ CARD8 _color_mode_256 : 1;
+ CARD8 : 1;
+ } _mode_register_s;
+ CARD8 _mode_register;
+ } _mode_register_u; /* GR5 */
+
+#define mode_register _mode_register_u._mode_register
+#define color_mode_256 _mode_register_u._mode_register_s._color_mode_256
+
+ union {
+ struct {
+ CARD8 _dot_clock_8_9 : 1;
+ CARD8 : 1;
+ CARD8 _shifter_load_16 : 1;
+ CARD8 _dot_clock_divide_2 : 1;
+ CARD8 _shifter_load_32 : 1;
+ CARD8 _display_off : 1;
+ CARD8 : 2;
+ } _clock_mode_s;
+ CARD8 _clock_mode;
+ } _clock_mode_u; /* SR1 */
+
+#define clock_mode _clock_mode_u._clock_mode
+#define dot_clock_8_9 _clock_mode_u._clock_mode_s._dot_clock_8_9
+#define shifter_load_16 _clock_mode_u._clock_mode_s._shifter_load_16
+#define dot_clock_divide_2 _clock_mode_u._clock_mode_s._dot_clock_divide_2
+#define shifter_load_32 _clock_mode_u._clock_mode_s._shifter_load_32
+#define display_off _clock_mode_u._clock_mode_s._display_off
+
+ union {
+ struct {
+ CARD8 _enhanced_text_mode : 1;
+ CARD8 _enhanced_graphics_mode : 1;
+ CARD8 _graphics_mode_32k : 1;
+ CARD8 _graphics_mode_64k : 1;
+ CARD8 _graphics_mode_true : 1;
+ CARD8 _graphics_mode_interlaced: 1;
+ CARD8 _graphics_mode_hw_cursor: 1;
+ CARD8 _graphics_mode_linear : 1;
+ } _graphics_mode_s;
+ CARD8 _graphics_mode;
+ } _graphics_mode_u; /* SR6 */
+
+#define graphics_mode _graphics_mode_u._graphics_mode
+#define enhanced_text_mode _graphics_mode_u._graphics_mode_s._enhanced_text_mode
+#define enhanced_graphics_mode _graphics_mode_u._graphics_mode_s._enhanced_graphics_mode
+#define graphics_mode_32k _graphics_mode_u._graphics_mode_s._graphics_mode_32k
+#define graphics_mode_64k _graphics_mode_u._graphics_mode_s._graphics_mode_64k
+#define graphics_mode_true _graphics_mode_u._graphics_mode_s._graphics_mode_true
+#define graphics_mode_interlaced _graphics_mode_u._graphics_mode_s._graphics_mode_interlaced
+#define graphics_mode_hw_cursor _graphics_mode_u._graphics_mode_s._graphics_mode_hw_cursor
+#define graphics_mode_linear _graphics_mode_u._graphics_mode_s._graphics_mode_linear
+
+ union {
+ struct {
+ CARD8 _external_dac_reference : 1;
+ CARD8 _high_speed_dac_0 : 1;
+ CARD8 _direct_color_24bit : 1;
+ CARD8 _multi_line_prefetch : 1;
+ CARD8 _extended_video_div_2 : 1;
+ CARD8 _ramdac_power_save : 1;
+ CARD8 : 1;
+ CARD8 _merge_video_fifo : 1;
+ } _misc_control_0_s;
+ CARD8 _misc_control_0;
+ } _misc_control_0_u; /* SR7 */
+
+#define misc_control_0 _misc_control_0_u._misc_control_0
+#define external_dac_reference _misc_control_0_u._misc_control_0_s._external_dac_reference
+#define high_speed_dac_0 _misc_control_0_u._misc_control_0_s._high_speed_dac_0
+#define direct_color_24bit _misc_control_0_u._misc_control_0_s._direct_color_24bit
+#define multi_line_prefetch _misc_control_0_u._misc_control_0_s._multi_line_prefetch
+#define extended_video_div_2 _misc_control_0_u._misc_control_0_s._extended_video_div_2
+#define ramdac_power_save _misc_control_0_u._misc_control_0_s._ramdac_power_save
+#define merge_video_fifo _misc_control_0_u._misc_control_0_s._merge_video_fifo
+
+ union {
+ struct {
+ CARD8 _crt_engine_threshold_high_0_3 : 4;
+ CARD8 _crt_cpu_threshold_low_0_3 : 4;
+ } _crt_cpu_threshold_control_0_s;
+ CARD8 _crt_cpu_threshold_control_0;
+ } _crt_cpu_threshold_control_0_u; /* SR8 */
+
+#define crt_cpu_threshold_control_0 _crt_cpu_threshold_control_0_u._crt_cpu_threshold_control_0
+#define crt_engine_threshold_high_0_3 _crt_cpu_threshold_control_0_u._crt_cpu_threshold_control_0_s._crt_engine_threshold_high_0_3
+#define crt_cpu_threshold_low_0_3 _crt_cpu_threshold_control_0_u._crt_cpu_threshold_control_0_s._crt_cpu_threshold_low_0_3
+
+ union {
+ struct {
+ CARD8 _crt_cpu_threshold_high_0_3 : 4;
+ CARD8 _ascii_attribute_threshold_0_2 : 3;
+ CARD8 _true_color_32bpp : 1;
+ } _crt_cpu_threshold_control_1_s;
+ CARD8 _crt_cpu_threshold_control_1;
+ } _crt_cpu_threshold_control_1_u; /* SR9 */
+
+#define crt_cpu_threshold_control_1 _crt_cpu_threshold_control_1_u._crt_cpu_threshold_control_1
+#define crt_cpu_threshold_high_0_3 _crt_cpu_threshold_control_1_u._crt_cpu_threshold_control_1_s._crt_cpu_threshold_high_0_3
+#define ascii_attribute_threshold_0_2 _crt_cpu_threshold_control_1_u._crt_cpu_threshold_control_1_s._ascii_attribute_threshold_0_2
+#define true_color_32bpp _crt_cpu_threshold_control_1_u._crt_cpu_threshold_control_1_s._true_color_32bpp
+
+ union {
+ struct {
+ CARD8 _v_total_10 : 1;
+ CARD8 _v_display_end_10 : 1;
+ CARD8 _v_blank_start_10 : 1;
+ CARD8 _v_retrace_start_10 : 1;
+ CARD8 _screen_off_8_11 : 4;
+ } _extended_crt_overflow_s;
+ CARD8 _extended_crt_overflow;
+ } _extended_crt_overflow_u; /* SRA */
+
+#define extended_crt_overflow _extended_crt_overflow_u._extended_crt_overflow
+#define v_total_10 _extended_crt_overflow_u._extended_crt_overflow_s._v_total_10
+#define v_display_end_10 _extended_crt_overflow_u._extended_crt_overflow_s._v_display_end_10
+#define v_blank_start_10 _extended_crt_overflow_u._extended_crt_overflow_s._v_blank_start_10
+#define v_retrace_start_10 _extended_crt_overflow_u._extended_crt_overflow_s._v_retrace_start_10
+#define screen_off_8_11 _extended_crt_overflow_u._extended_crt_overflow_s._screen_off_8_11
+
+ union {
+ struct {
+ CARD8 _cpu_bitblt_enable : 1; /* enable CPU bitblt */
+ CARD8 _packed_16_color_enable : 1; /* 2 pixels per byte? */
+ CARD8 _io_gating : 1; /* when write buffer not empty */
+ CARD8 _dual_segment_enable : 1; /* ? */
+ CARD8 _true_color_modulation : 1; /* ? */
+ CARD8 _memory_mapped_mode : 2; /* mmio enable */
+ CARD8 _true_color_order : 1; /* 0: RGB 1: BGR */
+ } _misc_control_1_s;
+ CARD8 _misc_control_1; /* SRB */
+ } _misc_control_1_u;
+
+#define misc_control_1 _misc_control_1_u._misc_control_1
+#define cpu_bitblt_enable _misc_control_1_u._misc_control_1_s._cpu_bitblt_enable
+#define memory_mapped_mode _misc_control_1_u._misc_control_1_s._memory_mapped_mode
+#define true_color_modulation _misc_control_1_u._misc_control_1_s._true_color_modulation
+#define true_color_order _misc_control_1_u._misc_control_1_s._true_color_order
+
+ union {
+ struct {
+ CARD8 _sync_reset_enable : 1;
+ CARD8 _memory_configuration : 3;
+#define SIS_MEMORY_CONFIG_1M_1BANK 0
+#define SIS_MEMORY_CONFIG_2M_2BANK 1
+#define SIS_MEMORY_CONFIG_4M_2BANK 2
+#define SIS_MEMORY_CONFIG_2M_1BANK 5
+#define SIS_MEMORY_CONFIG_4M_1BANK 6
+#define SIS_MEMORY_CONFIG_8M_2BANK 7
+ CARD8 _test_mode_enable : 1;
+ CARD8 _read_ahead_enable : 1;
+ CARD8 _text_mode_16bit_enable : 1;
+ CARD8 _graphics_mode_32bit_enable : 1;
+ } _misc_control_2_s;
+ CARD8 _misc_control_2;
+ } _misc_control_2_u; /* SRC */
+
+#define misc_control_2 _misc_control_2_u._misc_control_2
+#define sync_reset_enable _misc_control_2_u._misc_control_2_s._sync_reset_enable
+#define memory_configuration _misc_control_2_u._misc_control_2_s._memory_configuration
+#define test_mode_enable _misc_control_2_u._misc_control_2_s._test_mode_enable
+#define read_ahead_enable _misc_control_2_u._misc_control_2_s._read_ahead_enable
+#define text_mode_16bit_enable _misc_control_2_u._misc_control_2_s._text_mode_16bit_enable
+#define graphics_mode_32bit_enable _misc_control_2_u._misc_control_2_s._graphics_mode_32bit_enable
+
+ union ddc_and_power_control_u {
+ struct {
+ CARD8 _ddc_clk_programming : 1;
+ CARD8 _ddc_data_programming : 1;
+ CARD8 : 1;
+ CARD8 _acpi_enable : 1;
+ CARD8 _kbd_cursor_activate : 1;
+ CARD8 _video_memory_activate : 1;
+ CARD8 _vga_standby : 1;
+ CARD8 _vga_suspend : 1;
+ } _ddc_and_power_control_s;
+ CARD8 _ddc_and_power_control;
+ } _ddc_and_power_control_u; /* SR11 */
+
+#define ddc_and_power_control _ddc_and_power_control_u._ddc_and_power_control
+#define ddc_clk_programming _ddc_and_power_control_u._ddc_and_power_control_s._ddc_clk_programming
+#define ddc_data_programming _ddc_and_power_control_u._ddc_and_power_control_s._ddc_data_programming
+#define acpi_enable _ddc_and_power_control_u._ddc_and_power_control_s._acpi_enable
+#define kbd_cursor_activate _ddc_and_power_control_u._ddc_and_power_control_s._kbd_cursor_activate
+#define video_memory_activate _ddc_and_power_control_u._ddc_and_power_control_s._video_memory_activate
+#define vga_standby _ddc_and_power_control_u._ddc_and_power_control_s._vga_standby
+#define vga_suspend _ddc_and_power_control_u._ddc_and_power_control_s._vga_suspend
+
+ union {
+ struct {
+ CARD8 _h_total_8 : 1;
+ CARD8 _h_display_end_8 : 1;
+ CARD8 _h_blank_start_8 : 1;
+ CARD8 _h_sync_start_8 : 1;
+ CARD8 _h_blank_end_6 : 1;
+ CARD8 _h_retrace_skew : 3;
+ } _extended_horizontal_overflow_s;
+ CARD8 _extended_horizontal_overflow;
+ } _extended_horizontal_overflow_u; /* SR12 */
+#define extended_horizontal_overflow _extended_horizontal_overflow_u._extended_horizontal_overflow
+#define h_total_8 _extended_horizontal_overflow_u._extended_horizontal_overflow_s._h_total_8
+#define h_display_end_8 _extended_horizontal_overflow_u._extended_horizontal_overflow_s._h_display_end_8
+#define h_blank_start_8 _extended_horizontal_overflow_u._extended_horizontal_overflow_s._h_blank_start_8
+#define h_sync_start_8 _extended_horizontal_overflow_u._extended_horizontal_overflow_s._h_sync_start_8
+#define h_blank_end_6 _extended_horizontal_overflow_u._extended_horizontal_overflow_s._h_blank_end_6
+#define h_retrace_skew _extended_horizontal_overflow_u._extended_horizontal_overflow_s._h_retrace_skew
+
+ union {
+ struct {
+ CARD8 : 6;
+ CARD8 _vclk_post_scale_2 : 1;
+ CARD8 _mclk_post_scale_2 : 1;
+ } _extended_clock_generator_s;
+ CARD8 _extended_clock_generator;
+ } _extended_clock_generator_u; /* SR13 */
+
+#define extended_clock_generator _extended_clock_generator_u._extended_clock_generator
+#define vclk_post_scale_2 _extended_clock_generator_u._extended_clock_generator_s._vclk_post_scale_2
+#define mclk_post_scale_2 _extended_clock_generator_u._extended_clock_generator_s._mclk_post_scale_2
+
+ CARD8 cursor_0_red; /* SR14 */
+ CARD8 cursor_0_green; /* SR15 */
+ CARD8 cursor_0_blue; /* SR16 */
+
+ CARD8 cursor_1_red; /* SR17 */
+ CARD8 cursor_1_green; /* SR18 */
+ CARD8 cursor_1_blue; /* SR19 */
+
+ CARD8 cursor_h_start_0_7; /* SR1A */
+ union {
+ struct {
+ CARD8 _cursor_h_start_8_11 : 4;
+ CARD8 : 3;
+ CARD8 _cursor_mmio_enable : 1;
+ } _cusor_h_start_1_s;
+ CARD8 _cursor_h_start_1;
+ } _cursor_h_start_1_u; /* SR1B */
+
+#define cursor_h_start_1 _cursor_h_start_1_u._cursor_h_start_1
+#define cursor_h_start_8_11 _cursor_h_start_1_u._cursor_h_start_1_s._cursor_h_start_8_11
+
+ CARD8 cursor_h_preset_0_5; /* SR1C */
+
+ CARD8 cursor_v_start_0_7; /* SR1D */
+
+ union {
+ struct {
+ CARD8 _cursor_v_start_8_10 : 3;
+ CARD8 _cursor_side_pattern : 1;
+ CARD8 _cursor_pattern : 4;
+ } _cusor_v_start_1_s;
+ CARD8 _cursor_v_start_1;
+ } _cursor_v_start_1_u; /* SR1E */
+
+#define cursor_v_start_1 _cursor_v_start_1_u._cursor_v_start_1
+
+ CARD8 cursor_v_preset_0_5; /* SR1F */
+
+ CARD8 linear_base_19_26; /* SR20 */
+
+ union {
+ struct {
+ CARD8 _linear_base_27_31 : 5;
+ CARD8 _linear_aperture : 3;
+#define SIS_LINEAR_APERTURE_512K 0
+#define SIS_LINEAR_APERTURE_1M 1
+#define SIS_LINEAR_APERTURE_2M 2
+#define SIS_LINEAR_APERTURE_4M 3
+#define SIS_LINEAR_APERTURE_8M 4
+ } _linear_base_1_s;
+ CARD8 _linear_base_1;
+ } _linear_base_1_u; /* SR21 */
+
+#define linear_base_1 _linear_base_1_u._linear_base_1
+#define linear_base_27_31 _linear_base_1_u._linear_base_1_s._linear_base_27_31
+
+ union {
+ struct {
+ CARD8 _screen_start_addr_20 : 1;
+ CARD8 : 3;
+ CARD8 _continuous_mem_access : 1;
+ CARD8 : 1;
+ CARD8 _power_down_dac : 1;
+ CARD8 : 1;
+ } _graphics_engine_0_s;
+ CARD8 _graphics_engine_0;
+ } _graphics_engine_0_u; /* SR26 */
+
+#define graphics_engine_0 _graphics_engine_0_u._graphics_engine_0
+
+
+ union {
+ struct {
+ CARD8 _screen_start_addr_16_19: 4;
+ CARD8 _logical_screen_width : 2;
+#define SIS_LOG_SCREEN_WIDTH_1024 0
+#define SIS_LOG_SCREEN_WIDTH_2048 1
+#define SIS_LOG_SCREEN_WIDTH_4096 2
+ CARD8 _graphics_prog_enable : 1;
+ CARD8 _turbo_queue_enable : 1;
+ } _graphics_engine_1_s;
+ CARD8 _graphics_engine_1;
+ } _graphics_engine_1_u; /* SR27 */
+
+#define graphics_engine_1 _graphics_engine_1_u._graphics_engine_1
+#define screen_start_addr_16_19 _graphics_engine_1_u._graphics_engine_1_s._screen_start_addr_16_19
+#define logical_screen_width _graphics_engine_1_u._graphics_engine_1_s._logical_screen_width
+#define graphics_prog_enable _graphics_engine_1_u._graphics_engine_1_s._graphics_prog_enable
+#define turbo_queue_enable _graphics_engine_1_u._graphics_engine_1_s._turbo_queue_enable
+
+
+ union {
+ struct {
+ CARD8 _mclk_numerator : 7;
+ CARD8 _mclk_divide_by_2 : 1;
+ } _internal_mclk_0_s;
+ CARD8 _internal_mclk_0;
+ } _internal_mclk_0_u; /* SR28 */
+
+#define internal_mclk_0 _internal_mclk_0_u._internal_mclk_0
+#define mclk_numerator _internal_mclk_0_u._internal_mclk_0_s._mclk_numerator
+#define mclk_divide_by_2 _internal_mclk_0_u._internal_mclk_0_s._mclk_divide_by_2
+
+ union {
+ struct {
+ CARD8 _mclk_denominator : 5;
+ CARD8 _mclk_post_scale : 2;
+#define SIS_MCLK_POST_SCALE_1 0
+#define SIS_MCLK_POST_SCALE_2 1
+#define SIS_MCLK_POST_SCALE_3 2
+#define SIS_MCLK_POST_SCALE_4 3
+ CARD8 _mclk_vco_gain : 1;
+ } _internal_mclk_1_s;
+ CARD8 _internal_mclk_1;
+ } _internal_mclk_1_u; /* SR29 */
+
+#define internal_mclk_1 _internal_mclk_1_u._internal_mclk_1
+#define mclk_denominator _internal_mclk_1_u._internal_mclk_1_s._mclk_denominator
+#define mclk_post_scale _internal_mclk_1_u._internal_mclk_1_s._mclk_post_scale
+#define mclk_vco_gain _internal_mclk_1_u._internal_mclk_1_s._mclk_vco_gain
+
+ union {
+ struct {
+ CARD8 _vclk_numerator : 7;
+ CARD8 _vclk_divide_by_2 : 1;
+ } _internal_vclk_0_s;
+ CARD8 _internal_vclk_0;
+ } _internal_vclk_0_u; /* SR2A */
+
+#define internal_vclk_0 _internal_vclk_0_u._internal_vclk_0
+#define vclk_numerator _internal_vclk_0_u._internal_vclk_0_s._vclk_numerator
+#define vclk_divide_by_2 _internal_vclk_0_u._internal_vclk_0_s._vclk_divide_by_2
+
+ union {
+ struct {
+ CARD8 _vclk_denominator : 5;
+ CARD8 _vclk_post_scale : 2;
+#define SIS_VCLK_POST_SCALE_1 0
+#define SIS_VCLK_POST_SCALE_2 1
+#define SIS_VCLK_POST_SCALE_3 2
+#define SIS_VCLK_POST_SCALE_4 3
+ CARD8 _vclk_vco_gain : 1;
+ } _internal_vclk_1_s;
+ CARD8 _internal_vclk_1;
+ } _internal_vclk_1_u; /* SR2B */
+
+#define internal_vclk_1 _internal_vclk_1_u._internal_vclk_1
+#define vclk_denominator _internal_vclk_1_u._internal_vclk_1_s._vclk_denominator
+#define vclk_post_scale _internal_vclk_1_u._internal_vclk_1_s._vclk_post_scale
+#define vclk_vco_gain _internal_vclk_1_u._internal_vclk_1_s._vclk_vco_gain
+
+ union {
+ struct {
+ CARD8 _extended_clock_select : 2;
+#define SIS_CLOCK_SELECT_INTERNAL 0
+#define SIS_CLOCK_SELECT_25MHZ 1
+#define SIS_CLOCK_SELECT_28MHZ 2
+ CARD8 _disable_line_compare : 1;
+ CARD8 _disable_pci_read_t_o : 1;
+ CARD8 _cursor_start_addr_18_21: 4;
+ } _misc_control_7_s;
+ CARD8 _misc_control_7;
+ } _misc_control_7_u; /* SR38 */
+
+#define misc_control_7 _misc_control_7_u._misc_control_7
+#define extended_clock_select _misc_control_7_u._misc_control_7_s._extended_clock_select
+#define disable_line_compare _misc_control_7_u._misc_control_7_s._disable_line_compare
+#define disable_pci_read_t_o _misc_control_7_u._misc_control_7_s._disable_pci_read_t_o
+#define cursor_start_addr_18_21 _misc_control_7_u._misc_control_7_s._cursor_start_addr_18_21
+
+ union {
+ struct {
+ CARD8 _high_speed_dclk : 1;
+ CARD8 _sgram_block_write : 1;
+ CARD8 _cursor_start_addr_22 : 1;
+ CARD8 _dram_texture_read : 1;
+ CARD8 _sgram_16mb : 1;
+ CARD8 _agp_signal_delay : 2;
+ CARD8 _dclk_off : 1;
+ } _misc_control_11_s;
+ CARD8 _misc_control_11;
+ } _misc_control_11_u; /* SR3E */
+
+#define misc_control_11 _misc_control_11_u._misc_control_11
+#define high_speed_dclk _misc_control_11_u._misc_control_11_s._high_speed_dclk
+#define sgram_block_write _misc_control_11_u._misc_control_11_s.__sgram_block_write
+#define cursor_start_addr_22 _misc_control_11_u._misc_control_11_s._cursor_start_addr_22
+#define dram_texture_read _misc_control_11_u._misc_control_11_s._dram_texture_read
+#define sgram_16mb _misc_control_11_u._misc_control_11_s._sgram_16mb
+#define agp_signal_delay _misc_control_11_u._misc_control_11_s._agp_signal_delay
+#define dclk_off _misc_control_11_u._misc_control_11_s._dclk_off
+
+ union {
+ struct {
+ CARD8 : 1;
+ CARD8 _flat_panel_low_enable : 1;
+ CARD8 _crt_cpu_threshold_low_4: 1;
+ CARD8 _crt_engine_threshold_high_4: 1;
+ CARD8 _crt_cpu_threshold_high_4 : 1;
+ CARD8 _crt_threshold_full_control : 2;
+#define SIS_CRT_32_STAGE_THRESHOLD 0
+#define SIS_CRT_64_STAGE_THRESHOLD 1
+#define SIS_CRT_63_STAGE_THRESHOLD 2
+#define SIS_CRT_256_STAGE_THRESHOLD 3
+ CARD8 _high_speed_dac_1 : 1;
+ } _misc_control_12_s;
+ CARD8 _misc_control_12;
+ } _misc_control_12_u; /* SR3F */
+#define misc_control_12 _misc_control_12_u._misc_control_12
+#define flat_panel_low_enable _misc_control_12_u._misc_control_12_s._flat_panel_low_enable
+#define crt_cpu_threshold_low_4 _misc_control_12_u._misc_control_12_s._crt_cpu_threshold_low_4
+#define crt_engine_threshold_high_4 _misc_control_12_u._misc_control_12_s._crt_engine_threshold_high_4
+#define crt_cpu_threshold_high_4 _misc_control_12_u._misc_control_12_s._crt_cpu_threshold_high_4
+#define crt_threshold_full_control _misc_control_12_u._misc_control_12_s._crt_threshold_full_control
+#define high_speed_dac_1 _misc_control_12_u._misc_control_12_s._high_speed_dac_1
+
+ /* computed values */
+ CARD16 ge_screen_pitch;
+ CARD8 bits_per_pixel;
+ CARD8 depth;
+ CARD8 double_pixel_mode;
+ CARD16 pixel_width;
+} SisCrtc;
+
+#define crtc_v_total(crtc) ((crtc)->v_total_0_7 | \
+ ((crtc)->v_total_8 << 8) | \
+ ((crtc)->v_total_9 << 9) | \
+ ((crtc)->v_total_10 << 10))
+
+#define crtc_set_v_total(crtc,v) { \
+ ((crtc))->v_total_0_7 = (v); \
+ ((crtc))->v_total_8 = (v) >> 8; \
+ ((crtc))->v_total_9 = (v) >> 9; \
+ ((crtc))->v_total_10 = (v) >> 10; \
+}
+
+#define crtc_v_display_end(crtc) ((crtc)->v_display_end_0_7 | \
+ ((crtc)->v_display_end_8 << 8) | \
+ ((crtc)->v_display_end_9 << 9) | \
+ ((crtc)->v_display_end_10 << 10))
+
+#define crtc_set_v_display_end(crtc,v) {\
+ ((crtc))->v_display_end_0_7 = (v); \
+ ((crtc))->v_display_end_8 = (v) >> 8; \
+ ((crtc))->v_display_end_9 = (v) >> 9; \
+ ((crtc))->v_display_end_10 = (v) >> 10; \
+}
+
+#define crtc_v_retrace_start(crtc) ((crtc)->v_retrace_start_0_7 | \
+ ((crtc)->v_retrace_start_8 << 8) | \
+ ((crtc)->v_retrace_start_9 << 9) | \
+ ((crtc)->v_retrace_start_10 << 10))
+
+#define crtc_set_v_retrace_start(crtc,v) {\
+ ((crtc))->v_retrace_start_0_7 = (v); \
+ ((crtc))->v_retrace_start_8 = (v) >> 8; \
+ ((crtc))->v_retrace_start_9 = (v) >> 9; \
+ ((crtc))->v_retrace_start_10 = (v) >> 10; \
+}
+
+#define crtc_v_blank_start(crtc) ((crtc)->v_blank_start_0_7 | \
+ ((crtc)->v_blank_start_8 << 8) | \
+ ((crtc)->v_blank_start_9 << 9) | \
+ ((crtc)->v_blank_start_10 << 10))
+
+#define crtc_set_v_blank_start(crtc,v) {\
+ ((crtc))->v_blank_start_0_7 = (v); \
+ ((crtc))->v_blank_start_8 = (v) >> 8; \
+ ((crtc))->v_blank_start_9 = (v) >> 9; \
+ ((crtc))->v_blank_start_10 = (v) >> 10; \
+}
+
+#define crtc_h_total(crtc) ((crtc)->h_total_0_7 | \
+ ((crtc)->h_total_8 << 8))
+
+#define crtc_set_h_total(crtc,v) {\
+ ((crtc))->h_total_0_7 = (v); \
+ ((crtc))->h_total_8 = (v) >> 8; \
+}
+
+#define crtc_h_display_end(crtc) ((crtc)->h_display_end_0_7 | \
+ ((crtc)->h_display_end_8 << 8))
+
+#define crtc_set_h_display_end(crtc,v) {\
+ ((crtc))->h_display_end_0_7 = (v); \
+ ((crtc))->h_display_end_8 = (v) >> 8; \
+}
+
+#define crtc_h_blank_start(crtc) ((crtc)->h_blank_start_0_7 | \
+ ((crtc)->h_blank_start_8 << 8))
+
+#define crtc_set_h_blank_start(crtc,v) {\
+ ((crtc))->h_blank_start_0_7 = (v); \
+ ((crtc))->h_blank_start_8 = (v) >> 8; \
+}
+
+#define crtc_h_blank_end(crtc) ((crtc)->h_blank_end_0_4 | \
+ ((crtc)->h_blank_end_5 << 5))
+
+#define crtc_set_h_blank_end(crtc,v) {\
+ ((crtc))->h_blank_end_0_4 = (v); \
+ ((crtc))->h_blank_end_5 = (v) >> 5; \
+}
+
+#define crtc_h_sync_start(crtc) ((crtc)->h_sync_start_0_7 | \
+ ((crtc)->h_sync_start_8 << 8))
+
+#define crtc_set_h_sync_start(crtc,v) {\
+ ((crtc))->h_sync_start_0_7 = (v); \
+ ((crtc))->h_sync_start_8 = (v) >> 8; \
+}
+
+#define crtc_h_sync_end(crtc) ((crtc)->h_sync_end_0_4)
+
+#define crtc_set_h_sync_end(crtc,v) {\
+ ((crtc))->h_sync_end_0_4 = (v); \
+}
+
+#define crtc_screen_off(crtc) ((crtc)->screen_off_0_7 | \
+ ((crtc)->screen_off_8_11 << 8))
+
+#define crtc_set_screen_off(crtc,v) {\
+ ((crtc))->screen_off_0_7 = (v); \
+ ((crtc))->screen_off_8_11 = (v) >> 8; \
+}
+
+#define crtc_ge_screen_width(crtc) ((crtc)->ge_screen_width_0_1 | \
+ ((crtc)->ge_screen_width_2 << 2))
+
+#define crtc_set_ge_screen_width(crtc,v) { \
+ (crtc)->ge_screen_width_0_1 = (v); \
+ (crtc)->ge_screen_width_2 = (v) >> 2; \
+}
+
+#define crtc_h_start_fifo_fetch(crtc) ((crtc)->h_start_fifo_fetch_0_7 | \
+ ((crtc)->h_start_fifo_fetch_8 << 8))
+
+#define crtc_set_h_start_fifo_fetch(crtc,v) {\
+ (crtc)->h_start_fifo_fetch_0_7 = (v); \
+ (crtc)->h_start_fifo_fetch_8 = (v) >> 8; \
+}
+
+#define crtc_start_address(crtc) ((crtc)->start_address_0_7 | \
+ ((crtc)->start_address_8_15 << 8) | \
+ ((crtc)->start_address_16_19 << 16))
+
+#define crtc_set_start_address(crtc,v) {\
+ (crtc)->start_address_0_7 = (v); \
+ (crtc)->start_address_8_15 = (v) >> 8; \
+ (crtc)->start_address_16_19 = (v) >> 16; \
+}
+
+#define crtc_line_compare(crtc) ((crtc)->line_compare_0_7 | \
+ ((crtc)->line_compare_8 << 8) | \
+ ((crtc)->line_compare_9 << 9) | \
+ ((crtc)->line_compare_10 << 10))
+
+#define crtc_set_line_compare(crtc,v) { \
+ ((crtc))->line_compare_0_7 = (v); \
+ ((crtc))->line_compare_8 = (v) >> 8; \
+ ((crtc))->line_compare_9 = (v) >> 9; \
+ ((crtc))->line_compare_10 = (v) >> 10; \
+}
+
+#define crtc_set_cursor_start_addr(crtc,v) { \
+ (crtc)->cursor_start_addr_18_21 = (v) >> 18; \
+ (crtc)->cursor_start_addr_22 = (v) >> 22; \
+}
+
+#define _sisOutb(v,r) outb(v,r)
+#define _sisInb(r) inb(r)
+
+#define SIS_DAC_INDEX_READ 0x47
+#define SIS_DAC_INDEX_WRITE 0x48
+#define SIS_DAC_DATA 0x49
+
+#define GetCrtc(sisc,i) _sisReadIndexRegister ((sisc)->io_base+0x54,i)
+#define PutCrtc(sisc,i,v) _sisWriteIndexRegister ((sisc)->io_base+0x54,i,v)
+
+#define GetSrtc(sisc,i) _sisReadIndexRegister ((sisc)->io_base+0x44,i)
+#define PutSrtc(sisc,i,v) _sisWriteIndexRegister ((sisc)->io_base+0x44,i,v)
+
+#define GetArtc(sisc,i) _sisReadIndexRegister ((sisc)->io_base+0x40,i)
+#define PutArtc(sisc,i,v) _sisWriteIndexRegister ((sisc)->io_base+0x40,i,v)
+
+#define GetGrtc(sisc,i) _sisReadIndexRegister ((sisc)->io_base+0x4e,i)
+#define PutGrtc(sisc,i,v) _sisWriteIndexRegister ((sisc)->io_base+0x4e,i,v)
+
+#define _sisWaitVRetrace(sisc)
+
+#define LockSis(sisc)
+#define UnlockSis(sisc)
+
+typedef struct _sisTiming {
+ /* label */
+ int horizontal;
+ int vertical;
+ int rate;
+ /* horizontal timing */
+ int hfp; /* front porch */
+ int hbp; /* back porch */
+ int hblank; /* blanking */
+ /* vertical timing */
+ int vfp; /* front porch */
+ int vbp; /* back porch */
+ int vblank; /* blanking */
+} SisTiming;
+
+typedef struct _sisSave {
+ CARD8 srb;
+ CARD8 sr5;
+ SisCrtc crtc;
+} SisSave;
+
+typedef struct _sisCardInfo {
+ SisPtr sis;
+ int memory;
+ CARD8 *frameBuffer;
+ CARD8 *registers;
+ VOL32 *cpu_bitblt;
+ CARD32 io_base;
+ SisSave save;
+} SisCardInfo;
+
+typedef struct _sisScreenInfo {
+ CARD8 *cursor_base;
+ CARD32 cursor_off;
+ CARD8 *expand;
+ CARD32 expand_off;
+ int expand_len;
+ SisCursor cursor;
+} SisScreenInfo;
+
+#define getSisCardInfo(kd) ((SisCardInfo *) ((kd)->card->driver))
+#define sisCardInfo(kd) SisCardInfo *sisc = getSisCardInfo(kd)
+
+#define getSisScreenInfo(kd) ((SisScreenInfo *) ((kd)->screen->driver))
+#define sisScreenInfo(kd) SisScreenInfo *siss = getSisScreenInfo(kd)
+
+Bool sisCardInit (KdCardInfo *);
+Bool sisScreenInit (KdScreenInfo *);
+void sisEnable (ScreenPtr pScreen);
+void sisDisable (ScreenPtr pScreen);
+void sisFini (ScreenPtr pScreen);
+
+Bool sisCursorInit (ScreenPtr pScreen);
+void sisCursorEnable (ScreenPtr pScreen);
+void sisCursorDisable (ScreenPtr pScreen);
+void sisCursorFini (ScreenPtr pScreen);
+void sisRecolorCursor (ScreenPtr pScreen, int ndef, xColorItem *pdefs);
+
+Bool sisDrawInit (ScreenPtr pScreen);
+void sisDrawEnable (ScreenPtr pScreen);
+void sisDrawDisable (ScreenPtr pScreen);
+void sisDrawFini (ScreenPtr pScreen);
+
+void sisGetColors (ScreenPtr pScreen, int ndef, xColorItem *pdefs);
+void sisPutColors (ScreenPtr pScreen, int ndef, xColorItem *pdefs);
+
+void SISInitCard (KdCardAttr *attr);
+
+CARD8 _sisReadIndexRegister (CARD32 base, CARD8 index);
+void _sisWriteIndexRegister (CARD32 base, CARD8 index, CARD8 value);
+
+extern KdCardFuncs sisFuncs;
+
+/*
+ * sisclock.c
+ */
+void
+sisGetClock (unsigned long clock, SisCrtc *crtc);
+
+void
+sisEngThresh (SisCrtc *crtc, unsigned long vclk, int bpp);
+
+/*
+ * siscurs.c
+ */
+
+Bool
+sisCursorInit (ScreenPtr pScreen);
+
+void
+sisCursorEnable (ScreenPtr pScreen);
+
+void
+sisCursorDisable (ScreenPtr pScreen);
+
+void
+sisCursorFini (ScreenPtr pScreen);
+
+/* sisdraw.c */
+Bool
+sisDrawInit (ScreenPtr pScreen);
+
+void
+sisDrawEnable (ScreenPtr pScreen);
+
+void
+sisDrawDisable (ScreenPtr pScreen);
+
+void
+sisDrawFini (ScreenPtr pScreen);
+
+#endif /* _SIS_H_ */
diff --git a/hw/kdrive/sis530/sisclock.c b/hw/kdrive/sis530/sisclock.c
new file mode 100644
index 000000000..7d7a008df
--- /dev/null
+++ b/hw/kdrive/sis530/sisclock.c
@@ -0,0 +1,232 @@
+/*
+ * $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 "sis.h"
+#include <stdio.h>
+
+#define FREF 14318180
+#define MIN_VCO FREF
+#define MAX_VCO 230000000
+#define MAX_PSN 0 /* no pre scaler for this chip */
+#define TOLERANCE 0.01 /* search smallest M and N in this tolerance */
+#define max_VLD 1
+
+/*
+ * Compute clock values given target frequency
+ */
+void
+sisGetClock (unsigned long clock, SisCrtc *crtc)
+{
+ unsigned char reg7, reg13, reg2a, reg2b;
+ int M, N, P, VLD;
+
+ int bestM, bestN, bestP, bestPSN, bestVLD;
+ double bestError, abest = 42.0, bestFout;
+
+ double Fvco, Fout;
+ double error, aerror;
+
+ double target = (double) clock;
+
+ int M_min = 2;
+ int M_max = 128;
+
+ int low_N = 2;
+ int high_N = 32;
+ int PSN = 1;
+
+ /*
+ * fd = fref*(Numerator/Denumerator)*(Divider/PostScaler)
+ *
+ * M = Numerator [1:128]
+ * N = DeNumerator [1:32]
+ * VLD = Divider (Vco Loop Divider) : divide by 1, 2
+ * P = Post Scaler : divide by 1, 2, 3, 4
+ * PSN = Pre Scaler (Reference Divisor Select)
+ *
+ * result in vclk[]
+ */
+
+ P = 1;
+ if (target < MAX_VCO / 2)
+ P = 2;
+ if (target < MAX_VCO / 3)
+ P = 3;
+ if (target < MAX_VCO / 4)
+ P = 4;
+ if (target < MAX_VCO / 6)
+ P = 6;
+ if (target < MAX_VCO / 8)
+ P = 8;
+
+ Fvco = P * target;
+
+ for (N = low_N; N <= high_N; N++)
+ {
+ double M_desired = Fvco / FREF * N;
+
+ if (M_desired > M_max * max_VLD)
+ continue;
+
+ if ( M_desired > M_max )
+ {
+ M = (int)(M_desired / 2 + 0.5);
+ VLD = 2;
+ }
+ else
+ {
+ M = (int)(M_desired + 0.5);
+ VLD = 1;
+ }
+
+ Fout = (double)FREF * (M * VLD)/(N * P);
+ error = (target - Fout) / target;
+ aerror = (error < 0) ? -error : error;
+ if (aerror < abest)
+ {
+ abest = aerror;
+ bestError = error;
+ bestM = M;
+ bestN = N;
+ bestP = P;
+ bestPSN = PSN;
+ bestVLD = VLD;
+ bestFout = Fout;
+ }
+ }
+
+ crtc->vclk_numerator = bestM - 1;
+ crtc->vclk_divide_by_2 = bestVLD == 2;
+
+ crtc->vclk_denominator = bestN - 1;
+ switch (bestP) {
+ case 1:
+ crtc->vclk_post_scale = SIS_VCLK_POST_SCALE_1;
+ crtc->vclk_post_scale_2 = 0;
+ break;
+ case 2:
+ crtc->vclk_post_scale = SIS_VCLK_POST_SCALE_2;
+ crtc->vclk_post_scale_2 = 0;
+ break;
+ case 3:
+ crtc->vclk_post_scale = SIS_VCLK_POST_SCALE_3;
+ crtc->vclk_post_scale_2 = 0;
+ break;
+ case 4:
+ crtc->vclk_post_scale = SIS_VCLK_POST_SCALE_4;
+ crtc->vclk_post_scale_2 = 0;
+ break;
+ case 6:
+ crtc->vclk_post_scale = SIS_VCLK_POST_SCALE_3;
+ crtc->vclk_post_scale_2 = 1;
+ break;
+ case 8:
+ crtc->vclk_post_scale = SIS_VCLK_POST_SCALE_4;
+ crtc->vclk_post_scale_2 = 1;
+ break;
+ }
+
+ crtc->vclk_vco_gain = 1;
+
+ /*
+ * Don't know how to set mclk for local frame buffer; for
+ * shared frame buffer, mclk is hardwired to bus speed (100MHz)?
+ */
+}
+
+sisCalcMclk (SisCrtc *crtc)
+{
+ int mclk, Numer, DeNumer;
+ double Divider, Scalar;
+
+ Numer = crtc->mclk_numerator;
+ DeNumer = crtc->mclk_denominator;
+ Divider = crtc->mclk_divide_by_2 ? 2.0 : 1.0;
+ Scalar = 1.0;
+ if (crtc->mclk_post_scale_2)
+ {
+ switch (crtc->mclk_post_scale) {
+ case 2:
+ Scalar = 6.0;
+ break;
+ case 3:
+ Scalar = 8.0;
+ break;
+ }
+ }
+ else
+ {
+ switch (crtc->mclk_post_scale) {
+ case 0:
+ Scalar = 1.0;
+ break;
+ case 1:
+ Scalar = 2.0;
+ break;
+ case 2:
+ Scalar = 3.0;
+ break;
+ case 3:
+ Scalar = 4.0;
+ break;
+ }
+ }
+
+ mclk = (int)(FREF*((double)(Numer+1)/(double)(DeNumer+1))*(Divider/Scalar));
+
+ return(mclk);
+}
+
+#define UMA_FACTOR 60
+#define LFB_FACTOR 30 // Only if local frame buffer
+#define SIS_SAYS_SO 0x1F // But how is the performance??
+#define CRT_ENG_THRESH 0x0F // But how is the performance??
+#define BUS_WIDTH 64
+#define DFP_BUS_WIDTH 32 // rumour has it for digital flat panel ??
+#define MEGAHZ (1<<20)
+
+void
+sisEngThresh (SisCrtc *crtc, unsigned long vclk, int bpp)
+{
+ int threshlow, mclk;
+
+ mclk = sisCalcMclk(crtc) / 1000000;
+ vclk = vclk / 1000000;
+ threshlow = ((((UMA_FACTOR*vclk*bpp)/
+ (mclk*BUS_WIDTH))+1)/2)+4;
+
+ crtc->crt_cpu_threshold_low_0_3 = threshlow;
+ crtc->crt_cpu_threshold_low_4 = threshlow >> 4;
+
+ crtc->crt_cpu_threshold_high_0_3 = (SIS_SAYS_SO & 0xf);
+ crtc->crt_cpu_threshold_high_4 = 0;
+
+ crtc->crt_engine_threshold_high_0_3 = CRT_ENG_THRESH;
+ crtc->crt_engine_threshold_high_4 = 1;
+
+ crtc->ascii_attribute_threshold_0_2 = (SIS_SAYS_SO >> 4);
+
+ crtc->crt_threshold_full_control = SIS_CRT_64_STAGE_THRESHOLD;
+}
diff --git a/hw/kdrive/sis530/siscmap.c b/hw/kdrive/sis530/siscmap.c
new file mode 100644
index 000000000..dadecf895
--- /dev/null
+++ b/hw/kdrive/sis530/siscmap.c
@@ -0,0 +1,64 @@
+/*
+ * $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 "sis.h"
+
+void
+sisGetColors (ScreenPtr pScreen, int ndef, xColorItem *pdefs)
+{
+ KdScreenPriv(pScreen);
+ sisCardInfo(pScreenPriv);
+
+ LockSis (sisc);
+ while (ndef--)
+ {
+ _sisOutb (pdefs->pixel, sisc->io_base+SIS_DAC_INDEX_READ);
+ pdefs->red = _sisInb (sisc->io_base+SIS_DAC_DATA) << 10;
+ pdefs->green = _sisInb (sisc->io_base+SIS_DAC_DATA) << 10;
+ pdefs->blue = _sisInb (sisc->io_base+SIS_DAC_DATA) << 10;
+ pdefs++;
+ }
+ UnlockSis (sisc);
+}
+
+void
+sisPutColors (ScreenPtr pScreen, int ndef, xColorItem *pdefs)
+{
+ KdScreenPriv(pScreen);
+ sisCardInfo(pScreenPriv);
+
+ LockSis(sisc);
+ _sisWaitVRetrace (sisc);
+ while (ndef--)
+ {
+ _sisOutb (pdefs->pixel, sisc->io_base+SIS_DAC_INDEX_WRITE);
+ _sisOutb (pdefs->red >> 10, sisc->io_base+SIS_DAC_DATA);
+ _sisOutb (pdefs->green >> 10, sisc->io_base+SIS_DAC_DATA);
+ _sisOutb (pdefs->blue >> 10, sisc->io_base+SIS_DAC_DATA);
+ pdefs++;
+ }
+ UnlockSis(sisc);
+}
+
diff --git a/hw/kdrive/sis530/siscurs.c b/hw/kdrive/sis530/siscurs.c
new file mode 100644
index 000000000..624fdec32
--- /dev/null
+++ b/hw/kdrive/sis530/siscurs.c
@@ -0,0 +1,364 @@
+/*
+ * $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 "sis.h"
+#include "cursorstr.h"
+
+#define SetupCursor(s) KdScreenPriv(s); \
+ sisCardInfo(pScreenPriv); \
+ sisScreenInfo(pScreenPriv); \
+ SisPtr sis = sisc->sis; \
+ SisCursor *pCurPriv = &siss->cursor
+
+static void
+_sisMoveCursor (ScreenPtr pScreen, int x, int y)
+{
+ SetupCursor(pScreen);
+ CARD8 xlow, xhigh, ylow, yhigh;
+ CARD8 xoff, yoff;
+
+ x -= pCurPriv->xhot;
+ xoff = 0;
+ if (x < 0)
+ {
+ xoff = -x;
+ x = 0;
+ }
+ y -= pCurPriv->yhot;
+ yoff = 0;
+ if (y < 0)
+ {
+ yoff = -y;
+ y = 0;
+ }
+ xlow = (CARD8) x;
+ xhigh = (CARD8) (x >> 8);
+ ylow = (CARD8) y;
+ yhigh = (CARD8) (y >> 8);
+
+ PutSrtc (sisc, 0x5, 0x86);
+ PutSrtc (sisc, 0x1c, xoff & 0x3f);
+ PutSrtc (sisc, 0x1f, yoff & 0x3f);
+
+ PutSrtc (sisc, 0x1a, xlow);
+ PutSrtc (sisc, 0x1b, xhigh & 0xf);
+
+ PutSrtc (sisc, 0x1d, ylow);
+ PutSrtc (sisc, 0x1e, yhigh & 0x7);
+}
+
+static void
+sisMoveCursor (ScreenPtr pScreen, int x, int y)
+{
+ SetupCursor (pScreen);
+
+ if (!pCurPriv->has_cursor)
+ return;
+
+ if (!pScreenPriv->enabled)
+ return;
+
+ LockSis(sisc);
+ _sisMoveCursor (pScreen, x, y);
+ UnlockSis(sisc);
+}
+
+static void
+_sisSetCursorColors (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+ CursorPtr pCursor = pCurPriv->pCursor;
+ /* set foreground */
+ PutSrtc (sisc, 0x17, pCursor->foreRed >> 10);
+ PutSrtc (sisc, 0x18, pCursor->foreGreen >> 10);
+ PutSrtc (sisc, 0x19, pCursor->foreBlue >> 10);
+
+ /* set background */
+ PutSrtc (sisc, 0x14, pCursor->backRed >> 10);
+ PutSrtc (sisc, 0x15, pCursor->backGreen >> 10);
+ PutSrtc (sisc, 0x16, pCursor->backBlue >> 10);
+}
+
+static void
+sisLoadCursor (ScreenPtr pScreen, int x, int y)
+{
+ SetupCursor(pScreen);
+ CursorPtr pCursor = pCurPriv->pCursor;
+ CursorBitsPtr bits = pCursor->bits;
+ int w, h;
+ unsigned short *ram, r;
+ unsigned char *msk, *mskLine, *src, *srcLine;
+ unsigned short m, s;
+
+ int i, j;
+ int cursor_address;
+ int src_stride, src_width;
+
+ CARD8 sr6;
+
+ /*
+ * Lock Sis so the cursor doesn't move while we're setting it
+ */
+ LockSis(sisc);
+
+ pCurPriv->pCursor = pCursor;
+ pCurPriv->xhot = pCursor->bits->xhot;
+ pCurPriv->yhot = pCursor->bits->yhot;
+
+ /*
+ * Stick new image into cursor memory
+ */
+ ram = (unsigned short *) siss->cursor_base;
+ mskLine = (unsigned char *) bits->mask;
+ srcLine = (unsigned char *) bits->source;
+
+ h = bits->height;
+ if (h > SIS_CURSOR_HEIGHT)
+ h = SIS_CURSOR_HEIGHT;
+
+ src_stride = BitmapBytePad(bits->width); /* bytes per line */
+ src_width = (bits->width + 7) >> 3;
+
+ for (i = 0; i < SIS_CURSOR_HEIGHT; i++) {
+ msk = mskLine;
+ src = srcLine;
+ mskLine += src_stride;
+ srcLine += src_stride;
+ for (j = 0; j < SIS_CURSOR_WIDTH / 8; j++) {
+
+ unsigned short m, s;
+
+ if (i < h && j < src_width)
+ {
+ m = *msk++;
+ s = *src++ & m;
+ m = ~m;
+ /* mask off right side */
+ if (j == src_width - 1 && (bits->width & 7))
+ {
+ m |= 0xff << (bits->width & 7);
+ }
+ }
+ else
+ {
+ m = 0xff;
+ s = 0x00;
+ }
+
+ /*
+ * The SIS530 HW cursor format is: source(AND) bit,
+ * then a mask(XOR) bit, etc.
+ * byte swapping in sis530 is:
+ * abcd ==> cdab
+ */
+
+#define bit(a,n) (((a) >> (n)) & 0x1)
+
+ r = ((bit(m, 0) << 7) | (bit(s, 0) << 6) |
+ (bit(m, 1) << 5) | (bit(s, 1) << 4) |
+ (bit(m, 2) << 3) | (bit(s, 2) << 2) |
+ (bit(m, 3) << 1) | (bit(s, 3) << 0) |
+ (bit(m, 4) << 15) | (bit(s, 4) << 14) |
+ (bit(m, 5) << 13) | (bit(s, 5) << 12) |
+ (bit(m, 6) << 11) | (bit(s, 6) << 10) |
+ (bit(m, 7) << 9) | (bit(s, 7) << 8));
+
+ *ram++ = r;
+ }
+ }
+
+ /* Set new color */
+ _sisSetCursorColors (pScreen);
+
+ /* Move to new position */
+ _sisMoveCursor (pScreen, x, y);
+
+ /* Enable cursor */
+ sr6 = GetSrtc (sisc, 0x6);
+ sr6 |= 0x40;
+ PutSrtc (sisc, 0x6, sr6);
+
+ UnlockSis(sisc);
+}
+
+static void
+sisUnloadCursor (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+ CARD8 sr6;
+
+ LockSis (sisc);
+
+ /* Disable cursor */
+ sr6 = GetSrtc (sisc, 0x6);
+ sr6 &= ~0x40;
+ PutSrtc (sisc, 0x6, sr6);
+ PutSrtc (sisc, 0x1b, 0x00);
+
+ UnlockSis (sisc);
+}
+
+static Bool
+sisRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
+{
+ SetupCursor(pScreen);
+
+ if (!pScreenPriv->enabled)
+ return TRUE;
+
+ /* miRecolorCursor does this */
+ if (pCurPriv->pCursor == pCursor)
+ {
+ if (pCursor)
+ {
+ int x, y;
+
+ miPointerPosition (&x, &y);
+ sisLoadCursor (pScreen, x, y);
+ }
+ }
+ return TRUE;
+}
+
+static Bool
+sisUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
+{
+ return TRUE;
+}
+
+static void
+sisSetCursor (ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
+{
+ SetupCursor(pScreen);
+
+ pCurPriv->pCursor = pCursor;
+
+ if (!pScreenPriv->enabled)
+ return;
+
+ if (pCursor)
+ sisLoadCursor (pScreen, x, y);
+ else
+ sisUnloadCursor (pScreen);
+}
+
+miPointerSpriteFuncRec sisPointerSpriteFuncs = {
+ sisRealizeCursor,
+ sisUnrealizeCursor,
+ sisSetCursor,
+ sisMoveCursor,
+};
+
+static void
+sisQueryBestSize (int class,
+ unsigned short *pwidth, unsigned short *pheight,
+ ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ switch (class)
+ {
+ case CursorShape:
+ if (*pwidth > pCurPriv->width)
+ *pwidth = pCurPriv->width;
+ if (*pheight > pCurPriv->height)
+ *pheight = pCurPriv->height;
+ if (*pwidth > pScreen->width)
+ *pwidth = pScreen->width;
+ if (*pheight > pScreen->height)
+ *pheight = pScreen->height;
+ break;
+ default:
+ fbQueryBestSize (class, pwidth, pheight, pScreen);
+ break;
+ }
+}
+
+Bool
+sisCursorInit (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ if (!siss->cursor_base)
+ {
+ pCurPriv->has_cursor = FALSE;
+ return FALSE;
+ }
+
+ pCurPriv->width = SIS_CURSOR_WIDTH;
+ pCurPriv->height= SIS_CURSOR_HEIGHT;
+ pScreen->QueryBestSize = sisQueryBestSize;
+ miPointerInitialize (pScreen,
+ &sisPointerSpriteFuncs,
+ &kdPointerScreenFuncs,
+ FALSE);
+ pCurPriv->has_cursor = TRUE;
+ pCurPriv->pCursor = NULL;
+ return TRUE;
+}
+
+void
+sisCursorEnable (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ if (pCurPriv->has_cursor)
+ {
+ if (pCurPriv->pCursor)
+ {
+ int x, y;
+
+ miPointerPosition (&x, &y);
+ sisLoadCursor (pScreen, x, y);
+ }
+ else
+ sisUnloadCursor (pScreen);
+ }
+}
+
+void
+sisCursorDisable (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ if (!pScreenPriv->enabled)
+ return;
+
+ if (pCurPriv->has_cursor)
+ {
+ if (pCurPriv->pCursor)
+ {
+ sisUnloadCursor (pScreen);
+ }
+ }
+}
+
+void
+sisCursorFini (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ pCurPriv->pCursor = NULL;
+}
diff --git a/hw/kdrive/sis530/sisdraw.c b/hw/kdrive/sis530/sisdraw.c
new file mode 100644
index 000000000..836f54e79
--- /dev/null
+++ b/hw/kdrive/sis530/sisdraw.c
@@ -0,0 +1,1656 @@
+/*
+ * $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 "sis.h"
+#include "sisdraw.h"
+
+#include "Xmd.h"
+#include "gcstruct.h"
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "regionstr.h"
+#include "mistruct.h"
+#include "fontstruct.h"
+#include "dixfontstr.h"
+#include "fb.h"
+#include "migc.h"
+#include "miline.h"
+
+CARD8 sisPatRop[16] = {
+ /* GXclear */ 0x00, /* 0 */
+ /* GXand */ 0xa0, /* src AND dst */
+ /* GXandReverse */ 0x50, /* src AND NOT dst */
+ /* GXcopy */ 0xf0, /* src */
+ /* GXandInverted*/ 0x0a, /* NOT src AND dst */
+ /* GXnoop */ 0xaa, /* dst */
+ /* GXxor */ 0x5a, /* src XOR dst */
+ /* GXor */ 0xfa, /* src OR dst */
+ /* GXnor */ 0x05, /* NOT src AND NOT dst */
+ /* GXequiv */ 0xa5, /* NOT src XOR dst */
+ /* GXinvert */ 0x55, /* NOT dst */
+ /* GXorReverse */ 0xf5, /* src OR NOT dst */
+ /* GXcopyInverted*/ 0x0f, /* NOT src */
+ /* GXorInverted */ 0xaf, /* NOT src OR dst */
+ /* GXnand */ 0x5f, /* NOT src OR NOT dst */
+ /* GXset */ 0xff, /* 1 */
+};
+
+CARD8 sisBltRop[16] = {
+ /* GXclear */ 0x00, /* 0 */
+ /* GXand */ 0x88, /* src AND dst */
+ /* GXandReverse */ 0x44, /* src AND NOT dst */
+ /* GXcopy */ 0xcc, /* src */
+ /* GXandInverted*/ 0x22, /* NOT src AND dst */
+ /* GXnoop */ 0xaa, /* dst */
+ /* GXxor */ 0x66, /* src XOR dst */
+ /* GXor */ 0xee, /* src OR dst */
+ /* GXnor */ 0x11, /* NOT src AND NOT dst */
+ /* GXequiv */ 0x99, /* NOT src XOR dst */
+ /* GXinvert */ 0x55, /* NOT dst */
+ /* GXorReverse */ 0xdd, /* src OR NOT dst */
+ /* GXcopyInverted*/ 0x33, /* NOT src */
+ /* GXorInverted */ 0xbb, /* NOT src OR dst */
+ /* GXnand */ 0x77, /* NOT src OR NOT dst */
+ /* GXset */ 0xff, /* 1 */
+};
+
+/* Align blts to this boundary or risk trashing an in-progress expand */
+#define SIS_MIN_PATTERN 8
+
+/* Do plane bits in this increment to balance CPU and graphics engine */
+#define SIS_PATTERN_INC 1024
+
+typedef struct _SisExpand {
+ SisCardInfo *sisc;
+ SisScreenInfo *siss;
+ CARD32 off;
+ int last;
+} SisExpand;
+
+static void
+sisExpandInit (ScreenPtr pScreen,
+ SisExpand *e)
+{
+ KdScreenPriv(pScreen);
+ sisCardInfo(pScreenPriv);
+ sisScreenInfo(pScreenPriv);
+
+ e->sisc = sisc;
+ e->siss = siss;
+ e->off = siss->expand_off;
+ e->last = 0;
+}
+
+static CARD32 *
+sisExpandAlloc (SisExpand *e,
+ int nb)
+{
+ SisCardInfo *sisc = e->sisc;
+ SisScreenInfo *siss = e->siss;
+ SisPtr sis = sisc->sis;
+ CARD32 off;
+
+ /* round up to alignment boundary */
+ nb = (nb + SIS_MIN_PATTERN-1) & ~(SIS_MIN_PATTERN-1);
+
+ off = e->off + e->last;
+ if (off + nb > siss->expand_off + siss->expand_len)
+ {
+ _sisWaitIdleEmpty (sis);
+ off = siss->expand_off;
+ }
+ e->off = off;
+ e->last = nb;
+ return (CARD32 *) (sisc->frameBuffer + off);
+}
+
+void
+sisGlyphBltClipped (DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x,
+ int y,
+ unsigned int nglyph,
+ CharInfoPtr *ppciInit,
+ Bool imageBlt)
+{
+ SetupSis(pDrawable->pScreen);
+ FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC);
+ int height;
+ int width;
+ int xBack, yBack;
+ int hBack, wBack;
+ int nb, bwidth, nl;
+ FontPtr pfont = pGC->font;
+ CharInfoPtr pci;
+ CARD8 *bits8, b;
+ CARD16 *bits16;
+ CARD32 *bits32;
+ BoxPtr extents;
+ BoxRec bbox;
+ unsigned char alu;
+ CARD32 cmd;
+ SisExpand expand;
+ CARD32 *dst, d;
+ int nbytes;
+ int shift;
+ int x1, y1, x2, y2;
+ RegionPtr pClip = fbGetCompositeClip(pGC);
+ BoxPtr pBox;
+ int nbox;
+ int rect_in;
+ int widthBlt;
+ CharInfoPtr *ppci;
+
+ x += pDrawable->x;
+ y += pDrawable->y;
+
+ if (imageBlt)
+ {
+ xBack = x;
+ yBack = y - FONTASCENT(pGC->font);
+ wBack = 0;
+ hBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
+ if (hBack)
+ {
+ height = nglyph;
+ ppci = ppciInit;
+ while (height--)
+ wBack += (*ppci++)->metrics.characterWidth;
+ }
+ if (wBack < 0)
+ {
+ xBack = xBack + wBack;
+ wBack = -wBack;
+ }
+ if (hBack < 0)
+ {
+ yBack = yBack + hBack;
+ hBack = -hBack;
+ }
+ alu = GXcopy;
+ }
+ else
+ {
+ wBack = 0;
+ alu = pGC->alu;
+ }
+
+ if (wBack)
+ {
+ _sisSetSolidRect (sis, pGC->bgPixel, GXcopy, cmd);
+ for (nbox = REGION_NUM_RECTS (pClip),
+ pBox = REGION_RECTS (pClip);
+ nbox--;
+ pBox++)
+ {
+ x1 = xBack;
+ x2 = xBack + wBack;
+ y1 = yBack;
+ y2 = yBack + hBack;
+ if (x1 < pBox->x1) x1 = pBox->x1;
+ if (x2 > pBox->x2) x2 = pBox->x2;
+ if (y1 < pBox->y1) y1 = pBox->y1;
+ if (y2 > pBox->y2) y2 = pBox->y2;
+ if (x1 < x2 && y1 < y2)
+ {
+ _sisRect (sis, x1, y1, x2 - x1, y2 - y1, cmd);
+ }
+ }
+ }
+
+ sisExpandInit (pDrawable->pScreen, &expand);
+
+ sis->u.general.src_fg = pGC->fgPixel;
+ sis->u.general.src_pitch = 0;
+ sis->u.general.src_x = 0;
+ sis->u.general.src_y = 0;
+
+ cmd = (SIS_CMD_ENH_COLOR_EXPAND |
+ SIS_CMD_SRC_SCREEN |
+ SIS_CMD_PAT_FG |
+ (sisBltRop[alu] << 8) |
+ SIS_CMD_INC_X |
+ SIS_CMD_INC_Y |
+ SIS_CMD_RECT_CLIP_ENABLE |
+ SIS_CMD_TRANSPARENT);
+
+ ppci = ppciInit;
+ while (nglyph--)
+ {
+ pci = *ppci++;
+ height = pci->metrics.ascent + pci->metrics.descent;
+ width = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing;
+ widthBlt = (width + 31) & ~31;
+ nb = (widthBlt >> 3) * height;
+ if (nb)
+ {
+ x1 = x + pci->metrics.leftSideBearing;
+ y1 = y - pci->metrics.ascent;
+ bbox.x1 = x1;
+ bbox.y1 = y1;
+ bbox.x2 = x1 + width;
+ bbox.y2 = y1 + height;
+ rect_in = RECT_IN_REGION(pGC->pScreen, pClip, &bbox);
+ if (rect_in != rgnOUT)
+ {
+ dst = sisExpandAlloc (&expand, nb);
+
+ sis->u.general.src_base = expand.off;
+ sis->u.general.dst_x = x1;
+ sis->u.general.dst_y = y1;
+ sis->u.general.rect_width = widthBlt;
+ sis->u.general.rect_height = height;
+ nb >>= 2;
+ bits32 = (CARD32 *) pci->bits;
+ while (nb--)
+ {
+ d = *bits32++;
+ SisInvertBits32 (d);
+ *dst++ = d;
+ }
+ if (rect_in == rgnPART)
+ {
+ for (nbox = REGION_NUM_RECTS (pClip),
+ pBox = REGION_RECTS (pClip);
+ nbox--;
+ pBox++)
+ {
+ _sisClip (sis, pBox->x1, pBox->y1, pBox->x2, pBox->y2);
+ sis->u.general.command = cmd;
+ }
+ }
+ else
+ {
+ _sisClip (sis, 0, 0, x1+width, pScreenPriv->screen->height);
+ sis->u.general.command = cmd;
+ }
+ }
+ }
+ x += pci->metrics.characterWidth;
+ }
+ _sisClip (sis, 0, 0,
+ pScreenPriv->screen->width, pScreenPriv->screen->height);
+ _sisWaitIdleEmpty(sis);
+}
+
+Bool
+sisTEGlyphBlt (DrawablePtr pDrawable,
+ GCPtr pGC,
+ int xInit,
+ int yInit,
+ unsigned int nglyph,
+ CharInfoPtr *ppci,
+ Bool imageBlt)
+{
+ SetupSis(pDrawable->pScreen);
+ int x, y;
+ int widthGlyphs, widthGlyph;
+ int widthBlt;
+ FbBits depthMask;
+ int glyphsPer;
+ FontPtr pfont = pGC->font;
+ unsigned long *char1, *char2, *char3, *char4, *char5;
+ CARD8 alu;
+ CARD32 *dst, tmp;
+ CARD8 *dst8, *bits8;
+ int nb;
+ int bwidth;
+ CARD32 cmd;
+ int h;
+ BoxRec bbox;
+ SisExpand expand;
+ int lwTmp, lw;
+ int extra, n;
+
+ widthGlyph = FONTMAXBOUNDS(pfont,characterWidth);
+ if (!widthGlyph)
+ return TRUE;
+
+ h = FONTASCENT(pfont) + FONTDESCENT(pfont);
+ if (!h)
+ return TRUE;
+
+ x = xInit + FONTMAXBOUNDS(pfont,leftSideBearing) + pDrawable->x;
+ y = yInit - FONTASCENT(pfont) + pDrawable->y;
+
+ bbox.x1 = x;
+ bbox.x2 = x + (widthGlyph * nglyph);
+ bbox.y1 = y;
+ bbox.y2 = y + h;
+
+ switch (RECT_IN_REGION(pGC->pScreen, fbGetCompositeClip(pGC), &bbox))
+ {
+ case rgnPART:
+ if (x < 0 || y < 0)
+ return FALSE;
+ sisGlyphBltClipped (pDrawable, pGC, xInit, yInit, nglyph, ppci, imageBlt);
+ case rgnOUT:
+ return TRUE;
+ }
+
+ if (widthGlyph <= 6)
+ glyphsPer = 5;
+ else if (widthGlyph <= 8)
+ glyphsPer = 4;
+ else if (widthGlyph <= 10)
+ glyphsPer = 3;
+ else if (widthGlyph <= 16)
+ glyphsPer = 2;
+ else
+ glyphsPer = 1;
+
+ widthGlyphs = widthGlyph * glyphsPer;
+ widthBlt = widthGlyphs;
+
+ /* make sure scanlines are 32-bit aligned */
+ if (widthGlyphs <= 24)
+ widthBlt = 25;
+
+ cmd = (SIS_CMD_ENH_COLOR_EXPAND |
+ SIS_CMD_SRC_SCREEN |
+ SIS_CMD_PAT_FG |
+ SIS_CMD_INC_X |
+ SIS_CMD_INC_Y);
+
+ if (imageBlt)
+ {
+ sis->u.general.clip_right = bbox.x2;
+ cmd |= ((sisBltRop[GXcopy] << 8) |
+ SIS_CMD_OPAQUE |
+ SIS_CMD_RECT_CLIP_ENABLE);
+ }
+ else
+ {
+ cmd |= ((sisBltRop[pGC->alu] << 8) |
+ SIS_CMD_TRANSPARENT |
+ SIS_CMD_RECT_CLIP_DISABLE);
+ }
+
+ sisExpandInit (pDrawable->pScreen, &expand);
+
+ sis->u.general.src_fg = pGC->fgPixel;
+ sis->u.general.src_bg = pGC->bgPixel;
+
+ bwidth = (widthBlt + 7) >> 3;
+
+ nb = bwidth * h;
+
+#define LoopIt(count, loadup, fetch) \
+ while (nglyph >= count) \
+ { \
+ nglyph -= count; \
+ dst = sisExpandAlloc (&expand, nb); \
+ sis->u.general.src_base = expand.off; \
+ sis->u.general.src_pitch = 0; \
+ sis->u.general.src_x = 0; \
+ sis->u.general.src_y = 0; \
+ sis->u.general.dst_x = x; \
+ sis->u.general.dst_y = y; \
+ sis->u.general.rect_width = widthBlt; \
+ sis->u.general.rect_height = h; \
+ x += widthGlyphs; \
+ loadup \
+ lwTmp = h; \
+ while (lwTmp--) { \
+ tmp = fetch; \
+ SisInvertBits32(tmp); \
+ *dst++ = tmp; \
+ } \
+ sis->u.general.command = cmd; \
+ }
+
+ switch (glyphsPer) {
+ case 5:
+ LoopIt(5,
+ char1 = (unsigned long *) (*ppci++)->bits;
+ char2 = (unsigned long *) (*ppci++)->bits;
+ char3 = (unsigned long *) (*ppci++)->bits;
+ char4 = (unsigned long *) (*ppci++)->bits;
+ char5 = (unsigned long *) (*ppci++)->bits;,
+ (*char1++ | ((*char2++ | ((*char3++ | ((*char4++ | (*char5++
+ << widthGlyph))
+ << widthGlyph))
+ << widthGlyph))
+ << widthGlyph)));
+ break;
+ case 4:
+ LoopIt(4,
+ char1 = (unsigned long *) (*ppci++)->bits;
+ char2 = (unsigned long *) (*ppci++)->bits;
+ char3 = (unsigned long *) (*ppci++)->bits;
+ char4 = (unsigned long *) (*ppci++)->bits;,
+ (*char1++ | ((*char2++ | ((*char3++ | (*char4++
+ << widthGlyph))
+ << widthGlyph))
+ << widthGlyph)));
+ break;
+ case 3:
+ LoopIt(3,
+ char1 = (unsigned long *) (*ppci++)->bits;
+ char2 = (unsigned long *) (*ppci++)->bits;
+ char3 = (unsigned long *) (*ppci++)->bits;,
+ (*char1++ | ((*char2++ | (*char3++ << widthGlyph)) << widthGlyph)));
+ break;
+ case 2:
+ LoopIt(2,
+ char1 = (unsigned long *) (*ppci++)->bits;
+ char2 = (unsigned long *) (*ppci++)->bits;,
+ (*char1++ | (*char2++ << widthGlyph)));
+ break;
+ }
+
+ widthBlt = (widthGlyph + 31) & ~31;
+
+ bwidth = widthBlt >> 3;
+
+ nb = bwidth * h;
+
+ lw = (widthBlt >> 5) * h;
+
+ while (nglyph--)
+ {
+ dst = (CARD32 *) sisExpandAlloc (&expand, nb);
+ char1 = (CARD32 *) (*ppci++)->bits;
+ sis->u.general.src_base = expand.off;
+ sis->u.general.src_pitch = 0;
+ sis->u.general.src_x = 0;
+ sis->u.general.src_y = 0;
+ sis->u.general.dst_x = x;
+ sis->u.general.dst_y = y;
+ sis->u.general.rect_width = widthBlt;
+ sis->u.general.rect_height = h;
+ lwTmp = lw;
+ while (lwTmp--)
+ {
+ tmp = *char1++;
+ SisInvertBits32 (tmp);
+ *dst++ = tmp;
+ }
+ sis->u.general.command = cmd;
+ x += widthGlyph;
+ }
+ if (imageBlt)
+ sis->u.general.clip_right = pScreenPriv->screen->width;
+ _sisWaitIdleEmpty(sis);
+ return TRUE;
+}
+
+Bool
+sisGlyphBlt(DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x,
+ int y,
+ unsigned int nglyph,
+ CharInfoPtr *ppciInit,
+ Bool imageBlt)
+{
+ SetupSis(pDrawable->pScreen);
+ int height;
+ int width;
+ int xBack, yBack;
+ int hBack, wBack;
+ int nb, bwidth, nl;
+ FontPtr pfont = pGC->font;
+ CharInfoPtr pci;
+ CARD8 *bits8, b;
+ CARD16 *bits16;
+ CARD32 *bits32;
+ BoxPtr extents;
+ BoxRec bbox;
+ CharInfoPtr *ppci;
+ unsigned char alu;
+ CARD32 cmd;
+ SisExpand expand;
+ CARD32 *dst, d;
+ int nbytes;
+ int shift;
+
+ x += pDrawable->x;
+ y += pDrawable->y;
+
+ /* compute an approximate (but covering) bounding box */
+ ppci = ppciInit;
+ width = 0;
+ height = nglyph;
+ while (height--)
+ width += (*ppci++)->metrics.characterWidth;
+ if (width < 0)
+ {
+ bbox.x1 = x + width;
+ bbox.x2 = x;
+ }
+ else
+ {
+ bbox.x1 = x;
+ bbox.x2 = x + width;
+ }
+ width = FONTMINBOUNDS(pfont,leftSideBearing);
+ if (width < 0)
+ bbox.x1 += width;
+ width = FONTMAXBOUNDS(pfont, rightSideBearing) - FONTMINBOUNDS(pfont, characterWidth);
+ if (width > 0)
+ bbox.x2 += width;
+ bbox.y1 = y - FONTMAXBOUNDS(pfont,ascent);
+ bbox.y2 = y + FONTMAXBOUNDS(pfont,descent);
+
+ switch (RECT_IN_REGION(pGC->pScreen, fbGetCompositeClip(pGC), &bbox))
+ {
+ case rgnPART:
+ if (bbox.x1 < 0 || bbox.y1 < 0)
+ return FALSE;
+ sisGlyphBltClipped (pDrawable, pGC,
+ x - pDrawable->x, y - pDrawable->y,
+ nglyph, ppciInit, imageBlt);
+ case rgnOUT:
+ return TRUE;
+ }
+
+ if (imageBlt)
+ {
+ xBack = x;
+ yBack = y - FONTASCENT(pGC->font);
+ wBack = 0;
+ hBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
+ if (hBack)
+ {
+ height = nglyph;
+ ppci = ppciInit;
+ while (height--)
+ wBack += (*ppci++)->metrics.characterWidth;
+ }
+ if (wBack < 0)
+ {
+ xBack = xBack + wBack;
+ wBack = -wBack;
+ }
+ if (hBack < 0)
+ {
+ yBack = yBack + hBack;
+ hBack = -hBack;
+ }
+ alu = GXcopy;
+ }
+ else
+ {
+ wBack = 0;
+ alu = pGC->alu;
+ }
+
+ if (wBack)
+ {
+ _sisSetSolidRect (sis, pGC->bgPixel, GXcopy, cmd);
+ _sisRect (sis, xBack, yBack, wBack, hBack, cmd);
+ }
+
+ sisExpandInit (pDrawable->pScreen, &expand);
+
+ sis->u.general.src_fg = pGC->fgPixel;
+
+ cmd = (SIS_CMD_ENH_COLOR_EXPAND |
+ SIS_CMD_SRC_SCREEN |
+ SIS_CMD_PAT_FG |
+ (sisBltRop[alu] << 8) |
+ SIS_CMD_INC_X |
+ SIS_CMD_INC_Y |
+ SIS_CMD_RECT_CLIP_DISABLE |
+ SIS_CMD_TRANSPARENT);
+
+ ppci = ppciInit;
+ while (nglyph--)
+ {
+ pci = *ppci++;
+ height = pci->metrics.ascent + pci->metrics.descent;
+ width = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing;
+ /*
+ * For glyphs wider than 16 pixels, expand the blt to the nearest multiple
+ * of 32; this allows the scanlines to be padded to a 32-bit boundary
+ * instead of requiring byte packing
+ */
+ if (width > 16)
+ width = (width + 31) & ~31;
+ bwidth = (width + 7) >> 3;
+ nb = bwidth * height;
+ if (nb)
+ {
+ dst = sisExpandAlloc (&expand, nb);
+
+ sis->u.general.src_base = expand.off;
+ sis->u.general.src_pitch = 0;
+ sis->u.general.src_x = 0;
+ sis->u.general.src_y = 0;
+ sis->u.general.dst_x = x + pci->metrics.leftSideBearing;
+ sis->u.general.dst_y = y - pci->metrics.ascent;
+ sis->u.general.rect_width = width;
+ sis->u.general.rect_height = height;
+ switch (bwidth) {
+ case 1:
+ bits8 = (CARD8 *) pci->bits;
+ while (height >= 4)
+ {
+ d = (bits8[0] | (bits8[4] << 8) |
+ (bits8[8] << 16) | (bits8[12] << 24));
+ SisInvertBits32(d);
+ *dst++ = d;
+ bits8 += 16;
+ height -= 4;
+ }
+ if (height)
+ {
+ switch (height) {
+ case 3:
+ d = bits8[0] | (bits8[4] << 8) | (bits8[8] << 16);
+ break;
+ case 2:
+ d = bits8[0] | (bits8[4] << 8);
+ break;
+ case 1:
+ d = bits8[0];
+ break;
+ }
+ SisInvertBits32(d);
+ *dst++ = d;
+ }
+ break;
+ case 2:
+ bits16 = (CARD16 *) pci->bits;
+ while (height >= 2)
+ {
+ d = bits16[0] | (bits16[2] << 16);
+ SisInvertBits32(d);
+ *dst++ = d;
+ bits16 += 4;
+ height -= 2;
+ }
+ if (height)
+ {
+ d = bits16[0];
+ SisInvertBits32(d);
+ *dst++ = d;
+ }
+ break;
+ default:
+ nb >>= 2;
+ bits32 = (CARD32 *) pci->bits;
+ while (nb--)
+ {
+ d = *bits32++;
+ SisInvertBits32 (d);
+ *dst++ = d;
+ }
+ }
+ sis->u.general.command = cmd;
+ }
+ x += pci->metrics.characterWidth;
+ }
+ _sisWaitIdleEmpty(sis);
+ return TRUE;
+}
+/*
+ * Blt glyphs using Sis image transfer register, this does both
+ * poly glyph blt and image glyph blt (when pglyphBase == 1)
+ */
+
+void
+sisPolyGlyphBlt (DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x, int y,
+ unsigned int nglyph,
+ CharInfoPtr *ppci,
+ pointer pglyphBase)
+{
+ FbBits depthMask;
+
+ depthMask = FbFullMask (pDrawable->depth);
+ if ((pGC->planemask & depthMask) == depthMask &&
+ pGC->fillStyle == FillSolid)
+ {
+ if (TERMINALFONT(pGC->font))
+ {
+ if (sisTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, FALSE))
+ return;
+ }
+ else
+ {
+ if (sisGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, FALSE))
+ return;
+ }
+ }
+ fbPolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+}
+
+void
+sisImageGlyphBlt (DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x, int y,
+ unsigned int nglyph,
+ CharInfoPtr *ppci,
+ pointer pglyphBase)
+{
+ FbBits depthMask;
+
+ depthMask = FbFullMask (pDrawable->depth);
+ if ((pGC->planemask & depthMask) == depthMask)
+ {
+ if (TERMINALFONT(pGC->font))
+ {
+ if (sisTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, TRUE))
+ return;
+ }
+ else
+ {
+ if (sisGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, TRUE))
+ return;
+ }
+ }
+ fbImageGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+}
+
+#define sourceInvarient(alu) (((alu) & 3) == (((alu) >> 2) & 3))
+
+#define sisPatternDimOk(d) ((d) <= 8 && (((d) & ((d) - 1)) == 0))
+
+BOOL
+sisFillOk (GCPtr pGC)
+{
+ FbBits depthMask;
+
+ depthMask = FbFullMask(pGC->depth);
+ if ((pGC->planemask & depthMask) != depthMask)
+ return FALSE;
+ switch (pGC->fillStyle) {
+ case FillSolid:
+ return TRUE;
+ case FillTiled:
+ return (sisPatternDimOk (pGC->tile.pixmap->drawable.width) &&
+ sisPatternDimOk (pGC->tile.pixmap->drawable.height));
+ case FillStippled:
+ case FillOpaqueStippled:
+ return (sisPatternDimOk (pGC->stipple->drawable.width) &&
+ sisPatternDimOk (pGC->stipple->drawable.height));
+ }
+}
+
+CARD32
+sisStipplePrepare (DrawablePtr pDrawable, GCPtr pGC)
+{
+ SetupSis(pGC->pScreen);
+ PixmapPtr pStip = pGC->stipple;
+ int stipHeight = pStip->drawable.height;
+ int xRot, yRot;
+ int rot, stipX, stipY;
+ FbStip *stip, *stipEnd, bits;
+ FbStride stipStride;
+ int stipBpp;
+ int y;
+ CARD32 cmd;
+
+ xRot = pGC->patOrg.x + pDrawable->x;
+ yRot = pGC->patOrg.y + pDrawable->y;
+ modulus (- yRot, stipHeight, stipY);
+ modulus (- xRot, FB_UNIT, stipX);
+ rot = stipX;
+
+ fbGetStipDrawable (&pStip->drawable, stip, stipStride, stipBpp);
+ for (y = 0; y < 8; y++)
+ {
+ bits = stip[stipY<<1];
+ FbRotLeft(bits, rot);
+ SisInvertBits32(bits);
+ sis->u.general.mask[y] = (CARD8) bits;
+ stipY++;
+ if (stipY == stipHeight)
+ stipY = 0;
+ }
+ sis->u.general.pattern_fg = pGC->fgPixel;
+
+ cmd = (SIS_CMD_BITBLT |
+ SIS_CMD_SRC_SCREEN |
+ SIS_CMD_PAT_MONO |
+ (sisPatRop[pGC->alu] << 8) |
+ SIS_CMD_INC_X |
+ SIS_CMD_INC_Y |
+ SIS_CMD_RECT_CLIP_DISABLE |
+ SIS_CMD_RECT_CLIP_DONT_MERGE);
+ if (pGC->fillStyle == FillOpaqueStippled)
+ {
+ sis->u.general.pattern_bg = pGC->bgPixel;
+ cmd |= SIS_CMD_OPAQUE;
+ }
+ else
+ cmd |= SIS_CMD_TRANSPARENT;
+ return cmd;
+}
+
+CARD32
+sisTilePrepare (PixmapPtr pTile, int xRot, int yRot, CARD8 alu)
+{
+ SetupSis(pTile->drawable.pScreen);
+ int tileHeight = pTile->drawable.height;
+ int tileWidth = pTile->drawable.width;
+ FbBits *tile;
+ FbStride tileStride;
+ int tileBpp;
+
+ fbGetDrawable (&pTile->drawable, tile, tileStride, tileBpp);
+
+ /*
+ * Tile the pattern register
+ */
+ fbTile ((FbBits *) sis->u.general.pattern,
+ (8 * tileBpp) >> FB_SHIFT,
+ 0,
+
+ 8 * tileBpp, 8,
+
+ tile,
+ tileStride,
+ tileWidth * tileBpp,
+ tileHeight,
+ GXcopy, FB_ALLONES, tileBpp,
+ xRot * tileBpp,
+ yRot);
+
+ return (SIS_CMD_BITBLT |
+ SIS_CMD_SRC_SCREEN |
+ SIS_CMD_PAT_PATTERN |
+ (sisPatRop[alu] << 8) |
+ SIS_CMD_INC_X |
+ SIS_CMD_INC_Y |
+ SIS_CMD_RECT_CLIP_DISABLE |
+ SIS_CMD_RECT_CLIP_DONT_MERGE);
+}
+
+void
+sisFillBoxSolid (DrawablePtr pDrawable, int nBox, BoxPtr pBox,
+ unsigned long pixel, int alu)
+{
+ SetupSis(pDrawable->pScreen);
+ CARD32 cmd;
+
+ _sisSetSolidRect(sis,pixel,alu,cmd);
+
+ while (nBox--)
+ {
+ _sisRect(sis,pBox->x1,pBox->y1,pBox->x2-pBox->x1,pBox->y2-pBox->y1,cmd);
+ pBox++;
+ }
+ _sisWaitIdleEmpty(sis);
+}
+
+void
+sisFillBoxStipple (DrawablePtr pDrawable, GCPtr pGC,
+ int nBox, BoxPtr pBox)
+{
+ SetupSis(pDrawable->pScreen);
+ CARD32 cmd;
+
+ cmd = sisStipplePrepare (pDrawable, pGC);
+
+ while (nBox--)
+ {
+ _sisRect(sis,pBox->x1,pBox->y1,pBox->x2-pBox->x1,pBox->y2-pBox->y1,cmd);
+ pBox++;
+ }
+ _sisWaitIdleEmpty (sis);
+}
+
+void
+sisFillBoxTiled (DrawablePtr pDrawable,
+ int nBox, BoxPtr pBox,
+ PixmapPtr pTile, int xRot, int yRot, CARD8 alu)
+{
+ SetupSis (pDrawable->pScreen);
+ CARD32 cmd;
+
+ cmd = sisTilePrepare (pTile, xRot, yRot, alu);
+
+ while (nBox--)
+ {
+ _sisRect(sis,pBox->x1,pBox->y1,pBox->x2-pBox->x1,pBox->y2-pBox->y1,cmd);
+ pBox++;
+ }
+ _sisWaitIdleEmpty (sis);
+}
+
+/*
+ sisDoBitBlt
+ =============
+ Bit Blit for all window to window blits.
+*/
+
+void
+sisCopyNtoN (DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ BoxPtr pbox,
+ int nbox,
+ int dx,
+ int dy,
+ Bool reverse,
+ Bool upsidedown,
+ Pixel bitplane,
+ void *closure)
+{
+ SetupSis(pDstDrawable->pScreen);
+ int srcX, srcY, dstX, dstY;
+ int w, h;
+ CARD32 flags;
+ CARD32 cmd;
+ CARD8 alu;
+
+ if (pGC)
+ {
+ alu = pGC->alu;
+ if (sourceInvarient (pGC->alu))
+ {
+ sisFillBoxSolid (pDstDrawable, nbox, pbox, 0, pGC->alu);
+ return;
+ }
+ }
+ else
+ alu = GXcopy;
+
+ _sisSetBlt(sis,alu,cmd);
+ while (nbox--)
+ {
+ w = pbox->x2 - pbox->x1;
+ h = pbox->y2 - pbox->y1;
+ flags = 0;
+ if (reverse)
+ {
+ dstX = pbox->x2 - 1;
+ }
+ else
+ {
+ dstX = pbox->x1;
+ flags |= SIS_CMD_INC_X;
+ }
+ srcX = dstX + dx;
+
+ if (upsidedown)
+ {
+ dstY = pbox->y2 - 1;
+ }
+ else
+ {
+ dstY = pbox->y1;
+ flags |= SIS_CMD_INC_Y;
+ }
+ srcY = dstY + dy;
+
+ _sisBlt (sis, srcX, srcY, dstX, dstY, w, h, cmd|flags);
+ pbox++;
+ }
+ _sisWaitIdleEmpty(sis);
+}
+
+RegionPtr
+sisCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
+ int srcx, int srcy, int width, int height, int dstx, int dsty)
+{
+ KdScreenPriv(pDstDrawable->pScreen);
+ FbBits depthMask;
+
+ depthMask = FbFullMask (pDstDrawable->depth);
+ if ((pGC->planemask & depthMask) == depthMask &&
+ pSrcDrawable->type == DRAWABLE_WINDOW &&
+ pDstDrawable->type == DRAWABLE_WINDOW)
+ {
+ return fbDoCopy (pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy, width, height,
+ dstx, dsty, sisCopyNtoN, 0, 0);
+ }
+ return fbCopyArea (pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy, width, height, dstx, dsty);
+}
+
+typedef struct _sis1toNargs {
+ unsigned long copyPlaneFG, copyPlaneBG;
+} sis1toNargs;
+
+void
+_sisStipple (ScreenPtr pScreen,
+ FbStip *psrcBase,
+ FbStride widthSrc,
+ CARD8 alu,
+ int srcx,
+ int srcy,
+ int dstx,
+ int dsty,
+ int width,
+ int height)
+{
+ SetupSis(pScreen);
+ FbStip *psrcLine, *psrc;
+ FbStride widthRest;
+ FbStip bits, tmp, lastTmp;
+ int leftShift, rightShift;
+ int nl, nlMiddle;
+ int r;
+ SisExpand expand;
+ CARD32 *dst;
+ int hthis;
+ int hper;
+ int bwidth;
+ CARD32 cmd;
+
+ sisExpandInit (pScreen, &expand);
+
+ /* Compute blt address and parameters */
+ psrc = psrcBase + srcy * widthSrc + (srcx >> 5);
+ nlMiddle = (width + 31) >> 5;
+ leftShift = srcx & 0x1f;
+ rightShift = 32 - leftShift;
+ widthRest = widthSrc - nlMiddle;
+
+ cmd = (SIS_CMD_ENH_COLOR_EXPAND |
+ SIS_CMD_SRC_SCREEN |
+ SIS_CMD_PAT_FG |
+ (sisBltRop[alu] << 8) |
+ SIS_CMD_INC_X |
+ SIS_CMD_INC_Y |
+ SIS_CMD_OPAQUE |
+ SIS_CMD_RECT_CLIP_ENABLE);
+
+ if (leftShift != 0)
+ widthRest--;
+
+ sis->u.general.src_x = 0;
+ sis->u.general.src_y = 0;
+ sis->u.general.dst_x = dstx;
+ sis->u.general.rect_width = (width + 31) & ~31;
+ sis->u.general.clip_right = (dstx + width);
+
+ bwidth = nlMiddle << 2;
+ hper = SIS_PATTERN_INC / bwidth;
+ if (hper == 0)
+ hper = 1;
+
+ while (height)
+ {
+ hthis = hper;
+ if (hthis > height)
+ hthis = height;
+ dst = sisExpandAlloc (&expand, bwidth * hthis);
+ sis->u.general.src_base = expand.off;
+ sis->u.general.dst_y = dsty;
+ sis->u.general.rect_height = hthis;
+
+ dsty += hthis;
+ height -= hthis;
+
+ if (leftShift == 0)
+ {
+ while (hthis--)
+ {
+ nl = nlMiddle;
+ while (nl--)
+ {
+ tmp = *psrc++;
+ SisInvertBits32(tmp);
+ *dst++ = tmp;
+ }
+ psrc += widthRest;
+ }
+ }
+ else
+ {
+ while (hthis--)
+ {
+ bits = *psrc++;
+ nl = nlMiddle;
+ while (nl--)
+ {
+ tmp = FbStipLeft(bits, leftShift);
+ bits = *psrc++;
+ tmp |= FbStipRight(bits, rightShift);
+ SisInvertBits32(tmp);
+ *dst++ = tmp;
+ }
+ psrc += widthRest;
+ }
+ }
+ sis->u.general.command = cmd;
+ }
+ sis->u.general.clip_right = pScreenPriv->screen->width;
+}
+
+void
+sisCopy1toN (DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ BoxPtr pbox,
+ int nbox,
+ int dx,
+ int dy,
+ Bool reverse,
+ Bool upsidedown,
+ Pixel bitplane,
+ void *closure)
+{
+ SetupSis(pDstDrawable->pScreen);
+
+ sis1toNargs *args = closure;
+ int dstx, dsty;
+ FbStip *psrcBase;
+ FbStride widthSrc;
+ int srcBpp;
+
+ if (sourceInvarient (pGC->alu))
+ {
+ sisFillBoxSolid (pDstDrawable, nbox, pbox,
+ pGC->bgPixel, pGC->alu);
+ return;
+ }
+
+ fbGetStipDrawable (pSrcDrawable, psrcBase, widthSrc, srcBpp);
+
+ sis->u.general.src_fg = args->copyPlaneFG;
+ sis->u.general.src_bg = args->copyPlaneBG;
+
+ while (nbox--)
+ {
+ dstx = pbox->x1;
+ dsty = pbox->y1;
+
+ _sisStipple (pDstDrawable->pScreen,
+ psrcBase, widthSrc,
+ pGC->alu,
+ dstx + dx, dsty + dy,
+ dstx, dsty,
+ pbox->x2 - dstx, pbox->y2 - dsty);
+ pbox++;
+ }
+ _sisWaitIdleEmpty (sis);
+}
+
+RegionPtr
+sisCopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
+ int srcx, int srcy, int width, int height,
+ int dstx, int dsty, unsigned long bitPlane)
+{
+ KdScreenPriv (pDstDrawable->pScreen);
+ RegionPtr ret;
+ sis1toNargs args;
+ FbBits depthMask;
+
+ depthMask = FbFullMask (pDstDrawable->depth);
+ if ((pGC->planemask & depthMask) == depthMask &&
+ pDstDrawable->type == DRAWABLE_WINDOW &&
+ pSrcDrawable->depth == 1)
+ {
+ args.copyPlaneFG = pGC->fgPixel;
+ args.copyPlaneBG = pGC->bgPixel;
+ return fbDoCopy (pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy, width, height,
+ dstx, dsty, sisCopy1toN, bitPlane, &args);
+ }
+ return fbCopyPlane(pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy, width, height,
+ dstx, dsty, bitPlane);
+}
+
+void
+sisFillSpans (DrawablePtr pDrawable, GCPtr pGC, int n,
+ DDXPointPtr ppt, int *pwidth, int fSorted)
+{
+ SetupSis(pDrawable->pScreen);
+ DDXPointPtr pptFree;
+ FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC);
+ int *pwidthFree;/* copies of the pointers to free */
+ CARD32 cmd;
+ int nTmp;
+ INT16 x, y;
+ int width;
+
+ if (!sisFillOk (pGC))
+ {
+ fbFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted);
+ return;
+ }
+ nTmp = n * miFindMaxBand(fbGetCompositeClip(pGC));
+ pwidthFree = (int *)ALLOCATE_LOCAL(nTmp * sizeof(int));
+ pptFree = (DDXPointRec *)ALLOCATE_LOCAL(nTmp * sizeof(DDXPointRec));
+ if(!pptFree || !pwidthFree)
+ {
+ if (pptFree) DEALLOCATE_LOCAL(pptFree);
+ if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree);
+ return;
+ }
+ n = miClipSpans(fbGetCompositeClip(pGC),
+ ppt, pwidth, n,
+ pptFree, pwidthFree, fSorted);
+ pwidth = pwidthFree;
+ ppt = pptFree;
+ switch (pGC->fillStyle) {
+ case FillSolid:
+ _sisSetSolidRect(sis,pGC->fgPixel,pGC->alu,cmd);
+ break;
+ case FillTiled:
+ cmd = sisTilePrepare (pGC->tile.pixmap,
+ pGC->patOrg.x + pDrawable->x,
+ pGC->patOrg.y + pDrawable->y,
+ pGC->alu);
+ break;
+ default:
+ cmd = sisStipplePrepare (pDrawable, pGC);
+ break;
+ }
+ while (n--)
+ {
+ x = ppt->x;
+ y = ppt->y;
+ ppt++;
+ width = *pwidth++;
+ if (width)
+ {
+ _sisRect(sis,x,y,width,1,cmd);
+ }
+ }
+ _sisWaitIdleEmpty (sis);
+ DEALLOCATE_LOCAL(pptFree);
+ DEALLOCATE_LOCAL(pwidthFree);
+}
+
+#define NUM_STACK_RECTS 1024
+
+void
+sisPolyFillRect (DrawablePtr pDrawable, GCPtr pGC,
+ int nrectFill, xRectangle *prectInit)
+{
+ SetupSis(pDrawable->pScreen);
+ xRectangle *prect;
+ RegionPtr prgnClip;
+ register BoxPtr pbox;
+ register BoxPtr pboxClipped;
+ BoxPtr pboxClippedBase;
+ BoxPtr pextent;
+ BoxRec stackRects[NUM_STACK_RECTS];
+ FbGCPrivPtr fbPriv = fbGetGCPrivate (pGC);
+ int numRects;
+ int n;
+ int xorg, yorg;
+ int x, y;
+
+ if (!sisFillOk (pGC))
+ {
+ fbPolyFillRect (pDrawable, pGC, nrectFill, prectInit);
+ return;
+ }
+ prgnClip = fbGetCompositeClip(pGC);
+ xorg = pDrawable->x;
+ yorg = pDrawable->y;
+
+ if (xorg || yorg)
+ {
+ prect = prectInit;
+ n = nrectFill;
+ while(n--)
+ {
+ prect->x += xorg;
+ prect->y += yorg;
+ prect++;
+ }
+ }
+
+ prect = prectInit;
+
+ numRects = REGION_NUM_RECTS(prgnClip) * nrectFill;
+ if (numRects > NUM_STACK_RECTS)
+ {
+ pboxClippedBase = (BoxPtr)ALLOCATE_LOCAL(numRects * sizeof(BoxRec));
+ if (!pboxClippedBase)
+ return;
+ }
+ else
+ pboxClippedBase = stackRects;
+
+ pboxClipped = pboxClippedBase;
+
+ if (REGION_NUM_RECTS(prgnClip) == 1)
+ {
+ int x1, y1, x2, y2, bx2, by2;
+
+ pextent = REGION_RECTS(prgnClip);
+ x1 = pextent->x1;
+ y1 = pextent->y1;
+ x2 = pextent->x2;
+ y2 = pextent->y2;
+ while (nrectFill--)
+ {
+ if ((pboxClipped->x1 = prect->x) < x1)
+ pboxClipped->x1 = x1;
+
+ if ((pboxClipped->y1 = prect->y) < y1)
+ pboxClipped->y1 = y1;
+
+ bx2 = (int) prect->x + (int) prect->width;
+ if (bx2 > x2)
+ bx2 = x2;
+ pboxClipped->x2 = bx2;
+
+ by2 = (int) prect->y + (int) prect->height;
+ if (by2 > y2)
+ by2 = y2;
+ pboxClipped->y2 = by2;
+
+ prect++;
+ if ((pboxClipped->x1 < pboxClipped->x2) &&
+ (pboxClipped->y1 < pboxClipped->y2))
+ {
+ pboxClipped++;
+ }
+ }
+ }
+ else
+ {
+ int x1, y1, x2, y2, bx2, by2;
+
+ pextent = REGION_EXTENTS(pGC->pScreen, prgnClip);
+ x1 = pextent->x1;
+ y1 = pextent->y1;
+ x2 = pextent->x2;
+ y2 = pextent->y2;
+ while (nrectFill--)
+ {
+ BoxRec box;
+
+ if ((box.x1 = prect->x) < x1)
+ box.x1 = x1;
+
+ if ((box.y1 = prect->y) < y1)
+ box.y1 = y1;
+
+ bx2 = (int) prect->x + (int) prect->width;
+ if (bx2 > x2)
+ bx2 = x2;
+ box.x2 = bx2;
+
+ by2 = (int) prect->y + (int) prect->height;
+ if (by2 > y2)
+ by2 = y2;
+ box.y2 = by2;
+
+ prect++;
+
+ if ((box.x1 >= box.x2) || (box.y1 >= box.y2))
+ continue;
+
+ n = REGION_NUM_RECTS (prgnClip);
+ pbox = REGION_RECTS(prgnClip);
+
+ /* clip the rectangle to each box in the clip region
+ this is logically equivalent to calling Intersect()
+ */
+ while(n--)
+ {
+ pboxClipped->x1 = max(box.x1, pbox->x1);
+ pboxClipped->y1 = max(box.y1, pbox->y1);
+ pboxClipped->x2 = min(box.x2, pbox->x2);
+ pboxClipped->y2 = min(box.y2, pbox->y2);
+ pbox++;
+
+ /* see if clipping left anything */
+ if(pboxClipped->x1 < pboxClipped->x2 &&
+ pboxClipped->y1 < pboxClipped->y2)
+ {
+ pboxClipped++;
+ }
+ }
+ }
+ }
+ if (pboxClipped != pboxClippedBase)
+ {
+ switch (pGC->fillStyle) {
+ case FillSolid:
+ sisFillBoxSolid(pDrawable,
+ pboxClipped-pboxClippedBase, pboxClippedBase,
+ pGC->fgPixel, pGC->alu);
+ break;
+ case FillTiled:
+ sisFillBoxTiled(pDrawable,
+ pboxClipped-pboxClippedBase, pboxClippedBase,
+ pGC->tile.pixmap,
+ pGC->patOrg.x + pDrawable->x,
+ pGC->patOrg.y + pDrawable->y,
+ pGC->alu);
+ break;
+ case FillStippled:
+ case FillOpaqueStippled:
+ sisFillBoxStipple (pDrawable, pGC,
+ pboxClipped-pboxClippedBase, pboxClippedBase);
+ break;
+ }
+ }
+ if (pboxClippedBase != stackRects)
+ DEALLOCATE_LOCAL(pboxClippedBase);
+}
+
+static const GCOps sisOps = {
+ sisFillSpans,
+ fbSetSpans,
+ fbPutImage,
+ sisCopyArea,
+ sisCopyPlane,
+ fbPolyPoint,
+ fbPolyLine,
+ fbPolySegment,
+ miPolyRectangle,
+ fbPolyArc,
+ miFillPolygon,
+ sisPolyFillRect,
+ fbPolyFillArc,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ sisImageGlyphBlt,
+ sisPolyGlyphBlt,
+ fbPushPixels,
+#ifdef NEED_LINEHELPER
+ ,NULL
+#endif
+};
+
+void
+sisValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable)
+{
+ FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC);
+
+ fbValidateGC (pGC, changes, pDrawable);
+
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ pGC->ops = (GCOps *) &sisOps;
+ else
+ pGC->ops = (GCOps *) &fbGCOps;
+}
+
+GCFuncs sisGCFuncs = {
+ sisValidateGC,
+ miChangeGC,
+ miCopyGC,
+ miDestroyGC,
+ miChangeClip,
+ miDestroyClip,
+ miCopyClip
+};
+
+int
+sisCreateGC (GCPtr pGC)
+{
+ if (!fbCreateGC (pGC))
+ return FALSE;
+
+ if (pGC->depth != 1)
+ pGC->funcs = &sisGCFuncs;
+
+ return TRUE;
+}
+
+void
+sisCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ KdScreenPriv(pScreen);
+ RegionRec rgnDst;
+ int dx, dy;
+ WindowPtr pwinRoot;
+
+ pwinRoot = WindowTable[pWin->drawable.pScreen->myNum];
+
+ dx = ptOldOrg.x - pWin->drawable.x;
+ dy = ptOldOrg.y - pWin->drawable.y;
+ REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
+
+ REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0);
+
+ REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
+
+ fbCopyRegion ((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot,
+ 0,
+ &rgnDst, dx, dy, sisCopyNtoN, 0, 0);
+
+ REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
+}
+
+void
+sisPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
+{
+ KdScreenPriv(pWin->drawable.pScreen);
+ PixmapPtr pTile;
+
+ if (!REGION_NUM_RECTS(pRegion))
+ return;
+ switch (what) {
+ case PW_BACKGROUND:
+ switch (pWin->backgroundState) {
+ case None:
+ return;
+ case ParentRelative:
+ do {
+ pWin = pWin->parent;
+ } while (pWin->backgroundState == ParentRelative);
+ (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion,
+ what);
+ return;
+ case BackgroundPixmap:
+ pTile = pWin->background.pixmap;
+ if (sisPatternDimOk (pTile->drawable.width) &&
+ sisPatternDimOk (pTile->drawable.height))
+ {
+ sisFillBoxTiled ((DrawablePtr)pWin,
+ (int)REGION_NUM_RECTS(pRegion),
+ REGION_RECTS(pRegion),
+ pTile,
+ pWin->drawable.x, pWin->drawable.y, GXcopy);
+ return;
+ }
+ break;
+ case BackgroundPixel:
+ sisFillBoxSolid((DrawablePtr)pWin,
+ (int)REGION_NUM_RECTS(pRegion),
+ REGION_RECTS(pRegion),
+ pWin->background.pixel, GXcopy);
+ return;
+ }
+ break;
+ case PW_BORDER:
+ if (pWin->borderIsPixel)
+ {
+ sisFillBoxSolid((DrawablePtr)pWin,
+ (int)REGION_NUM_RECTS(pRegion),
+ REGION_RECTS(pRegion),
+ pWin->border.pixel, GXcopy);
+ return;
+ }
+ else
+ {
+ pTile = pWin->border.pixmap;
+ if (sisPatternDimOk (pTile->drawable.width) &&
+ sisPatternDimOk (pTile->drawable.height))
+ {
+ sisFillBoxTiled ((DrawablePtr)pWin,
+ (int)REGION_NUM_RECTS(pRegion),
+ REGION_RECTS(pRegion),
+ pTile,
+ pWin->drawable.x, pWin->drawable.y, GXcopy);
+ return;
+ }
+ }
+ break;
+ }
+ fbPaintWindow (pWin, pRegion, what);
+}
+
+Bool
+sisDrawInit (ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ sisScreenInfo(pScreenPriv);
+
+ /*
+ * Replace various fb screen functions
+ */
+ pScreen->CreateGC = sisCreateGC;
+ pScreen->CopyWindow = sisCopyWindow;
+ pScreen->PaintWindowBackground = sisPaintWindow;
+ pScreen->PaintWindowBorder = sisPaintWindow;
+
+ return TRUE;
+}
+
+void
+sisDrawEnable (ScreenPtr pScreen)
+{
+ SetupSis(pScreen);
+ sisScreenInfo(pScreenPriv);
+ CARD32 cmd;
+ CARD32 base;
+ CARD16 stride;
+
+ base = pScreenPriv->screen->frameBuffer - sisc->frameBuffer;
+ stride = pScreenPriv->screen->byteStride;
+ _sisWaitIdleEmpty(sis);
+ sis->u.general.dst_base = base;
+ sis->u.general.dst_pitch = stride;
+ sis->u.general.dst_height = pScreenPriv->screen->height;
+ _sisClip (sis, 0, 0,
+ pScreenPriv->screen->width, pScreenPriv->screen->height);
+ _sisSetSolidRect(sis, pScreen->blackPixel, GXcopy, cmd);
+ _sisRect (sis, 0, 0,
+ pScreenPriv->screen->width, pScreenPriv->screen->height,
+ cmd);
+ _sisWaitIdleEmpty (sis);
+}
+
+void
+sisDrawDisable (ScreenPtr pScreen)
+{
+}
+
+void
+sisDrawFini (ScreenPtr pScreen)
+{
+}
diff --git a/hw/kdrive/sis530/sisdraw.h b/hw/kdrive/sis530/sisdraw.h
new file mode 100644
index 000000000..45868e9ba
--- /dev/null
+++ b/hw/kdrive/sis530/sisdraw.h
@@ -0,0 +1,183 @@
+/*
+ * $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: $ */
+
+#ifndef _SISDRAW_H_
+#define _SISDRAW_H_
+
+#define SetupSis(s) KdScreenPriv(s); \
+ sisCardInfo(pScreenPriv); \
+ SisPtr sis = sisc->sis
+
+#define SIS_CMD_BITBLT (0)
+#define SIS_CMD_COLOR_EXPAND (1)
+#define SIS_CMD_ENH_COLOR_EXPAND (2)
+#define SIS_CMD_MULTI_SCANLINE (3)
+#define SIS_CMD_LINE (4)
+#define SIS_CMD_TRAPEZOID (5)
+#define SIS_CMD_TRANSPARENT_BITBLT (6)
+
+#define SIS_CMD_SRC_SCREEN (0 << 4)
+#define SIS_CMD_SRC_CPU (1 << 4)
+
+#define SIS_CMD_PAT_FG (0 << 6)
+#define SIS_CMD_PAT_PATTERN (1 << 6)
+#define SIS_CMD_PAT_MONO (2 << 6)
+
+/* 8->15 rop */
+
+#define SIS_CMD_DEC_X (0 << 16)
+#define SIS_CMD_INC_X (1 << 16)
+
+#define SIS_CMD_DEC_Y (0 << 17)
+#define SIS_CMD_INC_Y (1 << 17)
+
+#define SIS_CMD_RECT_CLIP_DISABLE (0 << 18)
+#define SIS_CMD_RECT_CLIP_ENABLE (1 << 18)
+
+#define SIS_CMD_OPAQUE (0 << 20)
+#define SIS_CMD_TRANSPARENT (1 << 20)
+
+#define SIS_CMD_RECT_CLIP_MERGE (0 << 26)
+#define SIS_CMD_RECT_CLIP_DONT_MERGE (1 << 26)
+
+#define SIS_STAT_2D_IDLE (1 << 31)
+#define SIS_STAT_3D_IDLE (1 << 30)
+#define SIS_STAT_EMPTY (1 << 29)
+#define SIS_STAT_CPU_BITBLT (0xf << 24)
+#define SIS_STAT_ENH_COLOR_EXPAND (1 << 23)
+#define SIS_STAT_AVAIL (0x1fff)
+
+extern CARD8 sisPatRop[16];
+extern CARD8 sisBltRop[16];
+
+#define _sisSetSolidRect(sis,pix,alu,cmd) {\
+ (sis)->u.general.pattern_fg = (pix); \
+ (cmd) = (SIS_CMD_BITBLT | \
+ SIS_CMD_SRC_SCREEN | \
+ SIS_CMD_PAT_FG | \
+ (sisPatRop[alu] << 8) | \
+ SIS_CMD_INC_X | \
+ SIS_CMD_INC_Y | \
+ SIS_CMD_RECT_CLIP_DISABLE | \
+ SIS_CMD_OPAQUE | \
+ SIS_CMD_RECT_CLIP_DONT_MERGE); \
+}
+
+#define _sisClip(sis,x1,y1,x2,y2) { \
+ (sis)->u.general.clip_left = (x1); \
+ (sis)->u.general.clip_top = (y1); \
+ (sis)->u.general.clip_right = (x2); \
+ (sis)->u.general.clip_bottom = (y2); \
+}
+
+#define _sisRect(sis,x,y,w,h,cmd) { \
+ (sis)->u.general.dst_x = (x); \
+ (sis)->u.general.dst_y = (y); \
+ (sis)->u.general.rect_width = (w); \
+ (sis)->u.general.rect_height = (h); \
+ (sis)->u.general.command = (cmd); \
+}
+
+#define _sisSetTransparentPlaneBlt(sis, alu, fg, cmd) { \
+ (sis)->u.general.src_fg = (fg); \
+ (cmd) = (SIS_CMD_ENH_COLOR_EXPAND | \
+ SIS_CMD_SRC_CPU | \
+ SIS_CMD_PAT_FG | \
+ (sisBltRop[alu] << 8) | \
+ SIS_CMD_INC_X | \
+ SIS_CMD_INC_Y | \
+ SIS_CMD_RECT_CLIP_DISABLE | \
+ SIS_CMD_TRANSPARENT | \
+ SIS_CMD_RECT_CLIP_DONT_MERGE); \
+}
+
+#define _sisSetOpaquePlaneBlt(sis, alu, fg, bg, cmd) { \
+ (sis)->u.general.src_fg = (fg); \
+ (sis)->u.general.src_bg = (bg); \
+ (cmd) = (SIS_CMD_ENH_COLOR_EXPAND | \
+ SIS_CMD_SRC_CPU | \
+ SIS_CMD_PAT_FG | \
+ (sisBltRop[alu] << 8) | \
+ SIS_CMD_INC_X | \
+ SIS_CMD_INC_Y | \
+ SIS_CMD_RECT_CLIP_DISABLE | \
+ SIS_CMD_OPAQUE | \
+ SIS_CMD_RECT_CLIP_DONT_MERGE); \
+}
+
+#define _sisPlaneBlt(sis,x,y,w,h,cmd) _sisSolidRect(sis,x,y,w,h,cmd)
+
+#define _sisSetBlt(sis,alu,cmd) { \
+ (sis)->u.general.src_base = (sis)->u.general.dst_base; \
+ (sis)->u.general.src_pitch = (sis)->u.general.dst_pitch; \
+ (cmd) = (SIS_CMD_RECT_CLIP_DONT_MERGE |\
+ (sisBltRop[alu] << 8) |\
+ SIS_CMD_PAT_FG |\
+ SIS_CMD_SRC_SCREEN |\
+ SIS_CMD_BITBLT); \
+}
+
+#define _sisBlt(sis,sx,sy,dx,dy,w,h,cmd) { \
+ (sis)->u.general.src_x = (sx); \
+ (sis)->u.general.src_y = (sy); \
+ (sis)->u.general.dst_x = (dx); \
+ (sis)->u.general.dst_y = (dy); \
+ (sis)->u.general.rect_width = (w); \
+ (sis)->u.general.rect_height = (h); \
+ (sis)->u.general.command = (cmd); \
+}
+
+#define SIS_IE (SIS_STAT_2D_IDLE|SIS_STAT_EMPTY)
+
+#define _sisWaitIdleEmpty(sis) \
+ while (((sis)->u.general.status & SIS_IE) != SIS_IE)
+
+/*
+ * Ok, so the Sis530 is broken -- it expects bitmaps to come MSB bit order,
+ * but it's willing to take them in LSB byte order. These macros
+ * flip bits around without flipping bytes. Instead of using a table
+ * and burning memory bandwidth, do them in place with the CPU.
+ */
+
+/* The MIPS compiler automatically places these constants in registers */
+#define SisInvertBits32(v) { \
+ v = ((v & 0x55555555) << 1) | ((v >> 1) & 0x55555555); \
+ v = ((v & 0x33333333) << 2) | ((v >> 2) & 0x33333333); \
+ v = ((v & 0x0f0f0f0f) << 4) | ((v >> 4) & 0x0f0f0f0f); \
+}
+
+#define SisInvertBits16(v) { \
+ v = ((v & 0x5555) << 1) | ((v >> 1) & 0x5555); \
+ v = ((v & 0x3333) << 2) | ((v >> 2) & 0x3333); \
+ v = ((v & 0x0f0f) << 4) | ((v >> 4) & 0x0f0f); \
+}
+
+#define SisInvertBits8(v) { \
+ v = ((v & 0x55) << 1) | ((v >> 1) & 0x55); \
+ v = ((v & 0x33) << 2) | ((v >> 2) & 0x33); \
+ v = ((v & 0x0f) << 4) | ((v >> 4) & 0x0f); \
+}
+
+#endif
diff --git a/hw/kdrive/sis530/sisio.c b/hw/kdrive/sis530/sisio.c
new file mode 100644
index 000000000..862c4d659
--- /dev/null
+++ b/hw/kdrive/sis530/sisio.c
@@ -0,0 +1,30 @@
+/*
+ * $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: $ */
+
+#ifdef linux
+#define extern
+#include <asm/io.h>
+#undef extern
+#endif
diff --git a/hw/kdrive/sis530/sisstub.c b/hw/kdrive/sis530/sisstub.c
new file mode 100644
index 000000000..9c3c30d86
--- /dev/null
+++ b/hw/kdrive/sis530/sisstub.c
@@ -0,0 +1,53 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999 SuSE, Inc.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+/* $XFree86: $ */
+
+#include "sis.h"
+
+void
+InitCard (char *name)
+{
+ KdCardAttr attr;
+ if (LinuxFindPci (0x1039, 0x6306, 0, &attr))
+ KdCardInfoAdd (&sisFuncs, &attr, 0);
+}
+
+void
+InitOutput (ScreenInfo *pScreenInfo, int argc, char **argv)
+{
+ KdInitOutput (pScreenInfo, argc, argv);
+}
+
+void
+InitInput (int argc, char **argv)
+{
+ KdInitInput (&Ps2MouseFuncs, &LinuxKeyboardFuncs);
+}
+
+void
+OsVendorInit (void)
+{
+ KdOsInit (&LinuxFuncs);
+}
diff --git a/hw/kdrive/src/kcmap.c b/hw/kdrive/src/kcmap.c
new file mode 100644
index 000000000..ed482a080
--- /dev/null
+++ b/hw/kdrive/src/kcmap.c
@@ -0,0 +1,231 @@
+/*
+ * $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 "kdrive.h"
+
+/*
+ * Put the entire colormap into the DAC
+ */
+
+void
+KdSetColormap (ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ ColormapPtr pCmap = pScreenPriv->pInstalledmap;
+ Pixel pixels[KD_MAX_PSEUDO_SIZE];
+ xrgb colors[KD_MAX_PSEUDO_SIZE];
+ xColorItem defs[KD_MAX_PSEUDO_SIZE];
+ int i;
+
+ if (!pScreenPriv->card->cfuncs->putColors)
+ return;
+ if (pScreenPriv->screen->depth > KD_MAX_PSEUDO_DEPTH)
+ return;
+
+ if (!pScreenPriv->enabled)
+ return;
+
+ if (!pCmap)
+ return;
+
+ /*
+ * Make DIX convert pixels into RGB values -- this handles
+ * true/direct as well as pseudo/static visuals
+ */
+
+ for (i = 0; i < (1 << pScreenPriv->screen->depth); i++)
+ pixels[i] = i;
+
+ QueryColors (pCmap, (1 << pScreenPriv->screen->depth), pixels, colors);
+
+ for (i = 0; i < (1 << pScreenPriv->screen->depth); i++)
+ {
+ defs[i].pixel = i;
+ defs[i].red = colors[i].red;
+ defs[i].green = colors[i].green;
+ defs[i].blue = colors[i].blue;
+ defs[i].flags = DoRed|DoGreen|DoBlue;
+ }
+
+ (*pScreenPriv->card->cfuncs->putColors) (pCmap->pScreen,
+ (1 << pScreenPriv->screen->depth),
+ defs);
+
+ /* recolor hardware cursor */
+ if (pScreenPriv->card->cfuncs->recolorCursor)
+ (*pScreenPriv->card->cfuncs->recolorCursor) (pCmap->pScreen, 0, 0);
+}
+
+/*
+ * When the hardware is enabled, save the hardware colors and store
+ * the current colormap
+ */
+void
+KdEnableColormap (ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ int i;
+
+ if (!pScreenPriv->card->cfuncs->putColors)
+ return;
+ if (pScreenPriv->screen->depth <= KD_MAX_PSEUDO_DEPTH)
+ {
+ for (i = 0; i < (1 << pScreenPriv->screen->depth); i++)
+ pScreenPriv->systemPalette[i].pixel = i;
+ (*pScreenPriv->card->cfuncs->getColors) (pScreen,
+ (1 << pScreenPriv->screen->depth),
+ pScreenPriv->systemPalette);
+ }
+ KdSetColormap (pScreen);
+}
+
+void
+KdDisableColormap (ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+
+ if (!pScreenPriv->card->cfuncs->putColors)
+ return;
+ if (pScreenPriv->screen->depth > KD_MAX_PSEUDO_DEPTH)
+ return;
+
+ (*pScreenPriv->card->cfuncs->putColors) (pScreen,
+ (1 << pScreenPriv->screen->depth),
+ pScreenPriv->systemPalette);
+}
+
+/*
+ * KdInstallColormap
+ *
+ * This function is called when the server receives a request to install a
+ * colormap or when the server needs to install one on its own, like when
+ * there's no window manager running and the user has moved the pointer over
+ * an X client window. It needs to build an identity Windows palette for the
+ * colormap and realize it into the Windows system palette.
+ */
+void
+KdInstallColormap (ColormapPtr pCmap)
+{
+ KdScreenPriv(pCmap->pScreen);
+
+ if (pCmap == pScreenPriv->pInstalledmap)
+ return;
+
+ /* Tell X clients that the installed colormap is going away. */
+ if (pScreenPriv->pInstalledmap)
+ WalkTree(pScreenPriv->pInstalledmap->pScreen, TellLostMap,
+ (pointer) &(pScreenPriv->pInstalledmap->mid));
+
+ /* Take note of the new installed colorscreen-> */
+ pScreenPriv->pInstalledmap = pCmap;
+
+ KdSetColormap (pCmap->pScreen);
+
+ /* Tell X clients of the new colorscreen-> */
+ WalkTree(pCmap->pScreen, TellGainedMap, (pointer) &(pCmap->mid));
+}
+
+/*
+ * KdUninstallColormap
+ *
+ * This function uninstalls a colormap by installing the default X colorscreen->
+ * The default X colormap itself cannot be uninstalled.
+ */
+void
+KdUninstallColormap (ColormapPtr pCmap)
+{
+ KdScreenPriv(pCmap->pScreen);
+
+ if (pCmap == pScreenPriv->pInstalledmap)
+ {
+ Colormap defMapID = pCmap->pScreen->defColormap;
+
+ if ((Colormap) pCmap->mid != defMapID)
+ {
+ ColormapPtr defMap = (ColormapPtr) LookupIDByType(defMapID,
+ RT_COLORMAP);
+ if (defMap)
+ (*pCmap->pScreen->InstallColormap)(defMap);
+ }
+ }
+}
+
+int
+KdListInstalledColormaps (ScreenPtr pScreen, Colormap *pCmaps)
+{
+ KdScreenPriv(pScreen);
+
+ if (pScreenPriv->pInstalledmap)
+ {
+ *pCmaps = pScreenPriv->pInstalledmap->mid;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * KdStoreColors
+ *
+ * This function is called whenever the server receives a request to store
+ * color values into one or more entries in the currently installed X
+ * colormap; it can be either the default colormap or a private colorscreen->
+ */
+void
+KdStoreColors (ColormapPtr pCmap, int ndef, xColorItem *pdefs)
+{
+ KdScreenPriv(pCmap->pScreen);
+ VisualPtr pVisual;
+ xColorItem expanddefs[KD_MAX_PSEUDO_SIZE];
+
+ if (pCmap != pScreenPriv->pInstalledmap)
+ return;
+
+ if (!pScreenPriv->card->cfuncs->putColors)
+ return;
+
+ if (pScreenPriv->screen->depth > KD_MAX_PSEUDO_DEPTH)
+ return;
+
+ if (!pScreenPriv->enabled)
+ return;
+
+ /* Check for DirectColor or TrueColor being simulated on a PseudoColor device. */
+ pVisual = pCmap->pVisual;
+ if ((pVisual->class | DynamicClass) == DirectColor)
+ {
+ /*
+ * Expand DirectColor or TrueColor color values into a PseudoColor
+ * format. Defer to the Color Framebuffer (CFB) code to do that.
+ */
+ ndef = fbExpandDirectColors(pCmap, ndef, pdefs, expanddefs);
+ pdefs = expanddefs;
+ }
+
+ (*pScreenPriv->card->cfuncs->putColors) (pCmap->pScreen, ndef, pdefs);
+
+ /* recolor hardware cursor */
+ if (pScreenPriv->card->cfuncs->recolorCursor)
+ (*pScreenPriv->card->cfuncs->recolorCursor) (pCmap->pScreen, ndef, pdefs);
+}
diff --git a/hw/kdrive/src/kcolor.c b/hw/kdrive/src/kcolor.c
new file mode 100644
index 000000000..b2ef89e19
--- /dev/null
+++ b/hw/kdrive/src/kcolor.c
@@ -0,0 +1,883 @@
+/*
+ * $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: $ */
+
+/* $XConsortium: oscolor.c,v 1.23 94/04/17 20:27:04 dpw Exp $ */
+
+#include "kdrive.h"
+#include <stdio.h>
+#include "os.h"
+#include "opaque.h"
+#include <X11/keysym.h>
+
+unsigned char
+KdToLower (unsigned char a)
+{
+ if ((a >= XK_A) && (a <= XK_Z))
+ return a + (XK_a - XK_A);
+ else if ((a >= XK_Agrave) && (a <= XK_Odiaeresis))
+ return a + (XK_agrave - XK_Agrave);
+ else if ((a >= XK_Ooblique) && (a <= XK_Thorn))
+ return a + (XK_oslash - XK_Ooblique);
+ else
+ return a;
+}
+
+int
+KdStrCaseCmp (unsigned char *s1, unsigned char *s2, int l2)
+{
+ unsigned char c1, c2;
+
+ for (;;)
+ {
+ c1 = KdToLower (*s1++);
+ if (l2 == 0)
+ c2 = '\0';
+ else
+ c2 = KdToLower (*s2++);
+ if (!c1 || !c2)
+ break;
+ if (c1 != c2)
+ break;
+ l2--;
+ }
+ return c2 - c1;
+}
+
+typedef struct _kdNamedColor {
+ unsigned short red;
+ unsigned short green;
+ unsigned short blue;
+ unsigned char *name;
+} KdNamedColor;
+
+#define C 0x101
+
+KdNamedColor KdColors[] = {
+240*C, 248*C, 255*C, "alice blue",
+240*C, 248*C, 255*C, "AliceBlue",
+250*C, 235*C, 215*C, "antique white",
+250*C, 235*C, 215*C, "AntiqueWhite",
+255*C, 239*C, 219*C, "AntiqueWhite1",
+238*C, 223*C, 204*C, "AntiqueWhite2",
+205*C, 192*C, 176*C, "AntiqueWhite3",
+139*C, 131*C, 120*C, "AntiqueWhite4",
+127*C, 255*C, 212*C, "aquamarine",
+127*C, 255*C, 212*C, "aquamarine1",
+118*C, 238*C, 198*C, "aquamarine2",
+102*C, 205*C, 170*C, "aquamarine3",
+ 69*C, 139*C, 116*C, "aquamarine4",
+240*C, 255*C, 255*C, "azure",
+240*C, 255*C, 255*C, "azure1",
+224*C, 238*C, 238*C, "azure2",
+193*C, 205*C, 205*C, "azure3",
+131*C, 139*C, 139*C, "azure4",
+245*C, 245*C, 220*C, "beige",
+255*C, 228*C, 196*C, "bisque",
+255*C, 228*C, 196*C, "bisque1",
+238*C, 213*C, 183*C, "bisque2",
+205*C, 183*C, 158*C, "bisque3",
+139*C, 125*C, 107*C, "bisque4",
+ 0*C, 0*C, 0*C, "black",
+255*C, 235*C, 205*C, "blanched almond",
+255*C, 235*C, 205*C, "BlanchedAlmond",
+ 0*C, 0*C, 255*C, "blue",
+138*C, 43*C, 226*C, "blue violet",
+ 0*C, 0*C, 255*C, "blue1",
+ 0*C, 0*C, 238*C, "blue2",
+ 0*C, 0*C, 205*C, "blue3",
+ 0*C, 0*C, 139*C, "blue4",
+138*C, 43*C, 226*C, "BlueViolet",
+165*C, 42*C, 42*C, "brown",
+255*C, 64*C, 64*C, "brown1",
+238*C, 59*C, 59*C, "brown2",
+205*C, 51*C, 51*C, "brown3",
+139*C, 35*C, 35*C, "brown4",
+222*C, 184*C, 135*C, "burlywood",
+255*C, 211*C, 155*C, "burlywood1",
+238*C, 197*C, 145*C, "burlywood2",
+205*C, 170*C, 125*C, "burlywood3",
+139*C, 115*C, 85*C, "burlywood4",
+ 95*C, 158*C, 160*C, "cadet blue",
+ 95*C, 158*C, 160*C, "CadetBlue",
+152*C, 245*C, 255*C, "CadetBlue1",
+142*C, 229*C, 238*C, "CadetBlue2",
+122*C, 197*C, 205*C, "CadetBlue3",
+ 83*C, 134*C, 139*C, "CadetBlue4",
+127*C, 255*C, 0*C, "chartreuse",
+127*C, 255*C, 0*C, "chartreuse1",
+118*C, 238*C, 0*C, "chartreuse2",
+102*C, 205*C, 0*C, "chartreuse3",
+69*C, 139*C, 0*C, "chartreuse4",
+210*C, 105*C, 30*C, "chocolate",
+255*C, 127*C, 36*C, "chocolate1",
+238*C, 118*C, 33*C, "chocolate2",
+205*C, 102*C, 29*C, "chocolate3",
+139*C, 69*C, 19*C, "chocolate4",
+255*C, 127*C, 80*C, "coral",
+255*C, 114*C, 86*C, "coral1",
+238*C, 106*C, 80*C, "coral2",
+205*C, 91*C, 69*C, "coral3",
+139*C, 62*C, 47*C, "coral4",
+100*C, 149*C, 237*C, "cornflower blue",
+100*C, 149*C, 237*C, "CornflowerBlue",
+255*C, 248*C, 220*C, "cornsilk",
+255*C, 248*C, 220*C, "cornsilk1",
+238*C, 232*C, 205*C, "cornsilk2",
+205*C, 200*C, 177*C, "cornsilk3",
+139*C, 136*C, 120*C, "cornsilk4",
+ 0*C, 255*C, 255*C, "cyan",
+ 0*C, 255*C, 255*C, "cyan1",
+ 0*C, 238*C, 238*C, "cyan2",
+ 0*C, 205*C, 205*C, "cyan3",
+ 0*C, 139*C, 139*C, "cyan4",
+0*C, 0*C, 139*C, "dark blue",
+0*C, 139*C, 139*C, "dark cyan",
+184*C, 134*C, 11*C, "dark goldenrod",
+169*C, 169*C, 169*C, "dark gray",
+ 0*C, 100*C, 0*C, "dark green",
+169*C, 169*C, 169*C, "dark grey",
+189*C, 183*C, 107*C, "dark khaki",
+139*C, 0*C, 139*C, "dark magenta",
+ 85*C, 107*C, 47*C, "dark olive green",
+255*C, 140*C, 0*C, "dark orange",
+153*C, 50*C, 204*C, "dark orchid",
+139*C, 0*C, 0*C, "dark red",
+233*C, 150*C, 122*C, "dark salmon",
+143*C, 188*C, 143*C, "dark sea green",
+ 72*C, 61*C, 139*C, "dark slate blue",
+ 47*C, 79*C, 79*C, "dark slate gray",
+ 47*C, 79*C, 79*C, "dark slate grey",
+ 0*C, 206*C, 209*C, "dark turquoise",
+148*C, 0*C, 211*C, "dark violet",
+0*C, 0*C, 139*C, "DarkBlue",
+0*C, 139*C, 139*C, "DarkCyan",
+184*C, 134*C, 11*C, "DarkGoldenrod",
+255*C, 185*C, 15*C, "DarkGoldenrod1",
+238*C, 173*C, 14*C, "DarkGoldenrod2",
+205*C, 149*C, 12*C, "DarkGoldenrod3",
+139*C, 101*C, 8*C, "DarkGoldenrod4",
+169*C, 169*C, 169*C, "DarkGray",
+ 0*C, 100*C, 0*C, "DarkGreen",
+169*C, 169*C, 169*C, "DarkGrey",
+189*C, 183*C, 107*C, "DarkKhaki",
+139*C, 0*C, 139*C, "DarkMagenta",
+ 85*C, 107*C, 47*C, "DarkOliveGreen",
+202*C, 255*C, 112*C, "DarkOliveGreen1",
+188*C, 238*C, 104*C, "DarkOliveGreen2",
+162*C, 205*C, 90*C, "DarkOliveGreen3",
+110*C, 139*C, 61*C, "DarkOliveGreen4",
+255*C, 140*C, 0*C, "DarkOrange",
+255*C, 127*C, 0*C, "DarkOrange1",
+238*C, 118*C, 0*C, "DarkOrange2",
+205*C, 102*C, 0*C, "DarkOrange3",
+139*C, 69*C, 0*C, "DarkOrange4",
+153*C, 50*C, 204*C, "DarkOrchid",
+191*C, 62*C, 255*C, "DarkOrchid1",
+178*C, 58*C, 238*C, "DarkOrchid2",
+154*C, 50*C, 205*C, "DarkOrchid3",
+104*C, 34*C, 139*C, "DarkOrchid4",
+139*C, 0*C, 0*C, "DarkRed",
+233*C, 150*C, 122*C, "DarkSalmon",
+143*C, 188*C, 143*C, "DarkSeaGreen",
+193*C, 255*C, 193*C, "DarkSeaGreen1",
+180*C, 238*C, 180*C, "DarkSeaGreen2",
+155*C, 205*C, 155*C, "DarkSeaGreen3",
+105*C, 139*C, 105*C, "DarkSeaGreen4",
+ 72*C, 61*C, 139*C, "DarkSlateBlue",
+ 47*C, 79*C, 79*C, "DarkSlateGray",
+151*C, 255*C, 255*C, "DarkSlateGray1",
+141*C, 238*C, 238*C, "DarkSlateGray2",
+121*C, 205*C, 205*C, "DarkSlateGray3",
+ 82*C, 139*C, 139*C, "DarkSlateGray4",
+ 47*C, 79*C, 79*C, "DarkSlateGrey",
+ 0*C, 206*C, 209*C, "DarkTurquoise",
+148*C, 0*C, 211*C, "DarkViolet",
+255*C, 20*C, 147*C, "deep pink",
+ 0*C, 191*C, 255*C, "deep sky blue",
+255*C, 20*C, 147*C, "DeepPink",
+255*C, 20*C, 147*C, "DeepPink1",
+238*C, 18*C, 137*C, "DeepPink2",
+205*C, 16*C, 118*C, "DeepPink3",
+139*C, 10*C, 80*C, "DeepPink4",
+ 0*C, 191*C, 255*C, "DeepSkyBlue",
+ 0*C, 191*C, 255*C, "DeepSkyBlue1",
+ 0*C, 178*C, 238*C, "DeepSkyBlue2",
+ 0*C, 154*C, 205*C, "DeepSkyBlue3",
+ 0*C, 104*C, 139*C, "DeepSkyBlue4",
+105*C, 105*C, 105*C, "dim gray",
+105*C, 105*C, 105*C, "dim grey",
+105*C, 105*C, 105*C, "DimGray",
+105*C, 105*C, 105*C, "DimGrey",
+ 30*C, 144*C, 255*C, "dodger blue",
+ 30*C, 144*C, 255*C, "DodgerBlue",
+ 30*C, 144*C, 255*C, "DodgerBlue1",
+ 28*C, 134*C, 238*C, "DodgerBlue2",
+ 24*C, 116*C, 205*C, "DodgerBlue3",
+ 16*C, 78*C, 139*C, "DodgerBlue4",
+178*C, 34*C, 34*C, "firebrick",
+255*C, 48*C, 48*C, "firebrick1",
+238*C, 44*C, 44*C, "firebrick2",
+205*C, 38*C, 38*C, "firebrick3",
+139*C, 26*C, 26*C, "firebrick4",
+255*C, 250*C, 240*C, "floral white",
+255*C, 250*C, 240*C, "FloralWhite",
+ 34*C, 139*C, 34*C, "forest green",
+ 34*C, 139*C, 34*C, "ForestGreen",
+220*C, 220*C, 220*C, "gainsboro",
+248*C, 248*C, 255*C, "ghost white",
+248*C, 248*C, 255*C, "GhostWhite",
+255*C, 215*C, 0*C, "gold",
+255*C, 215*C, 0*C, "gold1",
+238*C, 201*C, 0*C, "gold2",
+205*C, 173*C, 0*C, "gold3",
+139*C, 117*C, 0*C, "gold4",
+218*C, 165*C, 32*C, "goldenrod",
+255*C, 193*C, 37*C, "goldenrod1",
+238*C, 180*C, 34*C, "goldenrod2",
+205*C, 155*C, 29*C, "goldenrod3",
+139*C, 105*C, 20*C, "goldenrod4",
+190*C, 190*C, 190*C, "gray",
+ 0*C, 0*C, 0*C, "gray0",
+ 3*C, 3*C, 3*C, "gray1",
+ 26*C, 26*C, 26*C, "gray10",
+255*C, 255*C, 255*C, "gray100",
+ 28*C, 28*C, 28*C, "gray11",
+ 31*C, 31*C, 31*C, "gray12",
+ 33*C, 33*C, 33*C, "gray13",
+ 36*C, 36*C, 36*C, "gray14",
+ 38*C, 38*C, 38*C, "gray15",
+ 41*C, 41*C, 41*C, "gray16",
+ 43*C, 43*C, 43*C, "gray17",
+ 46*C, 46*C, 46*C, "gray18",
+ 48*C, 48*C, 48*C, "gray19",
+ 5*C, 5*C, 5*C, "gray2",
+ 51*C, 51*C, 51*C, "gray20",
+ 54*C, 54*C, 54*C, "gray21",
+ 56*C, 56*C, 56*C, "gray22",
+ 59*C, 59*C, 59*C, "gray23",
+ 61*C, 61*C, 61*C, "gray24",
+ 64*C, 64*C, 64*C, "gray25",
+ 66*C, 66*C, 66*C, "gray26",
+ 69*C, 69*C, 69*C, "gray27",
+ 71*C, 71*C, 71*C, "gray28",
+ 74*C, 74*C, 74*C, "gray29",
+ 8*C, 8*C, 8*C, "gray3",
+ 77*C, 77*C, 77*C, "gray30",
+ 79*C, 79*C, 79*C, "gray31",
+ 82*C, 82*C, 82*C, "gray32",
+ 84*C, 84*C, 84*C, "gray33",
+ 87*C, 87*C, 87*C, "gray34",
+ 89*C, 89*C, 89*C, "gray35",
+ 92*C, 92*C, 92*C, "gray36",
+ 94*C, 94*C, 94*C, "gray37",
+ 97*C, 97*C, 97*C, "gray38",
+ 99*C, 99*C, 99*C, "gray39",
+ 10*C, 10*C, 10*C, "gray4",
+102*C, 102*C, 102*C, "gray40",
+105*C, 105*C, 105*C, "gray41",
+107*C, 107*C, 107*C, "gray42",
+110*C, 110*C, 110*C, "gray43",
+112*C, 112*C, 112*C, "gray44",
+115*C, 115*C, 115*C, "gray45",
+117*C, 117*C, 117*C, "gray46",
+120*C, 120*C, 120*C, "gray47",
+122*C, 122*C, 122*C, "gray48",
+125*C, 125*C, 125*C, "gray49",
+ 13*C, 13*C, 13*C, "gray5",
+127*C, 127*C, 127*C, "gray50",
+130*C, 130*C, 130*C, "gray51",
+133*C, 133*C, 133*C, "gray52",
+135*C, 135*C, 135*C, "gray53",
+138*C, 138*C, 138*C, "gray54",
+140*C, 140*C, 140*C, "gray55",
+143*C, 143*C, 143*C, "gray56",
+145*C, 145*C, 145*C, "gray57",
+148*C, 148*C, 148*C, "gray58",
+150*C, 150*C, 150*C, "gray59",
+ 15*C, 15*C, 15*C, "gray6",
+153*C, 153*C, 153*C, "gray60",
+156*C, 156*C, 156*C, "gray61",
+158*C, 158*C, 158*C, "gray62",
+161*C, 161*C, 161*C, "gray63",
+163*C, 163*C, 163*C, "gray64",
+166*C, 166*C, 166*C, "gray65",
+168*C, 168*C, 168*C, "gray66",
+171*C, 171*C, 171*C, "gray67",
+173*C, 173*C, 173*C, "gray68",
+176*C, 176*C, 176*C, "gray69",
+ 18*C, 18*C, 18*C, "gray7",
+179*C, 179*C, 179*C, "gray70",
+181*C, 181*C, 181*C, "gray71",
+184*C, 184*C, 184*C, "gray72",
+186*C, 186*C, 186*C, "gray73",
+189*C, 189*C, 189*C, "gray74",
+191*C, 191*C, 191*C, "gray75",
+194*C, 194*C, 194*C, "gray76",
+196*C, 196*C, 196*C, "gray77",
+199*C, 199*C, 199*C, "gray78",
+201*C, 201*C, 201*C, "gray79",
+ 20*C, 20*C, 20*C, "gray8",
+204*C, 204*C, 204*C, "gray80",
+207*C, 207*C, 207*C, "gray81",
+209*C, 209*C, 209*C, "gray82",
+212*C, 212*C, 212*C, "gray83",
+214*C, 214*C, 214*C, "gray84",
+217*C, 217*C, 217*C, "gray85",
+219*C, 219*C, 219*C, "gray86",
+222*C, 222*C, 222*C, "gray87",
+224*C, 224*C, 224*C, "gray88",
+227*C, 227*C, 227*C, "gray89",
+ 23*C, 23*C, 23*C, "gray9",
+229*C, 229*C, 229*C, "gray90",
+232*C, 232*C, 232*C, "gray91",
+235*C, 235*C, 235*C, "gray92",
+237*C, 237*C, 237*C, "gray93",
+240*C, 240*C, 240*C, "gray94",
+242*C, 242*C, 242*C, "gray95",
+245*C, 245*C, 245*C, "gray96",
+247*C, 247*C, 247*C, "gray97",
+250*C, 250*C, 250*C, "gray98",
+252*C, 252*C, 252*C, "gray99",
+ 0*C, 255*C, 0*C, "green",
+173*C, 255*C, 47*C, "green yellow",
+0*C, 255*C, 0*C, "green1",
+0*C, 238*C, 0*C, "green2",
+0*C, 205*C, 0*C, "green3",
+0*C, 139*C, 0*C, "green4",
+173*C, 255*C, 47*C, "GreenYellow",
+190*C, 190*C, 190*C, "grey",
+ 0*C, 0*C, 0*C, "grey0",
+ 3*C, 3*C, 3*C, "grey1",
+ 26*C, 26*C, 26*C, "grey10",
+255*C, 255*C, 255*C, "grey100",
+ 28*C, 28*C, 28*C, "grey11",
+ 31*C, 31*C, 31*C, "grey12",
+ 33*C, 33*C, 33*C, "grey13",
+ 36*C, 36*C, 36*C, "grey14",
+ 38*C, 38*C, 38*C, "grey15",
+ 41*C, 41*C, 41*C, "grey16",
+ 43*C, 43*C, 43*C, "grey17",
+ 46*C, 46*C, 46*C, "grey18",
+ 48*C, 48*C, 48*C, "grey19",
+ 5*C, 5*C, 5*C, "grey2",
+ 51*C, 51*C, 51*C, "grey20",
+ 54*C, 54*C, 54*C, "grey21",
+ 56*C, 56*C, 56*C, "grey22",
+ 59*C, 59*C, 59*C, "grey23",
+ 61*C, 61*C, 61*C, "grey24",
+ 64*C, 64*C, 64*C, "grey25",
+ 66*C, 66*C, 66*C, "grey26",
+ 69*C, 69*C, 69*C, "grey27",
+ 71*C, 71*C, 71*C, "grey28",
+ 74*C, 74*C, 74*C, "grey29",
+ 8*C, 8*C, 8*C, "grey3",
+ 77*C, 77*C, 77*C, "grey30",
+ 79*C, 79*C, 79*C, "grey31",
+ 82*C, 82*C, 82*C, "grey32",
+ 84*C, 84*C, 84*C, "grey33",
+ 87*C, 87*C, 87*C, "grey34",
+ 89*C, 89*C, 89*C, "grey35",
+ 92*C, 92*C, 92*C, "grey36",
+ 94*C, 94*C, 94*C, "grey37",
+ 97*C, 97*C, 97*C, "grey38",
+ 99*C, 99*C, 99*C, "grey39",
+ 10*C, 10*C, 10*C, "grey4",
+102*C, 102*C, 102*C, "grey40",
+105*C, 105*C, 105*C, "grey41",
+107*C, 107*C, 107*C, "grey42",
+110*C, 110*C, 110*C, "grey43",
+112*C, 112*C, 112*C, "grey44",
+115*C, 115*C, 115*C, "grey45",
+117*C, 117*C, 117*C, "grey46",
+120*C, 120*C, 120*C, "grey47",
+122*C, 122*C, 122*C, "grey48",
+125*C, 125*C, 125*C, "grey49",
+ 13*C, 13*C, 13*C, "grey5",
+127*C, 127*C, 127*C, "grey50",
+130*C, 130*C, 130*C, "grey51",
+133*C, 133*C, 133*C, "grey52",
+135*C, 135*C, 135*C, "grey53",
+138*C, 138*C, 138*C, "grey54",
+140*C, 140*C, 140*C, "grey55",
+143*C, 143*C, 143*C, "grey56",
+145*C, 145*C, 145*C, "grey57",
+148*C, 148*C, 148*C, "grey58",
+150*C, 150*C, 150*C, "grey59",
+ 15*C, 15*C, 15*C, "grey6",
+153*C, 153*C, 153*C, "grey60",
+156*C, 156*C, 156*C, "grey61",
+158*C, 158*C, 158*C, "grey62",
+161*C, 161*C, 161*C, "grey63",
+163*C, 163*C, 163*C, "grey64",
+166*C, 166*C, 166*C, "grey65",
+168*C, 168*C, 168*C, "grey66",
+171*C, 171*C, 171*C, "grey67",
+173*C, 173*C, 173*C, "grey68",
+176*C, 176*C, 176*C, "grey69",
+ 18*C, 18*C, 18*C, "grey7",
+179*C, 179*C, 179*C, "grey70",
+181*C, 181*C, 181*C, "grey71",
+184*C, 184*C, 184*C, "grey72",
+186*C, 186*C, 186*C, "grey73",
+189*C, 189*C, 189*C, "grey74",
+191*C, 191*C, 191*C, "grey75",
+194*C, 194*C, 194*C, "grey76",
+196*C, 196*C, 196*C, "grey77",
+199*C, 199*C, 199*C, "grey78",
+201*C, 201*C, 201*C, "grey79",
+ 20*C, 20*C, 20*C, "grey8",
+204*C, 204*C, 204*C, "grey80",
+207*C, 207*C, 207*C, "grey81",
+209*C, 209*C, 209*C, "grey82",
+212*C, 212*C, 212*C, "grey83",
+214*C, 214*C, 214*C, "grey84",
+217*C, 217*C, 217*C, "grey85",
+219*C, 219*C, 219*C, "grey86",
+222*C, 222*C, 222*C, "grey87",
+224*C, 224*C, 224*C, "grey88",
+227*C, 227*C, 227*C, "grey89",
+ 23*C, 23*C, 23*C, "grey9",
+229*C, 229*C, 229*C, "grey90",
+232*C, 232*C, 232*C, "grey91",
+235*C, 235*C, 235*C, "grey92",
+237*C, 237*C, 237*C, "grey93",
+240*C, 240*C, 240*C, "grey94",
+242*C, 242*C, 242*C, "grey95",
+245*C, 245*C, 245*C, "grey96",
+247*C, 247*C, 247*C, "grey97",
+250*C, 250*C, 250*C, "grey98",
+252*C, 252*C, 252*C, "grey99",
+240*C, 255*C, 240*C, "honeydew",
+240*C, 255*C, 240*C, "honeydew1",
+224*C, 238*C, 224*C, "honeydew2",
+193*C, 205*C, 193*C, "honeydew3",
+131*C, 139*C, 131*C, "honeydew4",
+255*C, 105*C, 180*C, "hot pink",
+255*C, 105*C, 180*C, "HotPink",
+255*C, 110*C, 180*C, "HotPink1",
+238*C, 106*C, 167*C, "HotPink2",
+205*C, 96*C, 144*C, "HotPink3",
+139*C, 58*C, 98*C, "HotPink4",
+205*C, 92*C, 92*C, "indian red",
+205*C, 92*C, 92*C, "IndianRed",
+255*C, 106*C, 106*C, "IndianRed1",
+238*C, 99*C, 99*C, "IndianRed2",
+205*C, 85*C, 85*C, "IndianRed3",
+139*C, 58*C, 58*C, "IndianRed4",
+255*C, 255*C, 240*C, "ivory",
+255*C, 255*C, 240*C, "ivory1",
+238*C, 238*C, 224*C, "ivory2",
+205*C, 205*C, 193*C, "ivory3",
+139*C, 139*C, 131*C, "ivory4",
+240*C, 230*C, 140*C, "khaki",
+255*C, 246*C, 143*C, "khaki1",
+238*C, 230*C, 133*C, "khaki2",
+205*C, 198*C, 115*C, "khaki3",
+139*C, 134*C, 78*C, "khaki4",
+230*C, 230*C, 250*C, "lavender",
+255*C, 240*C, 245*C, "lavender blush",
+255*C, 240*C, 245*C, "LavenderBlush",
+255*C, 240*C, 245*C, "LavenderBlush1",
+238*C, 224*C, 229*C, "LavenderBlush2",
+205*C, 193*C, 197*C, "LavenderBlush3",
+139*C, 131*C, 134*C, "LavenderBlush4",
+124*C, 252*C, 0*C, "lawn green",
+124*C, 252*C, 0*C, "LawnGreen",
+255*C, 250*C, 205*C, "lemon chiffon",
+255*C, 250*C, 205*C, "LemonChiffon",
+255*C, 250*C, 205*C, "LemonChiffon1",
+238*C, 233*C, 191*C, "LemonChiffon2",
+205*C, 201*C, 165*C, "LemonChiffon3",
+139*C, 137*C, 112*C, "LemonChiffon4",
+173*C, 216*C, 230*C, "light blue",
+240*C, 128*C, 128*C, "light coral",
+224*C, 255*C, 255*C, "light cyan",
+238*C, 221*C, 130*C, "light goldenrod",
+250*C, 250*C, 210*C, "light goldenrod yellow",
+211*C, 211*C, 211*C, "light gray",
+144*C, 238*C, 144*C, "light green",
+211*C, 211*C, 211*C, "light grey",
+255*C, 182*C, 193*C, "light pink",
+255*C, 160*C, 122*C, "light salmon",
+ 32*C, 178*C, 170*C, "light sea green",
+135*C, 206*C, 250*C, "light sky blue",
+132*C, 112*C, 255*C, "light slate blue",
+119*C, 136*C, 153*C, "light slate gray",
+119*C, 136*C, 153*C, "light slate grey",
+176*C, 196*C, 222*C, "light steel blue",
+255*C, 255*C, 224*C, "light yellow",
+173*C, 216*C, 230*C, "LightBlue",
+191*C, 239*C, 255*C, "LightBlue1",
+178*C, 223*C, 238*C, "LightBlue2",
+154*C, 192*C, 205*C, "LightBlue3",
+104*C, 131*C, 139*C, "LightBlue4",
+240*C, 128*C, 128*C, "LightCoral",
+224*C, 255*C, 255*C, "LightCyan",
+224*C, 255*C, 255*C, "LightCyan1",
+209*C, 238*C, 238*C, "LightCyan2",
+180*C, 205*C, 205*C, "LightCyan3",
+122*C, 139*C, 139*C, "LightCyan4",
+238*C, 221*C, 130*C, "LightGoldenrod",
+255*C, 236*C, 139*C, "LightGoldenrod1",
+238*C, 220*C, 130*C, "LightGoldenrod2",
+205*C, 190*C, 112*C, "LightGoldenrod3",
+139*C, 129*C, 76*C, "LightGoldenrod4",
+250*C, 250*C, 210*C, "LightGoldenrodYellow",
+211*C, 211*C, 211*C, "LightGray",
+144*C, 238*C, 144*C, "LightGreen",
+211*C, 211*C, 211*C, "LightGrey",
+255*C, 182*C, 193*C, "LightPink",
+255*C, 174*C, 185*C, "LightPink1",
+238*C, 162*C, 173*C, "LightPink2",
+205*C, 140*C, 149*C, "LightPink3",
+139*C, 95*C, 101*C, "LightPink4",
+255*C, 160*C, 122*C, "LightSalmon",
+255*C, 160*C, 122*C, "LightSalmon1",
+238*C, 149*C, 114*C, "LightSalmon2",
+205*C, 129*C, 98*C, "LightSalmon3",
+139*C, 87*C, 66*C, "LightSalmon4",
+ 32*C, 178*C, 170*C, "LightSeaGreen",
+135*C, 206*C, 250*C, "LightSkyBlue",
+176*C, 226*C, 255*C, "LightSkyBlue1",
+164*C, 211*C, 238*C, "LightSkyBlue2",
+141*C, 182*C, 205*C, "LightSkyBlue3",
+ 96*C, 123*C, 139*C, "LightSkyBlue4",
+132*C, 112*C, 255*C, "LightSlateBlue",
+119*C, 136*C, 153*C, "LightSlateGray",
+119*C, 136*C, 153*C, "LightSlateGrey",
+176*C, 196*C, 222*C, "LightSteelBlue",
+202*C, 225*C, 255*C, "LightSteelBlue1",
+188*C, 210*C, 238*C, "LightSteelBlue2",
+162*C, 181*C, 205*C, "LightSteelBlue3",
+110*C, 123*C, 139*C, "LightSteelBlue4",
+255*C, 255*C, 224*C, "LightYellow",
+255*C, 255*C, 224*C, "LightYellow1",
+238*C, 238*C, 209*C, "LightYellow2",
+205*C, 205*C, 180*C, "LightYellow3",
+139*C, 139*C, 122*C, "LightYellow4",
+ 50*C, 205*C, 50*C, "lime green",
+ 50*C, 205*C, 50*C, "LimeGreen",
+250*C, 240*C, 230*C, "linen",
+255*C, 0*C, 255*C, "magenta",
+255*C, 0*C, 255*C, "magenta1",
+238*C, 0*C, 238*C, "magenta2",
+205*C, 0*C, 205*C, "magenta3",
+139*C, 0*C, 139*C, "magenta4",
+176*C, 48*C, 96*C, "maroon",
+255*C, 52*C, 179*C, "maroon1",
+238*C, 48*C, 167*C, "maroon2",
+205*C, 41*C, 144*C, "maroon3",
+139*C, 28*C, 98*C, "maroon4",
+102*C, 205*C, 170*C, "medium aquamarine",
+ 0*C, 0*C, 205*C, "medium blue",
+186*C, 85*C, 211*C, "medium orchid",
+147*C, 112*C, 219*C, "medium purple",
+ 60*C, 179*C, 113*C, "medium sea green",
+123*C, 104*C, 238*C, "medium slate blue",
+ 0*C, 250*C, 154*C, "medium spring green",
+ 72*C, 209*C, 204*C, "medium turquoise",
+199*C, 21*C, 133*C, "medium violet red",
+102*C, 205*C, 170*C, "MediumAquamarine",
+ 0*C, 0*C, 205*C, "MediumBlue",
+186*C, 85*C, 211*C, "MediumOrchid",
+224*C, 102*C, 255*C, "MediumOrchid1",
+209*C, 95*C, 238*C, "MediumOrchid2",
+180*C, 82*C, 205*C, "MediumOrchid3",
+122*C, 55*C, 139*C, "MediumOrchid4",
+147*C, 112*C, 219*C, "MediumPurple",
+171*C, 130*C, 255*C, "MediumPurple1",
+159*C, 121*C, 238*C, "MediumPurple2",
+137*C, 104*C, 205*C, "MediumPurple3",
+ 93*C, 71*C, 139*C, "MediumPurple4",
+ 60*C, 179*C, 113*C, "MediumSeaGreen",
+123*C, 104*C, 238*C, "MediumSlateBlue",
+ 0*C, 250*C, 154*C, "MediumSpringGreen",
+ 72*C, 209*C, 204*C, "MediumTurquoise",
+199*C, 21*C, 133*C, "MediumVioletRed",
+ 25*C, 25*C, 112*C, "midnight blue",
+ 25*C, 25*C, 112*C, "MidnightBlue",
+245*C, 255*C, 250*C, "mint cream",
+245*C, 255*C, 250*C, "MintCream",
+255*C, 228*C, 225*C, "misty rose",
+255*C, 228*C, 225*C, "MistyRose",
+255*C, 228*C, 225*C, "MistyRose1",
+238*C, 213*C, 210*C, "MistyRose2",
+205*C, 183*C, 181*C, "MistyRose3",
+139*C, 125*C, 123*C, "MistyRose4",
+255*C, 228*C, 181*C, "moccasin",
+255*C, 222*C, 173*C, "navajo white",
+255*C, 222*C, 173*C, "NavajoWhite",
+255*C, 222*C, 173*C, "NavajoWhite1",
+238*C, 207*C, 161*C, "NavajoWhite2",
+205*C, 179*C, 139*C, "NavajoWhite3",
+139*C, 121*C, 94*C, "NavajoWhite4",
+ 0*C, 0*C, 128*C, "navy",
+ 0*C, 0*C, 128*C, "navy blue",
+ 0*C, 0*C, 128*C, "NavyBlue",
+253*C, 245*C, 230*C, "old lace",
+253*C, 245*C, 230*C, "OldLace",
+107*C, 142*C, 35*C, "olive drab",
+107*C, 142*C, 35*C, "OliveDrab",
+192*C, 255*C, 62*C, "OliveDrab1",
+179*C, 238*C, 58*C, "OliveDrab2",
+154*C, 205*C, 50*C, "OliveDrab3",
+105*C, 139*C, 34*C, "OliveDrab4",
+255*C, 165*C, 0*C, "orange",
+255*C, 69*C, 0*C, "orange red",
+255*C, 165*C, 0*C, "orange1",
+238*C, 154*C, 0*C, "orange2",
+205*C, 133*C, 0*C, "orange3",
+139*C, 90*C, 0*C, "orange4",
+255*C, 69*C, 0*C, "OrangeRed",
+255*C, 69*C, 0*C, "OrangeRed1",
+238*C, 64*C, 0*C, "OrangeRed2",
+205*C, 55*C, 0*C, "OrangeRed3",
+139*C, 37*C, 0*C, "OrangeRed4",
+218*C, 112*C, 214*C, "orchid",
+255*C, 131*C, 250*C, "orchid1",
+238*C, 122*C, 233*C, "orchid2",
+205*C, 105*C, 201*C, "orchid3",
+139*C, 71*C, 137*C, "orchid4",
+238*C, 232*C, 170*C, "pale goldenrod",
+152*C, 251*C, 152*C, "pale green",
+175*C, 238*C, 238*C, "pale turquoise",
+219*C, 112*C, 147*C, "pale violet red",
+238*C, 232*C, 170*C, "PaleGoldenrod",
+152*C, 251*C, 152*C, "PaleGreen",
+154*C, 255*C, 154*C, "PaleGreen1",
+144*C, 238*C, 144*C, "PaleGreen2",
+124*C, 205*C, 124*C, "PaleGreen3",
+84*C, 139*C, 84*C, "PaleGreen4",
+175*C, 238*C, 238*C, "PaleTurquoise",
+187*C, 255*C, 255*C, "PaleTurquoise1",
+174*C, 238*C, 238*C, "PaleTurquoise2",
+150*C, 205*C, 205*C, "PaleTurquoise3",
+102*C, 139*C, 139*C, "PaleTurquoise4",
+219*C, 112*C, 147*C, "PaleVioletRed",
+255*C, 130*C, 171*C, "PaleVioletRed1",
+238*C, 121*C, 159*C, "PaleVioletRed2",
+205*C, 104*C, 137*C, "PaleVioletRed3",
+139*C, 71*C, 93*C, "PaleVioletRed4",
+255*C, 239*C, 213*C, "papaya whip",
+255*C, 239*C, 213*C, "PapayaWhip",
+255*C, 218*C, 185*C, "peach puff",
+255*C, 218*C, 185*C, "PeachPuff",
+255*C, 218*C, 185*C, "PeachPuff1",
+238*C, 203*C, 173*C, "PeachPuff2",
+205*C, 175*C, 149*C, "PeachPuff3",
+139*C, 119*C, 101*C, "PeachPuff4",
+205*C, 133*C, 63*C, "peru",
+255*C, 192*C, 203*C, "pink",
+255*C, 181*C, 197*C, "pink1",
+238*C, 169*C, 184*C, "pink2",
+205*C, 145*C, 158*C, "pink3",
+139*C, 99*C, 108*C, "pink4",
+221*C, 160*C, 221*C, "plum",
+255*C, 187*C, 255*C, "plum1",
+238*C, 174*C, 238*C, "plum2",
+205*C, 150*C, 205*C, "plum3",
+139*C, 102*C, 139*C, "plum4",
+176*C, 224*C, 230*C, "powder blue",
+176*C, 224*C, 230*C, "PowderBlue",
+160*C, 32*C, 240*C, "purple",
+155*C, 48*C, 255*C, "purple1",
+145*C, 44*C, 238*C, "purple2",
+125*C, 38*C, 205*C, "purple3",
+ 85*C, 26*C, 139*C, "purple4",
+255*C, 0*C, 0*C, "red",
+255*C, 0*C, 0*C, "red1",
+238*C, 0*C, 0*C, "red2",
+205*C, 0*C, 0*C, "red3",
+139*C, 0*C, 0*C, "red4",
+188*C, 143*C, 143*C, "rosy brown",
+188*C, 143*C, 143*C, "RosyBrown",
+255*C, 193*C, 193*C, "RosyBrown1",
+238*C, 180*C, 180*C, "RosyBrown2",
+205*C, 155*C, 155*C, "RosyBrown3",
+139*C, 105*C, 105*C, "RosyBrown4",
+ 65*C, 105*C, 225*C, "royal blue",
+ 65*C, 105*C, 225*C, "RoyalBlue",
+ 72*C, 118*C, 255*C, "RoyalBlue1",
+ 67*C, 110*C, 238*C, "RoyalBlue2",
+ 58*C, 95*C, 205*C, "RoyalBlue3",
+ 39*C, 64*C, 139*C, "RoyalBlue4",
+139*C, 69*C, 19*C, "saddle brown",
+139*C, 69*C, 19*C, "SaddleBrown",
+250*C, 128*C, 114*C, "salmon",
+255*C, 140*C, 105*C, "salmon1",
+238*C, 130*C, 98*C, "salmon2",
+205*C, 112*C, 84*C, "salmon3",
+139*C, 76*C, 57*C, "salmon4",
+244*C, 164*C, 96*C, "sandy brown",
+244*C, 164*C, 96*C, "SandyBrown",
+ 46*C, 139*C, 87*C, "sea green",
+ 46*C, 139*C, 87*C, "SeaGreen",
+ 84*C, 255*C, 159*C, "SeaGreen1",
+ 78*C, 238*C, 148*C, "SeaGreen2",
+ 67*C, 205*C, 128*C, "SeaGreen3",
+46*C, 139*C, 87*C, "SeaGreen4",
+255*C, 245*C, 238*C, "seashell",
+255*C, 245*C, 238*C, "seashell1",
+238*C, 229*C, 222*C, "seashell2",
+205*C, 197*C, 191*C, "seashell3",
+139*C, 134*C, 130*C, "seashell4",
+160*C, 82*C, 45*C, "sienna",
+255*C, 130*C, 71*C, "sienna1",
+238*C, 121*C, 66*C, "sienna2",
+205*C, 104*C, 57*C, "sienna3",
+139*C, 71*C, 38*C, "sienna4",
+135*C, 206*C, 235*C, "sky blue",
+135*C, 206*C, 235*C, "SkyBlue",
+135*C, 206*C, 255*C, "SkyBlue1",
+126*C, 192*C, 238*C, "SkyBlue2",
+108*C, 166*C, 205*C, "SkyBlue3",
+ 74*C, 112*C, 139*C, "SkyBlue4",
+106*C, 90*C, 205*C, "slate blue",
+112*C, 128*C, 144*C, "slate gray",
+112*C, 128*C, 144*C, "slate grey",
+106*C, 90*C, 205*C, "SlateBlue",
+131*C, 111*C, 255*C, "SlateBlue1",
+122*C, 103*C, 238*C, "SlateBlue2",
+105*C, 89*C, 205*C, "SlateBlue3",
+ 71*C, 60*C, 139*C, "SlateBlue4",
+112*C, 128*C, 144*C, "SlateGray",
+198*C, 226*C, 255*C, "SlateGray1",
+185*C, 211*C, 238*C, "SlateGray2",
+159*C, 182*C, 205*C, "SlateGray3",
+108*C, 123*C, 139*C, "SlateGray4",
+112*C, 128*C, 144*C, "SlateGrey",
+255*C, 250*C, 250*C, "snow",
+255*C, 250*C, 250*C, "snow1",
+238*C, 233*C, 233*C, "snow2",
+205*C, 201*C, 201*C, "snow3",
+139*C, 137*C, 137*C, "snow4",
+ 0*C, 255*C, 127*C, "spring green",
+ 0*C, 255*C, 127*C, "SpringGreen",
+ 0*C, 255*C, 127*C, "SpringGreen1",
+ 0*C, 238*C, 118*C, "SpringGreen2",
+ 0*C, 205*C, 102*C, "SpringGreen3",
+0*C, 139*C, 69*C, "SpringGreen4",
+ 70*C, 130*C, 180*C, "steel blue",
+ 70*C, 130*C, 180*C, "SteelBlue",
+ 99*C, 184*C, 255*C, "SteelBlue1",
+ 92*C, 172*C, 238*C, "SteelBlue2",
+ 79*C, 148*C, 205*C, "SteelBlue3",
+ 54*C, 100*C, 139*C, "SteelBlue4",
+210*C, 180*C, 140*C, "tan",
+255*C, 165*C, 79*C, "tan1",
+238*C, 154*C, 73*C, "tan2",
+205*C, 133*C, 63*C, "tan3",
+139*C, 90*C, 43*C, "tan4",
+216*C, 191*C, 216*C, "thistle",
+255*C, 225*C, 255*C, "thistle1",
+238*C, 210*C, 238*C, "thistle2",
+205*C, 181*C, 205*C, "thistle3",
+139*C, 123*C, 139*C, "thistle4",
+255*C, 99*C, 71*C, "tomato",
+255*C, 99*C, 71*C, "tomato1",
+238*C, 92*C, 66*C, "tomato2",
+205*C, 79*C, 57*C, "tomato3",
+139*C, 54*C, 38*C, "tomato4",
+ 64*C, 224*C, 208*C, "turquoise",
+ 0*C, 245*C, 255*C, "turquoise1",
+ 0*C, 229*C, 238*C, "turquoise2",
+ 0*C, 197*C, 205*C, "turquoise3",
+ 0*C, 134*C, 139*C, "turquoise4",
+238*C, 130*C, 238*C, "violet",
+208*C, 32*C, 144*C, "violet red",
+208*C, 32*C, 144*C, "VioletRed",
+255*C, 62*C, 150*C, "VioletRed1",
+238*C, 58*C, 140*C, "VioletRed2",
+205*C, 50*C, 120*C, "VioletRed3",
+139*C, 34*C, 82*C, "VioletRed4",
+245*C, 222*C, 179*C, "wheat",
+255*C, 231*C, 186*C, "wheat1",
+238*C, 216*C, 174*C, "wheat2",
+205*C, 186*C, 150*C, "wheat3",
+139*C, 126*C, 102*C, "wheat4",
+255*C, 255*C, 255*C, "white",
+245*C, 245*C, 245*C, "white smoke",
+245*C, 245*C, 245*C, "WhiteSmoke",
+255*C, 255*C, 0*C, "yellow",
+154*C, 205*C, 50*C, "yellow green",
+255*C, 255*C, 0*C, "yellow1",
+238*C, 238*C, 0*C, "yellow2",
+205*C, 205*C, 0*C, "yellow3",
+139*C, 139*C, 0*C, "yellow4",
+154*C, 205*C, 50*C, "YellowGreen",
+};
+
+#undef C
+
+#define NUM_KD_COLORS (sizeof (KdColors) / sizeof (KdColors[0]))
+
+Bool
+OsInitColors()
+{
+ return TRUE;
+}
+
+Bool
+OsLookupColor(int screen,
+ char *s_name,
+ unsigned int len,
+ unsigned short *pred,
+ unsigned short *pgreen,
+ unsigned short *pblue)
+{
+ KdNamedColor *c;
+ unsigned char *name = (unsigned char *) s_name;
+ int low, mid, high;
+ int r;
+
+ low = 0;
+ high = NUM_KD_COLORS;
+ while (high - low > 0)
+ {
+ mid = (low + high) / 2;
+ c = &KdColors[mid];
+ r = KdStrCaseCmp (c->name, name, len);
+ if (r == 0)
+ {
+ *pred = c->red;
+ *pgreen = c->green;
+ *pblue = c->blue;
+ return TRUE;
+ }
+ if (r < 0)
+ {
+ if (high == mid)
+ break;
+ high = mid;
+ }
+ else
+ {
+ if (low == mid)
+ break;
+ low = mid;
+ }
+ }
+ return FALSE;
+}
diff --git a/hw/kdrive/src/kdrive.c b/hw/kdrive/src/kdrive.c
new file mode 100644
index 000000000..b17fb0fc4
--- /dev/null
+++ b/hw/kdrive/src/kdrive.c
@@ -0,0 +1,872 @@
+/*
+ * $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 "kdrive.h"
+#include <mivalidate.h>
+#include <dixstruct.h>
+
+CARD8 kdBpp[] = { 1, 4, 8, 16, 24, 32 };
+
+#define NUM_KD_BPP (sizeof (kdBpp) / sizeof (kdBpp[0]))
+
+int kdScreenPrivateIndex;
+unsigned long kdGeneration;
+
+Bool kdVideoTest;
+unsigned long kdVideoTestTime;
+Bool kdEmulateMiddleButton;
+Bool kdDisableZaphod;
+Bool kdEnabled;
+Bool kdSwitchPending;
+
+void (*restoreHardware)(void);
+
+/*
+ * Carry arguments from InitOutput through driver initialization
+ * to KdScreenInit
+ */
+
+KdOsFuncs *kdOsFuncs;
+extern WindowPtr *WindowTable;
+
+void
+KdSetRootClip (ScreenPtr pScreen, BOOL enable)
+{
+ WindowPtr pWin = WindowTable[pScreen->myNum];
+ WindowPtr pChild;
+ Bool WasViewable = (Bool)(pWin->viewable);
+ Bool anyMarked;
+ RegionPtr pOldClip, bsExposed;
+#ifdef DO_SAVE_UNDERS
+ Bool dosave = FALSE;
+#endif
+ WindowPtr pLayerWin;
+ BoxRec box;
+
+ if (WasViewable)
+ {
+ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
+ {
+ (void) (*pScreen->MarkOverlappedWindows)(pChild,
+ pChild,
+ &pLayerWin);
+ }
+ (*pScreen->MarkWindow) (pWin);
+ anyMarked = TRUE;
+ if (pWin->valdata)
+ {
+ if (HasBorder (pWin))
+ {
+ RegionPtr borderVisible;
+
+ borderVisible = REGION_CREATE(pScreen, NullBox, 1);
+ REGION_SUBTRACT(pScreen, borderVisible,
+ &pWin->borderClip, &pWin->winSize);
+ pWin->valdata->before.borderVisible = borderVisible;
+ }
+ pWin->valdata->before.resized = TRUE;
+ }
+ }
+
+ if (enable)
+ {
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pScreen->width;
+ box.y2 = pScreen->height;
+ REGION_RESET(pScreen, &pWin->borderClip, &box);
+ REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList);
+ }
+ else
+ {
+ REGION_EMPTY(pScreen, &pWin->borderClip);
+ REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList);
+ }
+
+ ResizeChildrenWinSize (pWin, 0, 0, 0, 0);
+
+ if (WasViewable)
+ {
+ if (pWin->backStorage)
+ {
+ pOldClip = REGION_CREATE(pScreen, NullBox, 1);
+ REGION_COPY(pScreen, pOldClip, &pWin->clipList);
+ }
+
+ if (pWin->firstChild)
+ {
+ anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin->firstChild,
+ pWin->firstChild,
+ (WindowPtr *)NULL);
+ }
+ else
+ {
+ (*pScreen->MarkWindow) (pWin);
+ anyMarked = TRUE;
+ }
+
+#ifdef DO_SAVE_UNDERS
+ if (DO_SAVE_UNDERS(pWin))
+ {
+ dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin);
+ }
+#endif /* DO_SAVE_UNDERS */
+
+ if (anyMarked)
+ (*pScreen->ValidateTree)(pWin, NullWindow, VTOther);
+ }
+
+ if (pWin->backStorage &&
+ ((pWin->backingStore == Always) || WasViewable))
+ {
+ if (!WasViewable)
+ pOldClip = &pWin->clipList; /* a convenient empty region */
+ bsExposed = (*pScreen->TranslateBackingStore)
+ (pWin, 0, 0, pOldClip,
+ pWin->drawable.x, pWin->drawable.y);
+ if (WasViewable)
+ REGION_DESTROY(pScreen, pOldClip);
+ if (bsExposed)
+ {
+ RegionPtr valExposed = NullRegion;
+
+ if (pWin->valdata)
+ valExposed = &pWin->valdata->after.exposed;
+ (*pScreen->WindowExposures) (pWin, valExposed, bsExposed);
+ if (valExposed)
+ REGION_EMPTY(pScreen, valExposed);
+ REGION_DESTROY(pScreen, bsExposed);
+ }
+ }
+ if (WasViewable)
+ {
+ if (anyMarked)
+ (*pScreen->HandleExposures)(pWin);
+#ifdef DO_SAVE_UNDERS
+ if (dosave)
+ (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin);
+#endif /* DO_SAVE_UNDERS */
+ if (anyMarked && pScreen->PostValidateTree)
+ (*pScreen->PostValidateTree)(pWin, NullWindow, VTOther);
+ }
+ if (pWin->realized)
+ WindowsRestructured ();
+}
+
+void
+KdDisableScreen (ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+
+ if (!pScreenPriv->enabled)
+ return;
+ KdSetRootClip (pScreen, FALSE);
+ KdDisableColormap (pScreen);
+ if (!pScreenPriv->screen->dumb)
+ (*pScreenPriv->card->cfuncs->disableAccel) (pScreen);
+ if (!pScreenPriv->screen->softCursor)
+ (*pScreenPriv->card->cfuncs->disableCursor) (pScreen);
+ if (pScreenPriv->card->cfuncs->dpms)
+ (*pScreenPriv->card->cfuncs->dpms) (pScreen, KD_DPMS_NORMAL);
+ pScreenPriv->enabled = FALSE;
+ (*pScreenPriv->card->cfuncs->disable) (pScreen);
+}
+
+void
+KdDisableScreens (void)
+{
+ KdCardInfo *card;
+ KdScreenInfo *screen;
+
+ if (kdEnabled)
+ {
+ kdEnabled = FALSE;
+ for (card = kdCardInfo; card; card = card->next)
+ {
+ for (screen = card->screenList; screen; screen = screen->next)
+ if (screen->mynum == card->selected && screen->pScreen)
+ KdDisableScreen (screen->pScreen);
+ if (card->driver)
+ (*card->cfuncs->restore) (card);
+ }
+ (*kdOsFuncs->Disable) ();
+ KdDisableInput ();
+ }
+}
+
+void
+KdEnableScreen (ScreenPtr pScreen)
+{
+ KdScreenPriv (pScreen);
+
+ if (pScreenPriv->enabled)
+ return;
+ (*pScreenPriv->card->cfuncs->enable) (pScreen);
+ pScreenPriv->enabled = TRUE;
+ pScreenPriv->card->selected = pScreenPriv->screen->mynum;
+ if (!pScreenPriv->screen->softCursor)
+ (*pScreenPriv->card->cfuncs->enableCursor) (pScreen);
+ if (!pScreenPriv->screen->dumb)
+ (*pScreenPriv->card->cfuncs->enableAccel) (pScreen);
+ KdEnableColormap (pScreen);
+ KdSetRootClip (pScreen, TRUE);
+ if (pScreenPriv->card->cfuncs->dpms)
+ (*pScreenPriv->card->cfuncs->dpms) (pScreen, pScreenPriv->dpmsState);
+}
+
+void
+KdEnableScreens (void)
+{
+ KdCardInfo *card;
+ KdScreenInfo *screen;
+
+ if (!kdEnabled)
+ {
+ kdEnabled = TRUE;
+ (*kdOsFuncs->Enable) ();
+ for (card = kdCardInfo; card; card = card->next)
+ {
+ (*card->cfuncs->preserve) (card);
+ for (screen = card->screenList; screen; screen = screen->next)
+ if (screen->mynum == card->selected && screen->pScreen)
+ KdEnableScreen (screen->pScreen);
+ }
+ KdEnableInput ();
+ }
+}
+
+void
+KdProcessSwitch (void)
+{
+ if (kdEnabled)
+ KdDisableScreens ();
+ else
+ {
+ KdReleaseAllKeys ();
+ KdEnableScreens ();
+ }
+}
+
+void
+AbortDDX(void)
+{
+ KdDisableScreens ();
+ if (kdOsFuncs)
+ {
+ if (kdEnabled)
+ (*kdOsFuncs->Disable) ();
+ (*kdOsFuncs->Fini) ();
+ }
+}
+
+void
+ddxUseMsg()
+{
+}
+
+void
+ddxGiveUp ()
+{
+ AbortDDX ();
+}
+
+void
+KdParseScreen (KdScreenInfo *screen,
+ char *arg)
+{
+ screen->width = 0;
+ screen->height = 0;
+ screen->depth = 0;
+ screen->rate = 0;
+ if (!arg)
+ return;
+
+ screen->width = atoi(arg);
+ arg = strchr (arg, 'x');
+ if (!arg)
+ return;
+ arg++;
+
+ screen->height = atoi(arg);
+ arg = strchr (arg, 'x');
+ if (!arg)
+ return;
+ arg++;
+
+ screen->depth = atoi(arg);
+ arg = strchr (arg, 'x');
+ if (!arg)
+ return;
+ arg++;
+
+ screen->rate = atoi(arg);
+ arg = strchr (arg, 'x');
+ if (!arg)
+ return;
+ arg++;
+}
+
+Bool kdDumbDriver;
+Bool kdSoftCursor;
+
+int
+ddxProcessArgument (int argc, char **argv, int i)
+{
+ KdCardInfo *card;
+ KdScreenInfo *screen;
+
+ if (!strcmp (argv[i], "-card"))
+ {
+ if ((i+1) < argc)
+ InitCard (argv[i+1]);
+ else
+ UseMsg ();
+ return 2;
+ }
+ if (!strcmp (argv[i], "-screen"))
+ {
+ if ((i+1) < argc)
+ {
+ card = KdCardInfoLast ();
+ if (!card)
+ {
+ InitCard (0);
+ card = KdCardInfoLast ();
+ }
+ screen = KdScreenInfoAdd (card);
+ KdParseScreen (screen, argv[i+1]);
+ screen->dumb = kdDumbDriver;
+ screen->softCursor = kdSoftCursor;
+ kdDumbDriver = FALSE;
+ kdSoftCursor = FALSE;
+ }
+ else
+ UseMsg ();
+ return 2;
+ }
+ if (!strcmp (argv[i], "-zaphod"))
+ {
+ kdDisableZaphod = TRUE;
+ return 1;
+ }
+ if (!strcmp (argv[i], "-3button"))
+ {
+ kdEmulateMiddleButton = FALSE;
+ return 1;
+ }
+ if (!strcmp (argv[i], "-2button"))
+ {
+ kdEmulateMiddleButton = TRUE;
+ return 1;
+ }
+ if (!strcmp (argv[i], "-dumb"))
+ {
+ kdDumbDriver = TRUE;
+ return 1;
+ }
+ if (!strcmp (argv[i], "-softCursor"))
+ {
+ kdSoftCursor = TRUE;
+ return 1;
+ }
+ if (!strcmp (argv[i], "-videoTest"))
+ {
+ kdVideoTest = TRUE;
+ return 1;
+ }
+ if (!strcmp (argv[i], "-standalone"))
+ return 1;
+ return 0;
+}
+
+/*
+ * These are getting tossed in here until I can think of where
+ * they really belong
+ */
+
+void
+KdOsInit (KdOsFuncs *pOsFuncs)
+{
+ kdOsFuncs = pOsFuncs;
+ if (pOsFuncs)
+ {
+ if (serverGeneration == 1)
+ (*pOsFuncs->Init) ();
+ }
+}
+
+Bool
+KdAllocatePrivates (ScreenPtr pScreen)
+{
+ KdPrivScreenPtr pScreenPriv;
+
+ if (kdGeneration != serverGeneration)
+ {
+ kdScreenPrivateIndex = AllocateScreenPrivateIndex();
+ kdGeneration = serverGeneration;
+ }
+ pScreenPriv = (KdPrivScreenPtr) xalloc(sizeof (*pScreenPriv));
+ memset (pScreenPriv, '\0', sizeof (KdPrivScreenRec));
+ if (!pScreenPriv)
+ return FALSE;
+ KdSetScreenPriv (pScreen, pScreenPriv);
+ return TRUE;
+}
+
+Bool
+KdCloseScreen (int index, ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ KdCardInfo *card = pScreenPriv->card;
+ Bool ret;
+
+ pScreen->CloseScreen = pScreenPriv->CloseScreen;
+ ret = (*pScreen->CloseScreen) (index, pScreen);
+
+ if (pScreenPriv->dpmsState != KD_DPMS_NORMAL)
+ (*card->cfuncs->dpms) (pScreen, KD_DPMS_NORMAL);
+
+ if (screen->mynum == card->selected)
+ KdDisableScreen (pScreen);
+
+ /*
+ * Restore video hardware when last screen is closed
+ */
+ if (screen == card->screenList)
+ (*card->cfuncs->restore) (card);
+
+ if (!pScreenPriv->screen->dumb)
+ (*card->cfuncs->finiAccel) (pScreen);
+
+ if (!pScreenPriv->screen->softCursor)
+ (*card->cfuncs->finiCursor) (pScreen);
+
+ (*card->cfuncs->scrfini) (screen);
+
+ /*
+ * Clean up card when last screen is closed, DIX closes them in
+ * reverse order, thus we check for when the first in the list is closed
+ */
+ if (screen == card->screenList)
+ {
+ (*card->cfuncs->cardfini) (card);
+ /*
+ * Clean up OS when last card is closed
+ */
+ if (card == kdCardInfo)
+ {
+ if (kdEnabled)
+ {
+ kdEnabled = FALSE;
+ (*kdOsFuncs->Disable) ();
+ }
+ }
+ }
+
+ pScreenPriv->screen->pScreen = 0;
+
+ xfree ((pointer) pScreenPriv);
+ return ret;
+}
+
+Bool
+KdSaveScreen (ScreenPtr pScreen, int on)
+{
+ KdScreenPriv(pScreen);
+ int dpmsState;
+
+ if (!pScreenPriv->card->cfuncs->dpms)
+ return FALSE;
+
+ dpmsState = pScreenPriv->dpmsState;
+ switch (on) {
+ case SCREEN_SAVER_OFF:
+ dpmsState = KD_DPMS_NORMAL;
+ break;
+ case SCREEN_SAVER_ON:
+ if (dpmsState == KD_DPMS_NORMAL)
+ dpmsState = KD_DPMS_NORMAL+1;
+ break;
+ case SCREEN_SAVER_CYCLE:
+ if (dpmsState < KD_DPMS_MAX)
+ dpmsState++;
+ break;
+ case SCREEN_SAVER_FORCER:
+ break;
+ }
+ if (dpmsState != pScreenPriv->dpmsState)
+ {
+ if (pScreenPriv->enabled)
+ (*pScreenPriv->card->cfuncs->dpms) (pScreen, dpmsState);
+ pScreenPriv->dpmsState = dpmsState;
+ }
+ return TRUE;
+}
+
+Bool
+KdCreateWindow (WindowPtr pWin)
+{
+ if (!pWin->parent)
+ {
+ KdScreenPriv(pWin->drawable.pScreen);
+
+ if (!pScreenPriv->enabled)
+ {
+ REGION_EMPTY (pWin->drawable.pScreen, &pWin->borderClip);
+ REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList);
+ }
+ }
+ return TRUE;
+}
+
+/* Pass through AddScreen, which doesn't take any closure */
+static KdScreenInfo *kdCurrentScreen;
+
+Bool
+KdScreenInit(int index, ScreenPtr pScreen, int argc, char **argv)
+{
+ KdScreenInfo *screen = kdCurrentScreen;
+ KdCardInfo *card = screen->card;
+ KdPrivScreenPtr pScreenPriv;
+
+ KdAllocatePrivates (pScreen);
+
+ pScreenPriv = KdGetScreenPriv(pScreen);
+
+ screen->pScreen = pScreen;
+ pScreenPriv->screen = screen;
+ pScreenPriv->card = card;
+ pScreenPriv->bytesPerPixel = screen->bitsPerPixel >> 3;
+ pScreenPriv->dpmsState = KD_DPMS_NORMAL;
+
+ /*
+ * This is done in this order so that backing store wraps
+ * our GC functions; fbFinishScreenInit initializes MI
+ * backing store
+ */
+ if (!fbSetupScreen (pScreen,
+ screen->frameBuffer,
+ screen->width, screen->height,
+ screen->dpix, screen->dpiy,
+ screen->pixelStride,
+ screen->bitsPerPixel))
+ {
+ return FALSE;
+ }
+
+ /*
+ * Set colormap functions
+ */
+ pScreen->InstallColormap = KdInstallColormap;
+ pScreen->UninstallColormap = KdUninstallColormap;
+ pScreen->ListInstalledColormaps = KdListInstalledColormaps;
+ pScreen->StoreColors = KdStoreColors;
+
+ pScreen->SaveScreen = KdSaveScreen;
+ pScreen->CreateWindow = KdCreateWindow;
+
+ if (!screen->dumb && card->cfuncs->initAccel)
+ if (!(*card->cfuncs->initAccel) (pScreen))
+ screen->dumb = TRUE;
+
+ if (!fbFinishScreenInit (pScreen,
+ screen->frameBuffer,
+ screen->width, screen->height,
+ screen->dpix, screen->dpiy,
+ screen->pixelStride,
+ screen->bitsPerPixel))
+ {
+ return FALSE;
+ }
+
+ /*
+ * Plug in our own block/wakeup handlers.
+ * miScreenInit installs NoopDDA in both places
+ */
+ pScreen->BlockHandler = KdBlockHandler;
+ pScreen->WakeupHandler = KdWakeupHandler;
+
+ /*
+ * Wrap CloseScreen, the order now is:
+ * KdCloseScreen
+ * miBSCloseScreen
+ * fbCloseScreen
+ */
+ pScreenPriv->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = KdCloseScreen;
+
+ if (screen->softCursor ||
+ !card->cfuncs->initCursor ||
+ !(*card->cfuncs->initCursor) (pScreen))
+ {
+ /* Use MI for cursor display and event queueing. */
+ screen->softCursor = TRUE;
+ miDCInitialize(pScreen, &kdPointerScreenFuncs);
+ }
+
+ if (!fbCreateDefColormap (pScreen))
+ {
+ return FALSE;
+ }
+
+ /*
+ * Enable the hardware
+ */
+ if (!kdEnabled)
+ {
+ kdEnabled = TRUE;
+ (*kdOsFuncs->Enable) ();
+ }
+
+ if (screen->mynum == card->selected)
+ {
+ (*card->cfuncs->preserve) (card);
+ (*card->cfuncs->enable) (pScreen);
+ pScreenPriv->enabled = TRUE;
+ if (!screen->softCursor)
+ (*card->cfuncs->enableCursor) (pScreen);
+ KdEnableColormap (pScreen);
+ if (!screen->dumb)
+ (*card->cfuncs->enableAccel) (pScreen);
+ }
+
+ return TRUE;
+}
+
+void
+KdInitScreen (ScreenInfo *pScreenInfo,
+ KdScreenInfo *screen,
+ int argc,
+ char **argv)
+{
+ KdCardInfo *card = screen->card;
+ int i;
+
+ (*card->cfuncs->scrinit) (screen);
+
+ if (!screen->dpix)
+ screen->dpix = 75;
+
+ if (!screen->dpiy)
+ screen->dpiy = 75;
+ if (!card->cfuncs->initAccel)
+ screen->dumb = TRUE;
+ if (!card->cfuncs->initCursor)
+ screen->softCursor = TRUE;
+
+}
+
+Bool
+KdSetPixmapFormats (ScreenInfo *pScreenInfo)
+{
+ CARD8 depthToBpp[33]; /* depth -> bpp map */
+ CARD8 bppToDepth[33]; /* bpp -> depth map */
+ KdCardInfo *card;
+ KdScreenInfo *screen;
+ int i;
+ PixmapFormatRec *format;
+
+ for (i = 1; i <= 32; i++)
+ {
+ depthToBpp[i] = 0;
+ bppToDepth[i] = 0;
+ }
+
+ /*
+ * Generate mappings between bitsPerPixel and depth,
+ * also ensure that all screens comply with protocol
+ * restrictions on equivalent formats for the same
+ * depth on different screens
+ */
+ for (card = kdCardInfo; card; card = card->next)
+ {
+ for (screen = card->screenList; screen; screen = screen->next)
+ {
+ if (!depthToBpp[screen->depth])
+ depthToBpp[screen->depth] = screen->bitsPerPixel;
+ else if (depthToBpp[screen->depth] != screen->bitsPerPixel)
+ return FALSE;
+ if (!bppToDepth[screen->bitsPerPixel])
+ bppToDepth[screen->bitsPerPixel] = screen->depth;
+ }
+ }
+
+ /*
+ * Fill in additional formats
+ */
+ for (i = 0; i < NUM_KD_BPP; i++)
+ if (!bppToDepth[kdBpp[i]] && !depthToBpp[kdBpp[i]])
+ {
+ bppToDepth[kdBpp[i]] = kdBpp[i];
+ depthToBpp[kdBpp[i]] = kdBpp[i];
+ }
+
+ pScreenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
+ pScreenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
+ pScreenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
+ pScreenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
+
+ pScreenInfo->numPixmapFormats = 0;
+
+ for (i = 1; i <= 32; i++)
+ {
+ if (depthToBpp[i])
+ {
+ format = &pScreenInfo->formats[pScreenInfo->numPixmapFormats++];
+ format->depth = i;
+ format->bitsPerPixel = depthToBpp[i];
+ format->scanlinePad = BITMAP_SCANLINE_PAD;
+ }
+ }
+
+ return TRUE;
+}
+
+void
+KdAddScreen (ScreenInfo *pScreenInfo,
+ KdScreenInfo *screen,
+ int argc,
+ char **argv)
+{
+ int i;
+ /*
+ * Fill in fb visual type masks for this screen
+ */
+ for (i = 0; i < pScreenInfo->numPixmapFormats; i++)
+ {
+ unsigned long visuals;
+ Pixel rm, gm, bm;
+
+ if (pScreenInfo->formats[i].depth == screen->depth)
+ {
+ visuals = screen->visuals;
+ rm = screen->redMask;
+ gm = screen->greenMask;
+ bm = screen->blueMask;
+ }
+ else
+ {
+ visuals = 0;
+ rm = gm = bm = 0;
+ }
+ fbSetVisualTypesAndMasks (pScreenInfo->formats[i].depth,
+ visuals,
+ 8,
+ rm, gm, bm);
+ }
+
+ kdCurrentScreen = screen;
+
+ AddScreen (KdScreenInit, argc, argv);
+}
+
+void
+KdInitOutput (ScreenInfo *pScreenInfo,
+ int argc,
+ char **argv)
+{
+ int i;
+ KdCardInfo *card;
+ KdScreenInfo *screen;
+
+ if (!kdCardInfo)
+ {
+ InitCard (0);
+ card = KdCardInfoLast ();
+ screen = KdScreenInfoAdd (card);
+ KdParseScreen (screen, 0);
+ }
+ /*
+ * Initialize all of the screens for all of the cards
+ */
+ for (card = kdCardInfo; card; card = card->next)
+ {
+ if ((*card->cfuncs->cardinit) (card))
+ {
+ for (screen = card->screenList; screen; screen = screen->next)
+ KdInitScreen (pScreenInfo, screen, argc, argv);
+ }
+ }
+
+ /*
+ * Merge the various pixmap formats together, this can fail
+ * when two screens share depth but not bitsPerPixel
+ */
+ if (!KdSetPixmapFormats (pScreenInfo))
+ return;
+
+ /*
+ * Add all of the screens
+ */
+ for (card = kdCardInfo; card; card = card->next)
+ for (screen = card->screenList; screen; screen = screen->next)
+ KdAddScreen (pScreenInfo, screen, argc, argv);
+}
+
+#ifdef XTESTEXT1
+void
+XTestGenerateEvent(dev_type, keycode, keystate, mousex, mousey)
+ int dev_type;
+ int keycode;
+ int keystate;
+ int mousex;
+ int mousey;
+{
+}
+
+void
+XTestGetPointerPos(fmousex, fmousey)
+ short *fmousex, *fmousey;
+{
+}
+
+void
+XTestJumpPointer(jx, jy, dev_type)
+ int jx;
+ int jy;
+ int dev_type;
+{
+}
+#endif
+
+#ifdef DPMSExtension
+void
+DPMSSet(int level)
+{
+}
+
+int
+DPMSGet (int *level)
+{
+ return -1;
+}
+
+Bool
+DPMSSupported (void)
+{
+ return FALSE;
+}
+#endif
diff --git a/hw/kdrive/src/kdrive.h b/hw/kdrive/src/kdrive.h
new file mode 100644
index 000000000..50601d690
--- /dev/null
+++ b/hw/kdrive/src/kdrive.h
@@ -0,0 +1,362 @@
+/*
+ * $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 <stdio.h>
+#include "X.h"
+#define NEED_EVENTS
+#include "Xproto.h"
+#include "Xos.h"
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "windowstr.h"
+#include "servermd.h"
+#include "mibstore.h"
+#include "colormapst.h"
+#include "gcstruct.h"
+#include "input.h"
+#include "mipointer.h"
+#include "mi.h"
+#include "dix.h"
+#include "fb.h"
+
+extern WindowPtr *WindowTable;
+
+#define KD_DPMS_NORMAL 0
+#define KD_DPMS_STANDBY 1
+#define KD_DPMS_SUSPEND 2
+#define KD_DPMS_POWERDOWN 3
+#define KD_DPMS_MAX KD_DPMS_POWERDOWN
+
+/*
+ * Configuration information per video card
+ */
+#define KD_MAX_CARD_ADDRESS 8
+typedef struct _KdCardAttr {
+ CARD32 io;
+ CARD32 address[KD_MAX_CARD_ADDRESS];
+ int naddr;
+} KdCardAttr;
+
+typedef struct _KdCardInfo {
+ struct _KdCardFuncs *cfuncs;
+ void *closure;
+ KdCardAttr attr;
+ void *driver;
+ struct _KdScreenInfo *screenList;
+ int selected;
+ struct _KdCardInfo *next;
+} KdCardInfo;
+
+extern KdCardInfo *kdCardInfo;
+
+/*
+ * Configuration information per X screen
+ */
+typedef struct _KdScreenInfo {
+ struct _KdScreenInfo *next;
+ KdCardInfo *card;
+ ScreenPtr pScreen;
+ void *driver;
+ CARD8 *frameBuffer;
+ int width;
+ int height;
+ int depth;
+ int rate;
+ int bitsPerPixel;
+ int pixelStride;
+ int byteStride;
+ int dpix, dpiy;
+ unsigned long visuals;
+ Pixel redMask, greenMask, blueMask;
+ Bool dumb;
+ Bool softCursor;
+ int mynum;
+} KdScreenInfo;
+
+typedef struct _KdCardFuncs {
+ Bool (*cardinit) (KdCardInfo *); /* detect and map device */
+ Bool (*scrinit) (KdScreenInfo *);/* initialize screen information */
+ void (*preserve) (KdCardInfo *); /* save graphics card state */
+ void (*enable) (ScreenPtr); /* set up for rendering */
+ Bool (*dpms) (ScreenPtr, int); /* set DPMS screen saver */
+ void (*disable) (ScreenPtr); /* turn off rendering */
+ void (*restore) (KdCardInfo *); /* restore graphics card state */
+ void (*scrfini) (KdScreenInfo *);/* close down screen */
+ void (*cardfini) (KdCardInfo *); /* close down */
+
+ Bool (*initCursor) (ScreenPtr); /* detect and map cursor */
+ void (*enableCursor) (ScreenPtr); /* enable cursor */
+ void (*disableCursor) (ScreenPtr); /* disable cursor */
+ void (*finiCursor) (ScreenPtr); /* close down */
+ void (*recolorCursor) (ScreenPtr, int, xColorItem *);
+
+ Bool (*initAccel) (ScreenPtr);
+ void (*enableAccel) (ScreenPtr);
+ void (*disableAccel) (ScreenPtr);
+ void (*finiAccel) (ScreenPtr);
+
+ void (*getColors) (ScreenPtr, int, xColorItem *);
+ void (*putColors) (ScreenPtr, int, xColorItem *);
+} KdCardFuncs;
+
+#define KD_MAX_PSEUDO_DEPTH 8
+#define KD_MAX_PSEUDO_SIZE (1 << KD_MAX_PSEUDO_DEPTH)
+
+typedef struct {
+ KdScreenInfo *screen;
+ KdCardInfo *card;
+
+ Bool enabled;
+ int bytesPerPixel;
+
+ int dpmsState;
+
+ ColormapPtr pInstalledmap; /* current colormap */
+ xColorItem systemPalette[KD_MAX_PSEUDO_SIZE];/* saved windows colors */
+
+ CloseScreenProcPtr CloseScreen;
+} KdPrivScreenRec, *KdPrivScreenPtr;
+
+typedef struct _KdMouseFuncs {
+ int (*Init) (void);
+ void (*Read) (int);
+ void (*Fini) (int);
+} KdMouseFuncs;
+
+typedef struct _KdKeyboardFuncs {
+ void (*Load) (void);
+ int (*Init) (void);
+ void (*Read) (int);
+ void (*Leds) (int);
+ void (*Bell) (int, int, int);
+ void (*Fini) (int);
+ int LockLed;
+} KdKeyboardFuncs;
+
+typedef struct _KdOsFuncs {
+ int (*Init) (void);
+ void (*Enable) (void);
+ Bool (*SpecialKey) (KeySym);
+ void (*Disable) (void);
+ void (*Fini) (void);
+} KdOsFuncs;
+
+/*
+ * This is the only completely portable way to
+ * compute this info.
+ */
+
+#ifndef BitsPerPixel
+#define BitsPerPixel(d) (\
+ PixmapWidthPaddingInfo[d].notPower2 ? \
+ (PixmapWidthPaddingInfo[d].bytesPerPixel * 8) : \
+ ((1 << PixmapWidthPaddingInfo[d].padBytesLog2) * 8 / \
+ (PixmapWidthPaddingInfo[d].padRoundUp+1)))
+#endif
+
+extern int kdScreenPrivateIndex;
+extern unsigned long kdGeneration;
+extern Bool kdEnabled;
+extern Bool kdSwitchPending;
+extern Bool kdEmulateMiddleButton;
+extern Bool kdDisableZaphod;
+extern KdOsFuncs *kdOsFuncs;
+
+#define KdGetScreenPriv(pScreen) ((KdPrivScreenPtr) \
+ (pScreen)->devPrivates[kdScreenPrivateIndex].ptr)
+#define KdSetScreenPriv(pScreen,v) ((pScreen)->devPrivates[kdScreenPrivateIndex].ptr = \
+ (pointer) v)
+#define KdScreenPriv(pScreen) KdPrivScreenPtr pScreenPriv = KdGetScreenPriv(pScreen)
+
+/* knoop.c */
+extern GCOps kdNoopOps;
+
+/* kcmap.c */
+void
+KdSetColormap (ScreenPtr pScreen);
+
+void
+KdEnableColormap (ScreenPtr pScreen);
+
+void
+KdDisableColormap (ScreenPtr pScreen);
+
+void
+KdInstallColormap (ColormapPtr pCmap);
+
+void
+KdUninstallColormap (ColormapPtr pCmap);
+
+int
+KdListInstalledColormaps (ScreenPtr pScreen, Colormap *pCmaps);
+
+void
+KdStoreColors (ColormapPtr pCmap, int ndef, xColorItem *pdefs);
+
+/* kdrive.c */
+extern miPointerScreenFuncRec kdPointerScreenFuncs;
+
+void
+KdSetRootClip (ScreenPtr pScreen, BOOL enable);
+
+void
+KdDisableScreen (ScreenPtr pScreen);
+
+void
+KdDisableScreens (void);
+
+void
+KdEnableScreen (ScreenPtr pScreen);
+
+void
+KdEnableScreens (void);
+
+void
+KdProcessSwitch (void);
+
+void
+KdParseScreen (KdScreenInfo *screen,
+ char *arg);
+
+void
+KdOsInit (KdOsFuncs *pOsFuncs);
+
+Bool
+KdAllocatePrivates (ScreenPtr pScreen);
+
+Bool
+KdCloseScreen (int index, ScreenPtr pScreen);
+
+Bool
+KdSaveScreen (ScreenPtr pScreen, int on);
+
+Bool
+KdScreenInit(int index, ScreenPtr pScreen, int argc, char **argv);
+
+void
+KdInitScreen (ScreenInfo *pScreenInfo,
+ KdScreenInfo *screen,
+ int argc,
+ char **argv);
+
+void
+KdInitCard (ScreenInfo *pScreenInfo,
+ KdCardInfo *card,
+ int argc,
+ char **argv);
+
+void
+KdInitOutput (ScreenInfo *pScreenInfo,
+ int argc,
+ char **argv);
+
+
+
+void
+KdInitOutput (ScreenInfo *pScreenInfo,
+ int argc, char **argv);
+
+/* kinfo.c */
+KdCardInfo *
+KdCardInfoAdd (KdCardFuncs *funcs,
+ KdCardAttr *attr,
+ void *closure);
+
+KdCardInfo *
+KdCardInfoLast (void);
+
+void
+KdCardInfoDispose (KdCardInfo *ci);
+
+KdScreenInfo *
+KdScreenInfoAdd (KdCardInfo *ci);
+
+void
+KdScreenInfoDispose (KdScreenInfo *si);
+
+
+/* kinput.c */
+void
+KdInitInput(KdMouseFuncs *, KdKeyboardFuncs *);
+
+void
+KdEnqueueKeyboardEvent(unsigned char scan_code,
+ unsigned char is_up);
+
+#define KD_BUTTON_1 0x01
+#define KD_BUTTON_2 0x02
+#define KD_BUTTON_3 0x04
+#define KD_MOUSE_DELTA 0x80000000
+
+void
+KdEnqueueMouseEvent(unsigned long flags, int x, int y);
+
+void
+KdEnqueueMotionEvent (int x, int y);
+
+void
+KdReleaseAllKeys (void);
+
+void
+KdSetLed (int led, Bool on);
+
+void
+KdBlockHandler (int screen,
+ pointer blockData,
+ pointer timeout,
+ pointer readmask);
+
+void
+KdWakeupHandler (int screen,
+ pointer data,
+ unsigned long result,
+ pointer readmask);
+
+void
+KdDisableInput (void);
+
+void
+KdEnableInput (void);
+
+void
+ProcessInputEvents ();
+
+extern KdMouseFuncs Ps2MouseFuncs;
+extern KdKeyboardFuncs LinuxKeyboardFuncs;
+extern KdOsFuncs LinuxFuncs;
+
+/* kmap.c */
+void *
+KdMapDevice (CARD32 addr, CARD32 size);
+
+void
+KdUnmapDevice (void *addr, CARD32 size);
+
+/* ktest.c */
+Bool
+KdFrameBufferValid (CARD8 *base, int size);
+
+int
+KdFrameBufferSize (CARD8 *base, int max);
diff --git a/hw/kdrive/src/kinfo.c b/hw/kdrive/src/kinfo.c
new file mode 100644
index 000000000..6c5d2cec9
--- /dev/null
+++ b/hw/kdrive/src/kinfo.c
@@ -0,0 +1,110 @@
+/*
+ * $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 "kdrive.h"
+
+KdCardInfo *kdCardInfo;
+
+KdCardInfo *
+KdCardInfoAdd (KdCardFuncs *funcs,
+ KdCardAttr *attr,
+ void *closure)
+{
+ KdCardInfo *ci, **prev;
+
+ ci = (KdCardInfo *) xalloc (sizeof (KdCardInfo));
+ if (!ci)
+ return 0;
+ bzero (ci, sizeof (KdCardInfo));
+ for (prev = &kdCardInfo; *prev; prev = &(*prev)->next);
+ *prev = ci;
+ ci->cfuncs = funcs;
+ ci->attr = *attr;
+ ci->closure = closure;
+ ci->screenList = 0;
+ ci->selected = 0;
+ ci->next = 0;
+ return ci;
+}
+
+KdCardInfo *
+KdCardInfoLast (void)
+{
+ KdCardInfo *ci;
+
+ if (!kdCardInfo)
+ return 0;
+ for (ci = kdCardInfo; ci->next; ci = ci->next);
+ return ci;
+}
+
+void
+KdCardInfoDispose (KdCardInfo *ci)
+{
+ KdCardInfo **prev;
+
+ for (prev = &kdCardInfo; *prev; prev = &(*prev)->next)
+ if (*prev == ci)
+ {
+ *prev = ci->next;
+ xfree (ci);
+ break;
+ }
+}
+
+KdScreenInfo *
+KdScreenInfoAdd (KdCardInfo *ci)
+{
+ KdScreenInfo *si, **prev;
+ int n;
+
+ si = (KdScreenInfo *) xalloc (sizeof (KdScreenInfo));
+ if (!si)
+ return 0;
+ bzero (si, sizeof (KdScreenInfo));
+ for (prev = &ci->screenList, n = 0; *prev; prev = &(*prev)->next, n++);
+ *prev = si;
+ si->next = 0;
+ si->card = ci;
+ si->mynum = n;
+ return si;
+}
+
+void
+KdScreenInfoDispose (KdScreenInfo *si)
+{
+ KdCardInfo *ci = si->card;
+ KdScreenInfo **prev;
+
+ for (prev = &ci->screenList; *prev; prev = &(*prev)->next)
+ if (*prev == si)
+ {
+ *prev = si->next;
+ xfree (si);
+ if (!ci->screenList)
+ KdCardInfoDispose (ci);
+ break;
+ }
+}
diff --git a/hw/kdrive/src/kinput.c b/hw/kdrive/src/kinput.c
new file mode 100644
index 000000000..27207ac1e
--- /dev/null
+++ b/hw/kdrive/src/kinput.c
@@ -0,0 +1,1331 @@
+/*
+ * $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 "kdrive.h"
+#include "inputstr.h"
+
+#include <X11/keysym.h>
+#include "kkeymap.h"
+#include <signal.h>
+#include <stdio.h>
+
+static DeviceIntPtr pKdKeyboard, pKdPointer;
+
+static KdMouseFuncs *kdMouseFuncs;
+static KdKeyboardFuncs *kdKeyboardFuncs;
+static int kdMouseFd = -1;
+static int kdKeyboardFd = -1;
+static unsigned long kdEmulationTimeout;
+static Bool kdTimeoutPending;
+static int kdBellPitch;
+static int kdBellDuration;
+static int kdLeds;
+
+int kdMinScanCode;
+int kdMaxScanCode;
+int kdMinKeyCode;
+int kdMaxKeyCode;
+int kdKeymapWidth = KD_MAX_WIDTH;
+KeySym kdKeymap[KD_MAX_LENGTH * KD_MAX_WIDTH];
+CARD8 kdModMap[MAP_LENGTH];
+KeySymsRec kdKeySyms;
+
+
+void
+KdResetInputMachine (void);
+
+#define KD_MOUSEBUTTON_COUNT 3
+
+#define KD_KEY_COUNT 248
+
+CARD8 kdKeyState[KD_KEY_COUNT/8];
+
+#define IsKeyDown(key) ((kdKeyState[(key) >> 3] >> ((key) & 7)) & 1)
+
+void
+KdSigio (int sig)
+{
+ if (kdMouseFd >= 0)
+ (*kdMouseFuncs->Read) (kdMouseFd);
+ if (kdKeyboardFd >= 0)
+ (*kdKeyboardFuncs->Read) (kdKeyboardFd);
+}
+
+void
+KdBlockSigio (void)
+{
+ sigset_t set;
+
+ sigemptyset (&set);
+ sigaddset (&set, SIGIO);
+ sigprocmask (SIG_BLOCK, &set, 0);
+}
+
+void
+KdUnblockSigio (void)
+{
+ sigset_t set;
+
+ sigemptyset (&set);
+ sigaddset (&set, SIGIO);
+ sigprocmask (SIG_UNBLOCK, &set, 0);
+}
+
+#define VERIFY_SIGIO
+#ifdef VERIFY_SIGIO
+
+void
+KdAssertSigioBlocked (char *where)
+{
+ sigset_t set, old;
+
+ sigemptyset (&set);
+ sigprocmask (SIG_BLOCK, &set, &old);
+ if (!sigismember (&old, SIGIO))
+ ErrorF ("SIGIO not blocked at %s\n", where);
+}
+
+#else
+
+#define KdVerifySigioBlocked(s)
+
+#endif
+
+static int kdnFds;
+
+#ifdef FNONBLOCK
+#define NOBLOCK FNONBLOCK
+#else
+#define NOBLOCK FNDELAY
+#endif
+
+void
+KdAddFd (int fd)
+{
+ int flags;
+ struct sigaction act;
+ sigset_t set;
+
+ kdnFds++;
+ fcntl (fd, F_SETOWN, getpid());
+ flags = fcntl (fd, F_GETFL);
+ flags |= FASYNC|NOBLOCK;
+ fcntl (fd, F_SETFL, flags);
+ AddEnabledDevice (fd);
+ act.sa_handler = KdSigio;
+ sigemptyset (&act.sa_mask);
+ act.sa_flags = 0;
+ act.sa_restorer = 0;
+ sigaction (SIGIO, &act, 0);
+ sigemptyset (&set);
+ sigprocmask (SIG_SETMASK, &set, 0);
+}
+
+void
+KdRemoveFd (int fd)
+{
+ struct sigaction act;
+ int flags;
+
+ kdnFds--;
+ RemoveEnabledDevice (fd);
+ flags = fcntl (fd, F_GETFL);
+ flags &= ~(FASYNC|NOBLOCK);
+ fcntl (fd, F_SETFL, flags);
+ if (kdnFds == 0)
+ {
+ act.sa_handler = SIG_IGN;
+ sigemptyset (&act.sa_mask);
+ act.sa_flags = 0;
+ act.sa_restorer = 0;
+ sigaction (SIGIO, &act, 0);
+ }
+}
+
+void
+KdDisableInput (void)
+{
+ if (kdMouseFd >= 0)
+ KdRemoveFd (kdMouseFd);
+ if (kdKeyboardFd >= 0)
+ KdRemoveFd (kdKeyboardFd);
+}
+
+void
+KdEnableInput (void)
+{
+ if (kdMouseFd >= 0)
+ KdAddFd (kdMouseFd);
+ if (kdKeyboardFd >= 0)
+ KdAddFd (kdKeyboardFd);
+}
+
+static int
+KdMouseProc(DeviceIntPtr pDevice, int onoff)
+{
+ BYTE map[4];
+ DevicePtr pDev = (DevicePtr)pDevice;
+ int i;
+
+ if (!pDev)
+ return BadImplementation;
+
+ switch (onoff)
+ {
+ case DEVICE_INIT:
+ for (i = 1; i <= KD_MOUSEBUTTON_COUNT; i++)
+ map[i] = i;
+ InitPointerDeviceStruct(pDev, map, KD_MOUSEBUTTON_COUNT,
+ miPointerGetMotionEvents,
+ (PtrCtrlProcPtr)NoopDDA,
+ miPointerGetMotionBufferSize());
+ break;
+
+ case DEVICE_ON:
+ pDev->on = TRUE;
+ pKdPointer = pDevice;
+ if (kdMouseFuncs)
+ {
+ kdMouseFd = (*kdMouseFuncs->Init) ();
+ if (kdMouseFd >= 0)
+ KdAddFd (kdMouseFd);
+ }
+ break;
+ case DEVICE_OFF:
+ case DEVICE_CLOSE:
+ if (pDev->on)
+ {
+ pDev->on = FALSE;
+ pKdPointer = 0;
+ if (kdMouseFd >= 0)
+ {
+ KdRemoveFd (kdMouseFd);
+ (*kdMouseFuncs->Fini) (kdMouseFd);
+ kdMouseFd = -1;
+ }
+ }
+ break;
+ }
+ return Success;
+}
+
+Bool
+LegalModifier(unsigned int key, DevicePtr pDev)
+{
+ return TRUE;
+}
+
+static void
+KdBell (int volume, DeviceIntPtr pDev, pointer ctrl, int something)
+{
+ (*kdKeyboardFuncs->Bell) (volume, kdBellPitch, kdBellDuration);
+}
+
+
+static void
+KdSetLeds (void)
+{
+ (*kdKeyboardFuncs->Leds) (kdLeds);
+}
+
+void
+KdSetLed (int led, Bool on)
+{
+ NoteLedState (pKdKeyboard, led, on);
+ kdLeds = pKdKeyboard->kbdfeed->ctrl.leds;
+ KdSetLeds ();
+}
+
+static void
+KdKbdCtrl (DeviceIntPtr pDevice, KeybdCtrl *ctrl)
+{
+ kdLeds = ctrl->leds;
+ kdBellPitch = ctrl->bell_pitch;
+ kdBellDuration = ctrl->bell_duration;
+ KdSetLeds ();
+}
+
+static int
+KdKeybdProc(DeviceIntPtr pDevice, int onoff)
+{
+ Bool ret;
+ DevicePtr pDev = (DevicePtr)pDevice;
+
+ if (!pDev)
+ return BadImplementation;
+
+ switch (onoff)
+ {
+ case DEVICE_INIT:
+ if (pDev != LookupKeyboardDevice())
+ {
+ return !Success;
+ }
+ ret = InitKeyboardDeviceStruct(pDev,
+ &kdKeySyms,
+ kdModMap,
+ KdBell, KdKbdCtrl);
+ if (!ret)
+ return BadImplementation;
+ break;
+ case DEVICE_ON:
+ pDev->on = TRUE;
+ pKdKeyboard = pDevice;
+ if (kdKeyboardFuncs)
+ {
+ kdKeyboardFd = (*kdKeyboardFuncs->Init) ();
+ if (kdKeyboardFd >= 0)
+ KdAddFd (kdKeyboardFd);
+ }
+ break;
+ case DEVICE_OFF:
+ case DEVICE_CLOSE:
+ pKdKeyboard = 0;
+ if (pDev->on)
+ {
+ pDev->on = FALSE;
+ if (kdKeyboardFd >= 0)
+ {
+ KdRemoveFd (kdKeyboardFd);
+ (*kdKeyboardFuncs->Fini) (kdKeyboardFd);
+ kdKeyboardFd = -1;
+ }
+ }
+ break;
+ }
+ return Success;
+}
+
+extern KeybdCtrl defaultKeyboardControl;
+
+void
+InitAutoRepeats (void)
+{
+ int key_code;
+ unsigned char mask;
+ int i;
+ unsigned char *repeats;
+
+ repeats = defaultKeyboardControl.autoRepeats;
+ memset (repeats, '\0', 32);
+ for (key_code = KD_MIN_KEYCODE; key_code <= KD_MAX_KEYCODE; key_code++)
+ {
+ if (!kdModMap[key_code])
+ {
+ i = key_code >> 3;
+ mask = 1 << (key_code & 7);
+ repeats[i] |= mask;
+ }
+ }
+}
+
+void
+InitModMap (void)
+{
+ int key_code;
+ int row;
+ int width;
+ KeySym *syms;
+
+ width = kdKeySyms.mapWidth;
+ for (key_code = kdMinKeyCode; key_code <= kdMaxKeyCode; key_code++)
+ {
+ kdModMap[key_code] = 0;
+ syms = kdKeymap + (key_code - kdMinKeyCode) * width;
+ for (row = 0; row < width; row++, syms++)
+ {
+ switch (*syms) {
+ case XK_Control_L:
+ case XK_Control_R:
+ kdModMap[key_code] |= ControlMask;
+ break;
+ case XK_Shift_L:
+ case XK_Shift_R:
+ kdModMap[key_code] |= ShiftMask;
+ break;
+ case XK_Caps_Lock:
+ case XK_Shift_Lock:
+ kdModMap[key_code] |= LockMask;
+ break;
+ case XK_Alt_L:
+ case XK_Alt_R:
+ case XK_Meta_L:
+ case XK_Meta_R:
+ kdModMap[key_code] |= Mod1Mask;
+ break;
+ case XK_Num_Lock:
+ kdModMap[key_code] |= Mod2Mask;
+ break;
+ case XK_Super_L:
+ case XK_Super_R:
+ case XK_Hyper_L:
+ case XK_Hyper_R:
+ kdModMap[key_code] |= Mod3Mask;
+ break;
+ case XK_Mode_switch:
+ kdModMap[key_code] |= Mod4Mask;
+ break;
+ }
+ }
+ }
+}
+
+void
+KdInitInput(KdMouseFuncs *pMouseFuncs,
+ KdKeyboardFuncs *pKeyboardFuncs)
+{
+ DeviceIntPtr pKeyboard, pPointer;
+
+ kdMouseFuncs = pMouseFuncs;
+ kdKeyboardFuncs = pKeyboardFuncs;
+ memset (kdKeyState, '\0', sizeof (kdKeyState));
+ if (kdKeyboardFuncs)
+ (*kdKeyboardFuncs->Load) ();
+ kdMinKeyCode = kdMinScanCode + KD_KEY_OFFSET;
+ kdMaxKeyCode = kdMaxScanCode + KD_KEY_OFFSET;
+ kdKeySyms.map = kdKeymap;
+ kdKeySyms.minKeyCode = kdMinKeyCode;
+ kdKeySyms.maxKeyCode = kdMaxKeyCode;
+ kdKeySyms.mapWidth = kdKeymapWidth;
+ kdLeds = 0;
+ kdBellPitch = 1000;
+ kdBellDuration = 200;
+ InitModMap ();
+ InitAutoRepeats ();
+ KdResetInputMachine ();
+ pPointer = AddInputDevice(KdMouseProc, TRUE);
+ pKeyboard = AddInputDevice(KdKeybdProc, TRUE);
+ RegisterPointerDevice(pPointer);
+ RegisterKeyboardDevice(pKeyboard);
+ miRegisterPointerDevice(screenInfo.screens[0], pPointer);
+ mieqInit(&pKeyboard->public, &pPointer->public);
+}
+
+/*
+ * Middle button emulation state machine
+ *
+ * Possible transitions:
+ * Button 1 press v1
+ * Button 1 release ^1
+ * Button 2 press v2
+ * Button 2 release ^2
+ * Button 3 press v3
+ * Button 3 release ^3
+ * Mouse motion <>
+ * Keyboard event k
+ * timeout ...
+ * outside box <->
+ *
+ * States:
+ * start
+ * button_1_pend
+ * button_1_down
+ * button_2_down
+ * button_3_pend
+ * button_3_down
+ * synthetic_2_down_13
+ * synthetic_2_down_3
+ * synthetic_2_down_1
+ *
+ * Transition diagram
+ *
+ * start
+ * v1 -> (hold) (settimeout) button_1_pend
+ * ^1 -> (deliver) start
+ * v2 -> (deliver) button_2_down
+ * ^2 -> (deliever) start
+ * v3 -> (hold) (settimeout) button_3_pend
+ * ^3 -> (deliver) start
+ * <> -> (deliver) start
+ * k -> (deliver) start
+ *
+ * button_1_pend (button 1 is down, timeout pending)
+ * ^1 -> (release) (deliver) start
+ * v2 -> (release) (deliver) button_1_down
+ * ^2 -> (release) (deliver) button_1_down
+ * v3 -> (cleartimeout) (generate v2) synthetic_2_down_13
+ * ^3 -> (release) (deliver) button_1_down
+ * <-> -> (release) (deliver) button_1_down
+ * <> -> (deliver) button_1_pend
+ * k -> (release) (deliver) button_1_down
+ * ... -> (release) button_1_down
+ *
+ * button_1_down (button 1 is down)
+ * ^1 -> (deliver) start
+ * v2 -> (deliver) button_1_down
+ * ^2 -> (deliver) button_1_down
+ * v3 -> (deliver) button_1_down
+ * ^3 -> (deliver) button_1_down
+ * <> -> (deliver) button_1_down
+ * k -> (deliver) button_1_down
+ *
+ * button_2_down (button 2 is down)
+ * v1 -> (deliver) button_2_down
+ * ^1 -> (deliver) button_2_down
+ * ^2 -> (deliver) start
+ * v3 -> (deliver) button_2_down
+ * ^3 -> (deliver) button_2_down
+ * <> -> (deliver) button_2_down
+ * k -> (deliver) button_2_down
+ *
+ * button_3_pend (button 3 is down, timeout pending)
+ * v1 -> (generate v2) synthetic_2_down
+ * ^1 -> (release) (deliver) button_3_down
+ * v2 -> (release) (deliver) button_3_down
+ * ^2 -> (release) (deliver) button_3_down
+ * ^3 -> (release) (deliver) start
+ * <-> -> (release) (deliver) button_3_down
+ * <> -> (deliver) button_3_pend
+ * k -> (release) (deliver) button_3_down
+ * ... -> (release) button_3_down
+ *
+ * button_3_down (button 3 is down)
+ * v1 -> (deliver) button_3_down
+ * ^1 -> (deliver) button_3_down
+ * v2 -> (deliver) button_3_down
+ * ^2 -> (deliver) button_3_down
+ * ^3 -> (deliver) start
+ * <> -> (deliver) button_3_down
+ * k -> (deliver) button_3_down
+ *
+ * synthetic_2_down_13 (button 1 and 3 are down)
+ * ^1 -> (generate ^2) synthetic_2_down_3
+ * v2 -> synthetic_2_down_13
+ * ^2 -> synthetic_2_down_13
+ * ^3 -> (generate ^2) synthetic_2_down_1
+ * <> -> (deliver) synthetic_2_down_13
+ * k -> (deliver) synthetic_2_down_13
+ *
+ * synthetic_2_down_3 (button 3 is down)
+ * v1 -> (deliver) synthetic_2_down_3
+ * ^1 -> (deliver) synthetic_2_down_3
+ * v2 -> synthetic_2_down_3
+ * ^2 -> synthetic_2_down_3
+ * ^3 -> start
+ * <> -> (deliver) synthetic_2_down_3
+ * k -> (deliver) synthetic_2_down_3
+ *
+ * synthetic_2_down_1 (button 1 is down)
+ * ^1 -> start
+ * v2 -> synthetic_2_down_1
+ * ^2 -> synthetic_2_down_1
+ * v3 -> (deliver) synthetic_2_down_1
+ * ^3 -> (deliver) synthetic_2_down_1
+ * <> -> (deliver) synthetic_2_down_1
+ * k -> (deliver) synthetic_2_down_1
+ */
+
+typedef enum _inputState {
+ start,
+ button_1_pend,
+ button_1_down,
+ button_2_down,
+ button_3_pend,
+ button_3_down,
+ synth_2_down_13,
+ synth_2_down_3,
+ synth_2_down_1,
+ num_input_states
+} KdInputState;
+
+typedef enum _inputClass {
+ down_1, up_1,
+ down_2, up_2,
+ down_3, up_3,
+ motion, outside_box,
+ keyboard, timeout,
+ num_input_class
+} KdInputClass;
+
+typedef enum _inputAction {
+ noop,
+ hold,
+ setto,
+ deliver,
+ release,
+ clearto,
+ gen_down_2,
+ gen_up_2
+} KdInputAction;
+
+#define MAX_ACTIONS 2
+
+typedef struct _inputTransition {
+ KdInputAction actions[MAX_ACTIONS];
+ KdInputState nextState;
+} KdInputTransition;
+
+KdInputTransition kdInputMachine[num_input_states][num_input_class] = {
+ /* start */
+ {
+ { { hold, setto }, button_1_pend }, /* v1 */
+ { { deliver, noop }, start }, /* ^1 */
+ { { deliver, noop }, button_2_down }, /* v2 */
+ { { deliver, noop }, start }, /* ^2 */
+ { { hold, setto }, button_3_pend }, /* v3 */
+ { { deliver, noop }, start }, /* ^3 */
+ { { deliver, noop }, start }, /* <> */
+ { { deliver, noop }, start }, /* <-> */
+ { { deliver, noop }, start }, /* k */
+ { { noop, noop }, start }, /* ... */
+ },
+ /* button_1_pend */
+ {
+ { { noop, noop }, button_1_pend }, /* v1 */
+ { { release, deliver }, start }, /* ^1 */
+ { { release, deliver }, button_1_down }, /* v2 */
+ { { release, deliver }, button_1_down }, /* ^2 */
+ { { clearto, gen_down_2 }, synth_2_down_13 }, /* v3 */
+ { { release, deliver }, button_1_down }, /* ^3 */
+ { { deliver, noop }, button_1_pend }, /* <> */
+ { { release, deliver }, button_1_down }, /* <-> */
+ { { release, deliver }, button_1_down }, /* k */
+ { { release, noop }, button_1_down }, /* ... */
+ },
+ /* button_1_down */
+ {
+ { { noop, noop }, button_1_down }, /* v1 */
+ { { deliver, noop }, start }, /* ^1 */
+ { { deliver, noop }, button_1_down }, /* v2 */
+ { { deliver, noop }, button_1_down }, /* ^2 */
+ { { deliver, noop }, button_1_down }, /* v3 */
+ { { deliver, noop }, button_1_down }, /* ^3 */
+ { { deliver, noop }, button_1_down }, /* <> */
+ { { deliver, noop }, button_1_down }, /* <-> */
+ { { deliver, noop }, button_1_down }, /* k */
+ { { noop, noop }, button_1_down }, /* ... */
+ },
+ /* button_2_down */
+ {
+ { { deliver, noop }, button_2_down }, /* v1 */
+ { { deliver, noop }, button_2_down }, /* ^1 */
+ { { noop, noop }, button_2_down }, /* v2 */
+ { { deliver, noop }, start }, /* ^2 */
+ { { deliver, noop }, button_2_down }, /* v3 */
+ { { deliver, noop }, button_2_down }, /* ^3 */
+ { { deliver, noop }, button_2_down }, /* <> */
+ { { deliver, noop }, button_2_down }, /* <-> */
+ { { deliver, noop }, button_2_down }, /* k */
+ { { noop, noop }, button_2_down }, /* ... */
+ },
+ /* button_3_pend */
+ {
+ { { clearto, gen_down_2 }, synth_2_down_13 }, /* v1 */
+ { { release, deliver }, button_3_down }, /* ^1 */
+ { { release, deliver }, button_3_down }, /* v2 */
+ { { release, deliver }, button_3_down }, /* ^2 */
+ { { release, deliver }, button_3_down }, /* v3 */
+ { { release, deliver }, start }, /* ^3 */
+ { { deliver, noop }, button_3_pend }, /* <> */
+ { { release, deliver }, button_3_down }, /* <-> */
+ { { release, deliver }, button_3_down }, /* k */
+ { { release, noop }, button_3_down }, /* ... */
+ },
+ /* button_3_down */
+ {
+ { { deliver, noop }, button_3_down }, /* v1 */
+ { { deliver, noop }, button_3_down }, /* ^1 */
+ { { deliver, noop }, button_3_down }, /* v2 */
+ { { deliver, noop }, button_3_down }, /* ^2 */
+ { { noop, noop }, button_3_down }, /* v3 */
+ { { deliver, noop }, start }, /* ^3 */
+ { { deliver, noop }, button_3_down }, /* <> */
+ { { deliver, noop }, button_3_down }, /* <-> */
+ { { deliver, noop }, button_3_down }, /* k */
+ { { noop, noop }, button_3_down }, /* ... */
+ },
+ /* synthetic_2_down_13 */
+ {
+ { { noop, noop }, synth_2_down_13 }, /* v1 */
+ { { gen_up_2, noop }, synth_2_down_3 }, /* ^1 */
+ { { noop, noop }, synth_2_down_13 }, /* v2 */
+ { { noop, noop }, synth_2_down_13 }, /* ^2 */
+ { { noop, noop }, synth_2_down_13 }, /* v3 */
+ { { gen_up_2, noop }, synth_2_down_1 }, /* ^3 */
+ { { deliver, noop }, synth_2_down_13 }, /* <> */
+ { { deliver, noop }, synth_2_down_13 }, /* <-> */
+ { { deliver, noop }, synth_2_down_13 }, /* k */
+ { { noop, noop }, synth_2_down_13 }, /* ... */
+ },
+ /* synthetic_2_down_3 */
+ {
+ { { deliver, noop }, synth_2_down_3 }, /* v1 */
+ { { deliver, noop }, synth_2_down_3 }, /* ^1 */
+ { { deliver, noop }, synth_2_down_3 }, /* v2 */
+ { { deliver, noop }, synth_2_down_3 }, /* ^2 */
+ { { noop, noop }, synth_2_down_3 }, /* v3 */
+ { { noop, noop }, start }, /* ^3 */
+ { { deliver, noop }, synth_2_down_3 }, /* <> */
+ { { deliver, noop }, synth_2_down_3 }, /* <-> */
+ { { deliver, noop }, synth_2_down_3 }, /* k */
+ { { noop, noop }, synth_2_down_3 }, /* ... */
+ },
+ /* synthetic_2_down_1 */
+ {
+ { { noop, noop }, synth_2_down_1 }, /* v1 */
+ { { noop, noop }, start }, /* ^1 */
+ { { deliver, noop }, synth_2_down_1 }, /* v2 */
+ { { deliver, noop }, synth_2_down_1 }, /* ^2 */
+ { { deliver, noop }, synth_2_down_1 }, /* v3 */
+ { { deliver, noop }, synth_2_down_1 }, /* ^3 */
+ { { deliver, noop }, synth_2_down_1 }, /* <> */
+ { { deliver, noop }, synth_2_down_1 }, /* <-> */
+ { { deliver, noop }, synth_2_down_1 }, /* k */
+ { { noop, noop }, synth_2_down_1 }, /* ... */
+ },
+};
+
+Bool kdEventHeld;
+xEvent kdHeldEvent;
+int kdEmulationDx, kdEmulationDy;
+
+#define EMULATION_WINDOW 10
+#define EMULATION_TIMEOUT 30
+
+#define EventX(e) ((e)->u.keyButtonPointer.rootX)
+#define EventY(e) ((e)->u.keyButtonPointer.rootY)
+
+KdInsideEmulationWindow (xEvent *ev)
+{
+ if (ev->u.keyButtonPointer.pad1)
+ {
+ kdEmulationDx += EventX(ev);
+ kdEmulationDy += EventY(ev);
+ }
+ else
+ {
+ kdEmulationDx = EventX(&kdHeldEvent) - EventX(ev);
+ kdEmulationDy = EventY(&kdHeldEvent) - EventY(ev);
+ }
+ return (abs (kdEmulationDx) < EMULATION_WINDOW &&
+ abs (kdEmulationDy) < EMULATION_WINDOW);
+}
+
+KdInputClass
+KdClassifyInput (xEvent *ev)
+{
+ switch (ev->u.u.type) {
+ case ButtonPress:
+ switch (ev->u.u.detail) {
+ case 1: return down_1;
+ case 2: return down_2;
+ case 3: return down_3;
+ }
+ break;
+ case ButtonRelease:
+ switch (ev->u.u.detail) {
+ case 1: return up_1;
+ case 2: return up_2;
+ case 3: return up_3;
+ }
+ break;
+ case MotionNotify:
+ if (kdEventHeld && !KdInsideEmulationWindow(ev))
+ return outside_box;
+ else
+ return motion;
+ default:
+ return keyboard;
+ }
+}
+
+#ifndef NDEBUG
+char *kdStateNames[] = {
+ "start",
+ "button_1_pend",
+ "button_1_down",
+ "button_2_down",
+ "button_3_pend",
+ "button_3_down",
+ "synth_2_down_13",
+ "synth_2_down_3",
+ "synthetic_2_down_1",
+ "num_input_states"
+};
+
+char *kdClassNames[] = {
+ "down_1", "up_1",
+ "down_2", "up_2",
+ "down_3", "up_3",
+ "motion", "ouside_box",
+ "keyboard", "timeout",
+ "num_input_class"
+};
+
+char *kdActionNames[] = {
+ "noop",
+ "hold",
+ "setto",
+ "deliver",
+ "release",
+ "clearto",
+ "gen_down_2",
+ "gen_up_2",
+};
+#endif
+
+static void
+KdQueueEvent (xEvent *ev)
+{
+ KdAssertSigioBlocked ("KdQueueEvent");
+ if (ev->u.u.type == MotionNotify)
+ {
+ if (ev->u.keyButtonPointer.pad1)
+ {
+ ev->u.keyButtonPointer.pad1 = 0;
+ miPointerDeltaCursor (ev->u.keyButtonPointer.rootX,
+ ev->u.keyButtonPointer.rootY,
+ ev->u.keyButtonPointer.time);
+ }
+ else
+ {
+ miPointerAbsoluteCursor(ev->u.keyButtonPointer.rootX,
+ ev->u.keyButtonPointer.rootY,
+ ev->u.keyButtonPointer.time);
+ }
+ }
+ else
+ {
+ mieqEnqueue (ev);
+ }
+}
+
+KdInputState kdInputState;
+
+static void
+KdRunInputMachine (KdInputClass c, xEvent *ev)
+{
+ KdInputTransition *t;
+ int a;
+
+ t = &kdInputMachine[kdInputState][c];
+ for (a = 0; a < MAX_ACTIONS; a++)
+ {
+ switch (t->actions[a]) {
+ case noop:
+ break;
+ case hold:
+ kdEventHeld = TRUE;
+ kdEmulationDx = 0;
+ kdEmulationDy = 0;
+ kdHeldEvent = *ev;
+ break;
+ case setto:
+ kdEmulationTimeout = GetTimeInMillis () + EMULATION_TIMEOUT;
+ kdTimeoutPending = TRUE;
+ break;
+ case deliver:
+ KdQueueEvent (ev);
+ break;
+ case release:
+ kdEventHeld = FALSE;
+ kdTimeoutPending = FALSE;
+ KdQueueEvent (&kdHeldEvent);
+ break;
+ case clearto:
+ kdTimeoutPending = FALSE;
+ break;
+ case gen_down_2:
+ ev->u.u.detail = 2;
+ kdEventHeld = FALSE;
+ KdQueueEvent (ev);
+ break;
+ case gen_up_2:
+ ev->u.u.detail = 2;
+ KdQueueEvent (ev);
+ break;
+ }
+ }
+ kdInputState = t->nextState;
+}
+
+void
+KdResetInputMachine (void)
+{
+ kdInputState = start;
+ kdEventHeld = FALSE;
+}
+
+void
+KdHandleEvent (xEvent *ev)
+{
+ if (kdEmulateMiddleButton)
+ KdRunInputMachine (KdClassifyInput (ev), ev);
+ else
+ KdQueueEvent (ev);
+}
+
+void
+KdReceiveTimeout (void)
+{
+ KdRunInputMachine (timeout, 0);
+}
+
+#define KILL_SEQUENCE ((1L << KK_CONTROL)|(1L << KK_ALT)|(1L << KK_F8)|(1L << KK_F10))
+#define SPECIAL_SEQUENCE ((1L << KK_CONTROL) | (1L << KK_ALT))
+#define SETKILLKEY(b) (KdSpecialKeys |= (1L << (b)))
+#define CLEARKILLKEY(b) (KdSpecialKeys &= ~(1L << (b)))
+#define KEYMAP (pKdKeyboard->key->curKeySyms)
+#define KEYCOL1(k) (KEYMAP.map[((k)-kdMinKeyCode)*KEYMAP.mapWidth])
+
+CARD32 KdSpecialKeys = 0;
+
+extern char dispatchException;
+
+/*
+ * kdCheckTermination
+ *
+ * This function checks for the key sequence that terminates the server. When
+ * detected, it sets the dispatchException flag and returns. The key sequence
+ * is:
+ * Control-Alt
+ * It's assumed that the server will be waken up by the caller when this
+ * function returns.
+ */
+
+extern int nClients;
+
+void
+KdCheckSpecialKeys(xEvent *xE)
+{
+ KeySym sym;
+
+ if (!pKdKeyboard) return;
+
+ /*
+ * Ignore key releases
+ */
+
+ if (xE->u.u.type == KeyRelease) return;
+
+ /*
+ * Check for control/alt pressed
+ */
+ if ((pKdKeyboard->key->state & (ControlMask|Mod1Mask)) !=
+ (ControlMask|Mod1Mask))
+ return;
+
+ sym = KEYCOL1(xE->u.u.detail);
+
+ /*
+ * Let OS function see keysym first
+ */
+
+ if (kdOsFuncs->SpecialKey)
+ if ((*kdOsFuncs->SpecialKey) (sym))
+ return;
+
+ /*
+ * Now check for backspace or delete; these signal the
+ * X server to terminate
+ */
+ switch (sym) {
+ case XK_BackSpace:
+ case XK_Delete:
+ case XK_KP_Delete:
+ /*
+ * Set the dispatch exception flag so the server will terminate the
+ * next time through the dispatch loop.
+ */
+ dispatchException |= DE_TERMINATE;
+ break;
+ }
+}
+
+/*
+ * kdEnqueueKeyboardEvent
+ *
+ * This function converts hardware keyboard event information into an X event
+ * and enqueues it using MI. It wakes up the server before returning so that
+ * the event will be processed normally.
+ *
+ */
+
+void
+KdHandleKeyboardEvent (xEvent *ev)
+{
+ int key = ev->u.u.detail;
+ int byte;
+ CARD8 bit;
+
+ byte = key >> 3;
+ bit = 1 << (key & 7);
+ switch (ev->u.u.type) {
+ case KeyPress:
+ kdKeyState[byte] |= bit;
+ break;
+ case KeyRelease:
+ kdKeyState[byte] &= ~bit;
+ break;
+ }
+ KdHandleEvent (ev);
+}
+
+void
+KdReleaseAllKeys (void)
+{
+ xEvent xE;
+ int key;
+
+ for (key = 0; key < KD_KEY_COUNT; key++)
+ if (IsKeyDown(key))
+ {
+ xE.u.keyButtonPointer.time = GetTimeInMillis();
+ xE.u.u.type = KeyRelease;
+ xE.u.u.detail = key;
+ KdHandleKeyboardEvent (&xE);
+ }
+}
+
+void
+KdCheckLock (void)
+{
+ KeyClassPtr keyc = pKdKeyboard->key;
+ Bool isSet, shouldBeSet;
+
+ if (kdKeyboardFuncs->LockLed)
+ {
+ isSet = (kdLeds & (1 << (kdKeyboardFuncs->LockLed-1))) != 0;
+ shouldBeSet = (keyc->state & LockMask) != 0;
+ if (isSet != shouldBeSet)
+ {
+ KdSetLed (kdKeyboardFuncs->LockLed, shouldBeSet);
+ }
+ }
+}
+
+void
+KdEnqueueKeyboardEvent(unsigned char scan_code,
+ unsigned char is_up)
+{
+ unsigned char key_code;
+ xEvent xE;
+ int e;
+ KeyClassPtr keyc;
+
+ if (!pKdKeyboard)
+ return;
+ keyc = pKdKeyboard->key;
+
+ xE.u.keyButtonPointer.time = GetTimeInMillis();
+
+ if (kdMinScanCode <= scan_code && scan_code <= kdMaxScanCode)
+ {
+ key_code = scan_code + KD_MIN_KEYCODE - kdMinScanCode;
+
+ /*
+ * Set up this event -- the type may be modified below
+ */
+ if (is_up)
+ xE.u.u.type = KeyRelease;
+ else
+ xE.u.u.type = KeyPress;
+ xE.u.u.detail = key_code;
+
+ switch (KEYCOL1(key_code))
+ {
+ case XK_Num_Lock:
+ case XK_Scroll_Lock:
+ case XK_Shift_Lock:
+ case XK_Caps_Lock:
+ if (xE.u.u.type == KeyRelease)
+ return;
+ if (IsKeyDown (key_code))
+ xE.u.u.type = KeyRelease;
+ else
+ xE.u.u.type = KeyPress;
+ }
+
+ /*
+ * Check pressed keys which are already down
+ */
+ if (IsKeyDown (key_code) && xE.u.u.type == KeyPress)
+ {
+ KeybdCtrl *ctrl = &pKdKeyboard->kbdfeed->ctrl;
+
+ /*
+ * Check auto repeat
+ */
+ if (!ctrl->autoRepeat || keyc->modifierMap[key_code] ||
+ !(ctrl->autoRepeats[key_code >> 3] & (1 << (key_code & 7))))
+ {
+ return;
+ }
+ }
+ if (xE.u.u.type == KeyRelease && !IsKeyDown (key_code))
+ {
+ xE.u.u.type = KeyPress;
+ KdHandleKeyboardEvent (&xE);
+ xE.u.u.type = KeyRelease;
+ }
+ KdCheckSpecialKeys (&xE);
+ KdHandleKeyboardEvent (&xE);
+ }
+}
+
+#define SetButton(b,v, s) \
+{\
+ xE.u.u.detail = b; \
+ xE.u.u.type = v; \
+ KdHandleEvent (&xE); \
+}
+
+#define Press(b) SetButton(b+1,ButtonPress,"Down")
+#define Release(b) SetButton(b+1,ButtonRelease,"Up")
+
+unsigned char ButtonState = 0;
+
+/*
+ * kdEnqueueMouseEvent
+ *
+ * This function converts hardware mouse event information into X event
+ * information. A mouse movement event is passed off to MI to generate
+ * a MotionNotify event, if appropriate. Button events are created and
+ * passed off to MI for enqueueing.
+ */
+
+static int
+KdMouseAccelerate (DeviceIntPtr device, int delta)
+{
+ PtrCtrl *pCtrl = &device->ptrfeed->ctrl;
+
+ if (abs(delta) > pCtrl->threshold)
+ delta = (delta * pCtrl->num) / pCtrl->den;
+ return delta;
+}
+
+void
+KdEnqueueMouseEvent(unsigned long flags, int x, int y)
+{
+ CARD32 ms;
+ xEvent xE;
+ unsigned char buttons;
+
+ if (!pKdPointer)
+ return;
+
+ ms = GetTimeInMillis();
+
+ if (flags & KD_MOUSE_DELTA)
+ {
+ x = KdMouseAccelerate (pKdPointer, x);
+ y = KdMouseAccelerate (pKdPointer, y);
+ xE.u.keyButtonPointer.pad1 = 1;
+ }
+ else
+ xE.u.keyButtonPointer.pad1 = 0;
+ xE.u.keyButtonPointer.time = ms;
+ xE.u.keyButtonPointer.rootX = x;
+ xE.u.keyButtonPointer.rootY = y;
+
+ xE.u.u.type = MotionNotify;
+ xE.u.u.detail = 0;
+ KdHandleEvent (&xE);
+
+ buttons = flags;
+
+ if ((ButtonState & KD_BUTTON_1) ^ (buttons & KD_BUTTON_1))
+ {
+ if (buttons & KD_BUTTON_1)
+ {
+ Press(0);
+ }
+ else
+ {
+ Release(0);
+ }
+ }
+ if ((ButtonState & KD_BUTTON_2) ^ (buttons & KD_BUTTON_2))
+ {
+ if (buttons & KD_BUTTON_2)
+ {
+ Press(1);
+ }
+ else
+ {
+ Release(1);
+ }
+ }
+ if ((ButtonState & KD_BUTTON_3) ^ (buttons & KD_BUTTON_3))
+ {
+ if (buttons & KD_BUTTON_3)
+ {
+ Press(2);
+ }
+ else
+ {
+ Release(2);
+ }
+ }
+ ButtonState = buttons;
+}
+
+void
+KdEnqueueMotionEvent (int x, int y)
+{
+ xEvent xE;
+ CARD32 ms;
+
+ ms = GetTimeInMillis();
+
+ xE.u.u.type = MotionNotify;
+ xE.u.keyButtonPointer.time = ms;
+ xE.u.keyButtonPointer.rootX = x;
+ xE.u.keyButtonPointer.rootY = y;
+
+ KdHandleEvent (&xE);
+}
+
+void
+KdBlockHandler (int screen,
+ pointer blockData,
+ pointer timeout,
+ pointer readmask)
+{
+ struct timeval **pTimeout = timeout;
+
+ if (kdTimeoutPending)
+ {
+ static struct timeval tv;
+ int ms;
+
+ ms = kdEmulationTimeout - GetTimeInMillis ();
+ if (ms < 0)
+ ms = 0;
+ tv.tv_sec = ms / 1000;
+ tv.tv_usec = (ms % 1000) * 1000;
+ if (*pTimeout)
+ {
+ if ((*pTimeout)->tv_sec > tv.tv_sec ||
+ ((*pTimeout)->tv_sec == tv.tv_sec &&
+ (*pTimeout)->tv_usec > tv.tv_usec))
+ {
+ *pTimeout = &tv;
+ }
+ }
+ else
+ *pTimeout = &tv;
+ }
+}
+
+void
+KdWakeupHandler (int screen,
+ pointer data,
+ unsigned long result,
+ pointer readmask)
+{
+ fd_set *pReadmask = (fd_set *) readmask;
+
+ if (kdMouseFd >= 0 && FD_ISSET (kdMouseFd, pReadmask))
+ {
+ KdBlockSigio ();
+ (*kdMouseFuncs->Read) (kdMouseFd);
+ KdUnblockSigio ();
+ }
+ if (kdKeyboardFd >= 0 && FD_ISSET (kdKeyboardFd, pReadmask))
+ {
+ KdBlockSigio ();
+ (*kdKeyboardFuncs->Read) (kdKeyboardFd);
+ KdUnblockSigio ();
+ }
+ if (kdTimeoutPending)
+ {
+ if ((long) (GetTimeInMillis () - kdEmulationTimeout) >= 0)
+ {
+ kdTimeoutPending = FALSE;
+ KdBlockSigio ();
+ KdReceiveTimeout ();
+ KdUnblockSigio ();
+ }
+ }
+ if (kdSwitchPending)
+ KdProcessSwitch ();
+}
+
+static Bool
+KdCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y)
+{
+ ScreenPtr pScreen = *ppScreen;
+ int n;
+
+ if (kdDisableZaphod || screenInfo.numScreens <= 1)
+ return FALSE;
+ if (*x < 0)
+ {
+ n = pScreen->myNum - 1;
+ if (n < 0)
+ n = screenInfo.numScreens - 1;
+ pScreen = screenInfo.screens[n];
+ *x += pScreen->width;
+ *ppScreen = pScreen;
+ return TRUE;
+ }
+ else if (*x >= pScreen->width)
+ {
+ n = pScreen->myNum + 1;
+ if (n >= screenInfo.numScreens)
+ n = 0;
+ *x -= pScreen->width;
+ pScreen = screenInfo.screens[n];
+ *ppScreen = pScreen;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+KdCrossScreen(ScreenPtr pScreen, Bool entering)
+{
+ if (entering)
+ KdEnableScreen (pScreen);
+ else
+ KdDisableScreen (pScreen);
+}
+
+static void
+KdWarpCursor (ScreenPtr pScreen, int x, int y)
+{
+ KdBlockSigio ();
+ miPointerWarpCursor (pScreen, x, y);
+ KdUnblockSigio ();
+}
+
+miPointerScreenFuncRec kdPointerScreenFuncs =
+{
+ KdCursorOffScreen,
+ KdCrossScreen,
+ KdWarpCursor
+};
+
+void
+ProcessInputEvents ()
+{
+ (void)mieqProcessInputEvents();
+ miPointerUpdate();
+ if (kdSwitchPending)
+ KdProcessSwitch ();
+ KdCheckLock ();
+}
+
diff --git a/hw/kdrive/src/kkeymap.c b/hw/kdrive/src/kkeymap.c
new file mode 100644
index 000000000..2ec89b96d
--- /dev/null
+++ b/hw/kdrive/src/kkeymap.c
@@ -0,0 +1,235 @@
+/*
+ * $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 "kdrive.h"
+#include <X11/keysym.h>
+#include "kkeymap.h"
+
+/*
+ * Map scan codes (both regular and synthesized from extended keys)
+ * to X keysyms
+ */
+
+KeySym kdKeymap[(MAX_SCANCODE - MIN_SCANCODE + 1) * MAX_WIDTH] = {
+/* These are directly mapped from DOS scanset 0 */
+/* 1 8 */ XK_Escape, NoSymbol,
+/* 2 9 */ XK_1, XK_exclam,
+/* 3 10 */ XK_2, XK_at,
+/* 4 11 */ XK_3, XK_numbersign,
+/* 5 12 */ XK_4, XK_dollar,
+/* 6 13 */ XK_5, XK_percent,
+/* 7 14 */ XK_6, XK_asciicircum,
+/* 8 15 */ XK_7, XK_ampersand,
+/* 9 16 */ XK_8, XK_asterisk,
+/* 10 17 */ XK_9, XK_parenleft,
+/* 11 18 */ XK_0, XK_parenright,
+/* 12 19 */ XK_minus, XK_underscore,
+/* 13 20 */ XK_equal, XK_plus,
+/* 14 21 */ XK_BackSpace, NoSymbol,
+/* 15 22 */ XK_Tab, NoSymbol,
+/* 16 23 */ XK_Q, NoSymbol,
+/* 17 24 */ XK_W, NoSymbol,
+/* 18 25 */ XK_E, NoSymbol,
+/* 19 26 */ XK_R, NoSymbol,
+/* 20 27 */ XK_T, NoSymbol,
+/* 21 28 */ XK_Y, NoSymbol,
+/* 22 29 */ XK_U, NoSymbol,
+/* 23 30 */ XK_I, NoSymbol,
+/* 24 31 */ XK_O, NoSymbol,
+/* 25 32 */ XK_P, NoSymbol,
+/* 26 33 */ XK_bracketleft, XK_braceleft,
+/* 27 34 */ XK_bracketright, XK_braceright,
+/* 28 35 */ XK_Return, NoSymbol,
+/* 29 36 */ XK_Control_L, NoSymbol,
+/* 30 37 */ XK_A, NoSymbol,
+/* 31 38 */ XK_S, NoSymbol,
+/* 32 39 */ XK_D, NoSymbol,
+/* 33 40 */ XK_F, NoSymbol,
+/* 34 41 */ XK_G, NoSymbol,
+/* 35 42 */ XK_H, NoSymbol,
+/* 36 43 */ XK_J, NoSymbol,
+/* 37 44 */ XK_K, NoSymbol,
+/* 38 45 */ XK_L, NoSymbol,
+/* 39 46 */ XK_semicolon, XK_colon,
+/* 40 47 */ XK_apostrophe, XK_quotedbl,
+/* 41 48 */ XK_grave, XK_asciitilde,
+/* 42 49 */ XK_Shift_L, NoSymbol,
+/* 43 50 */ XK_backslash, XK_bar,
+/* 44 51 */ XK_Z, NoSymbol,
+/* 45 52 */ XK_X, NoSymbol,
+/* 46 53 */ XK_C, NoSymbol,
+/* 47 54 */ XK_V, NoSymbol,
+/* 48 55 */ XK_B, NoSymbol,
+/* 49 56 */ XK_N, NoSymbol,
+/* 50 57 */ XK_M, NoSymbol,
+/* 51 58 */ XK_comma, XK_less,
+/* 52 59 */ XK_period, XK_greater,
+/* 53 60 */ XK_slash, XK_question,
+/* 54 61 */ XK_Shift_R, NoSymbol,
+/* 55 62 */ XK_KP_Multiply, NoSymbol,
+/* 56 63 */ XK_Alt_L, XK_Meta_L,
+/* 57 64 */ XK_space, NoSymbol,
+/* 58 65 */ XK_Caps_Lock, NoSymbol,
+/* 59 66 */ XK_F1, NoSymbol,
+/* 60 67 */ XK_F2, NoSymbol,
+/* 61 68 */ XK_F3, NoSymbol,
+/* 62 69 */ XK_F4, NoSymbol,
+/* 63 70 */ XK_F5, NoSymbol,
+/* 64 71 */ XK_F6, NoSymbol,
+/* 65 72 */ XK_F7, NoSymbol,
+/* 66 73 */ XK_F8, NoSymbol,
+/* 67 74 */ XK_F9, NoSymbol,
+/* 68 75 */ XK_F10, NoSymbol,
+/* 69 76 */ XK_Break, XK_Pause,
+/* 70 77 */ XK_Scroll_Lock, NoSymbol,
+/* 71 78 */ XK_KP_Home, XK_KP_7,
+/* 72 79 */ XK_KP_Up, XK_KP_8,
+/* 73 80 */ XK_KP_Page_Up, XK_KP_9,
+/* 74 81 */ XK_KP_Subtract, NoSymbol,
+/* 75 82 */ XK_KP_Left, XK_KP_4,
+/* 76 83 */ XK_KP_5, NoSymbol,
+/* 77 84 */ XK_KP_Right, XK_KP_6,
+/* 78 85 */ XK_KP_Add, NoSymbol,
+/* 79 86 */ XK_KP_End, XK_KP_1,
+/* 80 87 */ XK_KP_Down, XK_KP_2,
+/* 81 88 */ XK_KP_Page_Down, XK_KP_3,
+/* 82 89 */ XK_KP_Insert, XK_KP_0,
+/* 83 90 */ XK_KP_Delete, XK_KP_Decimal,
+/* 84 91 */ NoSymbol, NoSymbol,
+/* 85 92 */ NoSymbol, NoSymbol,
+/* 86 93 */ NoSymbol, NoSymbol,
+/* 87 94 */ XK_F11, NoSymbol,
+/* 88 95 */ XK_F12, NoSymbol,
+
+/* These are remapped from the extended set (using ExtendMap) */
+
+/* 89 96 */ XK_Control_R, NoSymbol,
+/* 90 97 */ XK_KP_Enter, NoSymbol,
+/* 91 98 */ XK_KP_Divide, NoSymbol,
+/* 92 99 */ XK_Sys_Req, XK_Print,
+/* 93 100 */ XK_Alt_R, XK_Meta_R,
+/* 94 101 */ XK_Num_Lock, NoSymbol,
+/* 95 102 */ XK_Home, NoSymbol,
+/* 96 103 */ XK_Up, NoSymbol,
+/* 97 104 */ XK_Page_Up, NoSymbol,
+/* 98 105 */ XK_Left, NoSymbol,
+/* 99 106 */ XK_Right, NoSymbol,
+/* 100 107 */ XK_End, NoSymbol,
+/* 101 108 */ XK_Down, NoSymbol,
+/* 102 109 */ XK_Page_Down, NoSymbol,
+/* 103 110 */ XK_Insert, NoSymbol,
+/* 104 111 */ XK_Delete, NoSymbol,
+/* 105 112 */ XK_Super_L, NoSymbol,
+/* 106 113 */ XK_Super_R, NoSymbol,
+/* 107 114 */ XK_Menu, NoSymbol,
+/* 108 115 */ NoSymbol, NoSymbol,
+/* 109 116 */ NoSymbol, NoSymbol,
+/* 110 117 */ NoSymbol, NoSymbol,
+/* 111 118 */ NoSymbol, NoSymbol,
+/* 112 119 */ NoSymbol, NoSymbol,
+;
+
+/*
+ * Map extended keys to additional scancodes
+ */
+KdExtendMap kdExtendMap[] = {
+ 0x1d, 89, /* Control_R */
+ 0x1c, 90, /* KP_Enter */
+ 0x35, 91, /* KP_Divide */
+ 0x37, 92, /* Sys_Req */
+ 0x38, 93, /* Alt_R */
+ 0x45, 94, /* Num_Lock */
+ 0x47, 95, /* Home */
+ 0x48, 96, /* Up */
+ 0x49, 97, /* Page_Up */
+ 0x4b, 98, /* Left */
+ 0x4d, 99, /* Right */
+ 0x4f, 100, /* End */
+ 0x50, 101, /* Down */
+ 0x51, 102, /* Page_Down */
+ 0x52, 103, /* Insert */
+ 0x53, 104, /* Delete */
+ 0x5b, 105, /* Super_L (Windows_L) */
+ 0x5c, 106, /* Super_R (Windows_R) */
+ 0x5d, 107, /* Menu */
+ 0x46, 69, /* Break (with control pressed) */
+};
+
+#define NUM_EXTEND (sizeof (kdExtendMap)/ sizeof (kdExtendMap[0]))
+
+int kdNumExtend = NUM_EXTEND;
+
+/*
+ * Map keys on Japanese keyboard far from zero back to reasonable values
+ */
+KdExtendMap kdJapanMap[] = {
+ 0x70, 108, /* next to Alt key */
+ 0x73, 109, /* dash/vbar */
+ 0x79, 110, /* right of space bar */
+ 0x7b, 111, /* left of space bar */
+ 0x7d, 112, /* Yen */
+};
+
+#define NUM_JAPAN (sizeof (kdJapanMap)/sizeof (kdJapanMap[0]))
+
+int kdNumJapan = NUM_JAPAN;
+
+/*
+ * List of locking key codes
+ */
+
+CARD8 kdLockMap[] = {
+ 65,
+ 101,
+ 77,
+};
+
+#define NUM_LOCK (sizeof (kdLockMap) / sizeof (kdLockMap[0]))
+
+int kdNumLock = NUM_LOCK;
+
+/*
+ * Map containing list of keys which the X server makes locking when
+ * the KEYMAP_LOCKING_ALTGR flag is set in CEKeymapFlags
+ */
+
+CARD8 kdOptionalLockMap[] = {
+ 100,
+};
+
+#define NUM_OPTIONAL_LOCK (sizeof (kdOptionalLockMap) / sizeof (kdOptionalLockMap[0]))
+
+int kdNumOptionalLock = NUM_OPTIONAL_LOCK;
+
+CARD8 kdModMap[MAP_LENGTH];
+
+unsigned long kdKeymapFlags = 0;
+
+KeySymsRec kdKeySyms = {
+ kdKeymap,
+ MIN_KEYCODE,
+ MAX_KEYCODE,
+ 2
+};
diff --git a/hw/kdrive/src/kkeymap.h b/hw/kdrive/src/kkeymap.h
new file mode 100644
index 000000000..d97d7370e
--- /dev/null
+++ b/hw/kdrive/src/kkeymap.h
@@ -0,0 +1,53 @@
+/*
+ * $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: $ */
+/*
+ * All global variables and functions pertaining to keyboard key mapping
+ * live in this header file.
+ */
+
+#ifndef _KDKEYMP_H
+#define _KDKEYMP_H
+
+/* Offset of MIN_SCANCODE to 8 (X minimum scancode value) */
+#define KD_KEY_OFFSET (8 - kdMinScanCode)
+
+#define KD_MIN_KEYCODE 8
+#define KD_MAX_KEYCODE 254
+#define KD_MAX_WIDTH 4
+#define KD_MAX_LENGTH (KD_MAX_KEYCODE - KD_MIN_KEYCODE + 1)
+
+extern int kdMinScanCode;
+extern int kdMaxScanCode;
+extern int kdMinKeyCode;
+extern int kdMaxKeyCode;
+extern int kdKeymapWidth;
+
+extern KeySym kdKeymap[KD_MAX_LENGTH * KD_MAX_WIDTH];
+
+extern CARD8 kdModMap[MAP_LENGTH];
+
+extern KeySymsRec kdKeySyms;
+
+#endif /* _WINKEYMP_H */
diff --git a/hw/kdrive/src/kloadmap.c b/hw/kdrive/src/kloadmap.c
new file mode 100644
index 000000000..bd8e31cbd
--- /dev/null
+++ b/hw/kdrive/src/kloadmap.c
@@ -0,0 +1,200 @@
+/*
+ * $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 "kdrive.h"
+#include "kkeymap.h"
+
+#ifdef WINDOWS
+#define KM_BUF 1024
+#define KM_EOF -1
+
+typedef struct _km_file {
+ HANDLE handle;
+ char buf[KM_BUF];
+ char *bufptr;
+ DWORD remain;
+} km_file;
+
+int
+km_fill (km_file *kf)
+{
+ BOOL r;
+
+ NCD_DEBUG ((DEBUG_INIT, "km_fill"));
+ r = ReadFile (kf->handle, kf->buf, KM_BUF,
+ &kf->remain, NULL);
+ NCD_DEBUG ((DEBUG_INIT, "Got %d", kf->remain));
+ if (!r || !kf->remain)
+ return KM_EOF;
+ kf->bufptr = kf->buf;
+ --kf->remain;
+ return *kf->bufptr++;
+}
+
+#define km_getchar(kf) ((kf)->remain-- ? *kf->bufptr++ : km_fill (kf))
+#else
+#define km_getchar(kf) getc(kf)
+#endif
+
+BOOL
+km_word (km_file *kf, char *buf, int len)
+{
+ int c;
+
+ for (;;)
+ {
+ switch (c = km_getchar (kf)) {
+ case KM_EOF:
+ return FALSE;
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ continue;
+ }
+ break;
+ }
+ len--;
+ while (len--)
+ {
+ *buf++ = c;
+ switch (c = km_getchar (kf)) {
+ case KM_EOF:
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ *buf++ = '\0';
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+BOOL
+km_int (km_file *kf, int *r)
+{
+ char word[64];
+
+ if (km_word (kf, word, sizeof (word)))
+ {
+ *r = strtol (word, NULL, 0);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+WCHAR *winKbdExtensions[] = {
+ L".xku",
+ L".xkb"
+};
+
+#define NUM_KBD_EXTENSIONS (sizeof (winKbdExtensions) / sizeof (winKbdExtensions[0]))
+
+BOOL
+winLoadKeymap (void)
+{
+ WCHAR file[32 + KL_NAMELENGTH];
+ WCHAR name[KL_NAMELENGTH];
+ HKL layout;
+ km_file kf;
+ int width;
+ BOOL ret;
+ KeySym *m;
+ int scancode;
+ int w;
+ int e;
+
+ layout = GetKeyboardLayout (0);
+ /*
+ * Pre-build 46 versions of ThinSTAR software return 0
+ * for all layouts
+ */
+ if (!layout)
+ return FALSE;
+ NCD_DEBUG ((DEBUG_INIT, "Keyboard layout 0x%x", layout));
+ for (e = 0; e < NUM_KBD_EXTENSIONS; e++)
+ {
+ wstrcpy (file, L"\\Storage Card\\");
+ wsprintf (name, TEXT("%08x"), layout);
+ wstrcat (file, name);
+ wstrcat (file, winKbdExtensions[e]);
+ NCD_DEBUG ((DEBUG_INIT, "Loading keymap from %S", file));
+ kf.handle = CreateFile (file,
+ GENERIC_READ,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (kf.handle != INVALID_HANDLE_VALUE)
+ break;
+ }
+ if (kf.handle == INVALID_HANDLE_VALUE)
+ {
+ NCD_DEBUG ((DEBUG_INIT, "No such file"));
+ return FALSE;
+ }
+ ret = FALSE;
+ kf.remain = 0;
+ /*
+ * Keymap format:
+ *
+ * flags (optional)
+ * width
+ * keycode -> keysym array (num_keycodes * width)
+ */
+ if (!km_int (&kf, &width))
+ goto bail1;
+ if (width & KEYMAP_FLAGS)
+ {
+ CEKeymapFlags = (unsigned long) width;
+ if (!km_int (&kf, &width))
+ goto bail1;
+ }
+ else
+ CEKeymapFlags = 0;
+ if (width > MAX_WIDTH)
+ goto bail1;
+ NCD_DEBUG ((DEBUG_INIT, "Keymap width %d flags 0x%x",
+ width, CEKeymapFlags));
+ m = CEKeymap;
+ for (scancode = MIN_SCANCODE; scancode <= MAX_SCANCODE; scancode++)
+ {
+ for (w = 0; w < width; w++)
+ {
+ if (!km_int (&kf, m))
+ break;
+ m++;
+ }
+ if (w != width)
+ break;
+ }
+ CEKeySyms.mapWidth = width;
+ ret = TRUE;
+bail1:
+ CloseHandle (kf.handle);
+ return ret;
+}
diff --git a/hw/kdrive/src/kmap.c b/hw/kdrive/src/kmap.c
new file mode 100644
index 000000000..fdd0f36d6
--- /dev/null
+++ b/hw/kdrive/src/kmap.c
@@ -0,0 +1,86 @@
+/*
+ * $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 "kdrive.h"
+
+#ifdef linux
+#include <errno.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#endif
+
+void *
+KdMapDevice (CARD32 addr, CARD32 size)
+{
+#ifdef WINDOWS
+ void *a;
+ void *d;
+
+ d = VirtualAlloc (NULL, size, MEM_RESERVE, PAGE_NOACCESS);
+ if (!d)
+ return NULL;
+ DRAW_DEBUG ((DEBUG_S3INIT, "Virtual address of 0x%x is 0x%x", addr, d));
+ a = VirtualCopyAddr (addr);
+ DRAW_DEBUG ((DEBUG_S3INIT, "Translated address is 0x%x", a));
+ if (!VirtualCopy (d, a, size,
+ PAGE_READWRITE|PAGE_NOCACHE|PAGE_PHYSICAL))
+ {
+ DRAW_DEBUG ((DEBUG_FAILURE, "VirtualCopy failed %d",
+ GetLastError ()));
+ return NULL;
+ }
+ DRAW_DEBUG ((DEBUG_S3INIT, "Device mapped successfully"));
+ return d;
+#endif
+#ifdef linux
+ void *a;
+ int fd;
+
+ fd = open ("/dev/mem", O_RDWR);
+ if (fd < 0)
+ FatalError ("KdMapDevice: failed to open /dev/mem (%s)\n",
+ strerror (errno));
+
+ a = mmap ((caddr_t) 0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, addr);
+ close (fd);
+ if ((long) a == -1)
+ FatalError ("KdMapDevice: failed to map frame buffer (%s)\n",
+ strerror (errno));
+ return a;
+#endif
+}
+
+void
+KdUnmapDevice (void *addr, CARD32 size)
+{
+#ifdef WINDOWS
+ VirtualFree (addr, size, MEM_DECOMMIT);
+ VirtualFree (addr, 0, MEM_RELEASE);
+#endif
+#ifdef linux
+ munmap (addr, size);
+#endif
+}
+
diff --git a/hw/kdrive/src/knoop.c b/hw/kdrive/src/knoop.c
new file mode 100644
index 000000000..483047f22
--- /dev/null
+++ b/hw/kdrive/src/knoop.c
@@ -0,0 +1,294 @@
+/*
+ * $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: $ */
+
+/*
+ * GC ops that don't do anything
+ */
+
+#include "kdrive.h"
+#include <gcstruct.h>
+
+typedef void (* typeFillSpans)(
+#if NeedNestedPrototypes
+ DrawablePtr /*pDrawable*/,
+ GCPtr /*pGC*/,
+ int /*nInit*/,
+ DDXPointPtr /*pptInit*/,
+ int * /*pwidthInit*/,
+ int /*fSorted*/
+#endif
+);
+
+typedef void (* typeSetSpans)(
+#if NeedNestedPrototypes
+ DrawablePtr /*pDrawable*/,
+ GCPtr /*pGC*/,
+ char * /*psrc*/,
+ DDXPointPtr /*ppt*/,
+ int * /*pwidth*/,
+ int /*nspans*/,
+ int /*fSorted*/
+#endif
+);
+
+typedef void (* typePutImage)(
+#if NeedNestedPrototypes
+ DrawablePtr /*pDrawable*/,
+ GCPtr /*pGC*/,
+ int /*depth*/,
+ int /*x*/,
+ int /*y*/,
+ int /*w*/,
+ int /*h*/,
+ int /*leftPad*/,
+ int /*format*/,
+ char * /*pBits*/
+#endif
+);
+
+typedef RegionPtr (* typeCopyArea)(
+#if NeedNestedPrototypes
+ DrawablePtr /*pSrc*/,
+ DrawablePtr /*pDst*/,
+ GCPtr /*pGC*/,
+ int /*srcx*/,
+ int /*srcy*/,
+ int /*w*/,
+ int /*h*/,
+ int /*dstx*/,
+ int /*dsty*/
+#endif
+);
+
+typedef RegionPtr (* typeCopyPlane)(
+#if NeedNestedPrototypes
+ DrawablePtr /*pSrcDrawable*/,
+ DrawablePtr /*pDstDrawable*/,
+ GCPtr /*pGC*/,
+ int /*srcx*/,
+ int /*srcy*/,
+ int /*width*/,
+ int /*height*/,
+ int /*dstx*/,
+ int /*dsty*/,
+ unsigned long /*bitPlane*/
+#endif
+);
+typedef void (* typePolyPoint)(
+#if NeedNestedPrototypes
+ DrawablePtr /*pDrawable*/,
+ GCPtr /*pGC*/,
+ int /*mode*/,
+ int /*npt*/,
+ DDXPointPtr /*pptInit*/
+#endif
+);
+
+typedef void (* typePolylines)(
+#if NeedNestedPrototypes
+ DrawablePtr /*pDrawable*/,
+ GCPtr /*pGC*/,
+ int /*mode*/,
+ int /*npt*/,
+ DDXPointPtr /*pptInit*/
+#endif
+);
+
+typedef void (* typePolySegment)(
+#if NeedNestedPrototypes
+ DrawablePtr /*pDrawable*/,
+ GCPtr /*pGC*/,
+ int /*nseg*/,
+ xSegment * /*pSegs*/
+#endif
+);
+
+typedef void (* typePolyRectangle)(
+#if NeedNestedPrototypes
+ DrawablePtr /*pDrawable*/,
+ GCPtr /*pGC*/,
+ int /*nrects*/,
+ xRectangle * /*pRects*/
+#endif
+);
+
+typedef void (* typePolyArc)(
+#if NeedNestedPrototypes
+ DrawablePtr /*pDrawable*/,
+ GCPtr /*pGC*/,
+ int /*narcs*/,
+ xArc * /*parcs*/
+#endif
+);
+
+typedef void (* typeFillPolygon)(
+#if NeedNestedPrototypes
+ DrawablePtr /*pDrawable*/,
+ GCPtr /*pGC*/,
+ int /*shape*/,
+ int /*mode*/,
+ int /*count*/,
+ DDXPointPtr /*pPts*/
+#endif
+);
+
+typedef void (* typePolyFillRect)(
+#if NeedNestedPrototypes
+ DrawablePtr /*pDrawable*/,
+ GCPtr /*pGC*/,
+ int /*nrectFill*/,
+ xRectangle * /*prectInit*/
+#endif
+);
+
+typedef void (* typePolyFillArc)(
+#if NeedNestedPrototypes
+ DrawablePtr /*pDrawable*/,
+ GCPtr /*pGC*/,
+ int /*narcs*/,
+ xArc * /*parcs*/
+#endif
+);
+
+typedef int (* typePolyText8)(
+#if NeedNestedPrototypes
+ DrawablePtr /*pDrawable*/,
+ GCPtr /*pGC*/,
+ int /*x*/,
+ int /*y*/,
+ int /*count*/,
+ char * /*chars*/
+#endif
+);
+
+typedef int (* typePolyText16)(
+#if NeedNestedPrototypes
+ DrawablePtr /*pDrawable*/,
+ GCPtr /*pGC*/,
+ int /*x*/,
+ int /*y*/,
+ int /*count*/,
+ unsigned short * /*chars*/
+#endif
+);
+
+typedef void (* typeImageText8)(
+#if NeedNestedPrototypes
+ DrawablePtr /*pDrawable*/,
+ GCPtr /*pGC*/,
+ int /*x*/,
+ int /*y*/,
+ int /*count*/,
+ char * /*chars*/
+#endif
+);
+
+typedef void (* typeImageText16)(
+#if NeedNestedPrototypes
+ DrawablePtr /*pDrawable*/,
+ GCPtr /*pGC*/,
+ int /*x*/,
+ int /*y*/,
+ int /*count*/,
+ unsigned short * /*chars*/
+#endif
+);
+
+typedef void (* typeImageGlyphBlt)(
+#if NeedNestedPrototypes
+ DrawablePtr /*pDrawable*/,
+ GCPtr /*pGC*/,
+ int /*x*/,
+ int /*y*/,
+ unsigned int /*nglyph*/,
+ CharInfoPtr * /*ppci*/,
+ pointer /*pglyphBase*/
+#endif
+);
+
+typedef void (* typePolyGlyphBlt)(
+#if NeedNestedPrototypes
+ DrawablePtr /*pDrawable*/,
+ GCPtr /*pGC*/,
+ int /*x*/,
+ int /*y*/,
+ unsigned int /*nglyph*/,
+ CharInfoPtr * /*ppci*/,
+ pointer /*pglyphBase*/
+#endif
+);
+
+typedef void (* typePushPixels)(
+#if NeedNestedPrototypes
+ GCPtr /*pGC*/,
+ PixmapPtr /*pBitMap*/,
+ DrawablePtr /*pDst*/,
+ int /*w*/,
+ int /*h*/,
+ int /*x*/,
+ int /*y*/
+#endif
+);
+
+RegionPtr
+KdNoopCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
+ int srcx, int srcy, int width, int height, int dstx, int dsty)
+{
+ return NullRegion;
+}
+
+RegionPtr
+KdNoopCopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
+ int srcx, int srcy, int width, int height,
+ int dstx, int dsty, unsigned long bitPlane)
+{
+ return NullRegion;
+}
+
+GCOps kdNoopOps = {
+ (typeFillSpans) NoopDDA, /* fill spans */
+ (typeSetSpans) NoopDDA, /* set spans */
+ (typePutImage) NoopDDA, /* put image */
+ KdNoopCopyArea, /* copy area */
+ KdNoopCopyPlane, /* copy plane */
+ (typePolyPoint) NoopDDA, /* poly point */
+ (typePolylines) NoopDDA, /* poly lines */
+ (typePolySegment) NoopDDA, /* poly segment */
+ (typePolyRectangle) NoopDDA, /* poly rectangle */
+ (typePolyArc) NoopDDA, /* poly arc */
+ (typeFillPolygon) NoopDDA, /* fill polygon */
+ (typePolyFillRect) NoopDDA, /* poly fillrect */
+ (typePolyFillArc) NoopDDA, /* poly fillarc */
+ (typePolyText8) NoopDDA, /* text 8 */
+ (typePolyText16) NoopDDA, /* text 16 */
+ (typeImageText8) NoopDDA, /* itext 8 */
+ (typeImageText16) NoopDDA, /* itext 16 */
+ (typePolyGlyphBlt) NoopDDA, /* glyph blt */
+ (typeImageGlyphBlt) NoopDDA, /* iglyph blt */
+ (typePushPixels) NoopDDA, /* push pixels */
+#ifdef NEED_LINEHELPER
+ (typeLineHelper) NULL,
+#endif
+};
diff --git a/hw/kdrive/src/ktest.c b/hw/kdrive/src/ktest.c
new file mode 100644
index 000000000..f4505406d
--- /dev/null
+++ b/hw/kdrive/src/ktest.c
@@ -0,0 +1,76 @@
+/*
+ * $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 "kdrive.h"
+
+
+static CARD8 memoryPatterns[] = { 0xff, 0x00, 0x5a, 0xa5, 0xaa, 0x55 };
+
+#define NUM_PATTERNS (sizeof (memoryPatterns) / sizeof (memoryPatterns[0]))
+
+Bool
+KdFrameBufferValid (CARD8 *base, int size)
+{
+ volatile CARD8 *b = (volatile CARD8 *) base;
+ CARD8 save, test, compare;
+ int i, j;
+
+ b = base + (size - 1);
+ save = *b;
+
+ for (i = 0; i < NUM_PATTERNS; i++)
+ {
+ test = memoryPatterns[i];
+ *b = test;
+ for (j = 0; j < 1000; j++)
+ {
+ compare = *b;
+ if (compare != test)
+ return FALSE;
+ }
+ }
+ *b = save;
+ return TRUE;
+}
+
+int
+KdFrameBufferSize (CARD8 *base, int max)
+{
+ int min, cur;
+
+ min = 0;
+ while (min + 1 < max)
+ {
+ cur = (max + min) / 2;
+ if (KdFrameBufferValid (base, cur))
+ min = cur;
+ else
+ max = cur;
+ }
+ if (KdFrameBufferValid (base, max))
+ return max;
+ else
+ return min;
+}
diff --git a/hw/kdrive/src/vga.c b/hw/kdrive/src/vga.c
new file mode 100644
index 000000000..0e0c53878
--- /dev/null
+++ b/hw/kdrive/src/vga.c
@@ -0,0 +1,288 @@
+/*
+ * $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 "vga.h"
+#include <stdio.h>
+
+#ifdef linux
+#define extern
+#include <asm/io.h>
+#undef extern
+
+#define _VgaInb(r) inb(r)
+#define _VgaOutb(v,r) outb(v,r)
+
+#endif
+
+#if 0
+#define VGA_DEBUG(a) fprintf a
+#else
+#define VGA_DEBUG(a)
+#endif
+
+VGA8
+VgaInb (VGA16 r)
+{
+ return _VgaInb(r);
+}
+
+void
+VgaOutb (VGA8 v, VGA16 r)
+{
+ _VgaOutb (v,r);
+}
+
+VGA8
+VgaFetch (VgaCard *card, VGA16 reg)
+{
+ VgaMap map;
+ VGAVOL8 *mem;
+ VGA8 value;
+
+ (*card->map) (card, reg, &map, VGAFALSE);
+ switch (map.access) {
+ case VgaAccessMem:
+ mem = (VGAVOL8 *) map.port;
+ value = *mem;
+ break;
+ case VgaAccessIo:
+ value = _VgaInb (map.port);
+ VGA_DEBUG ((stderr, "%4x -> %2x\n", map.port, value));
+ break;
+ case VgaAccessIndMem:
+ mem = (VGAVOL8 *) map.port;
+ mem[map.addr] = map.index;
+ value = mem[map.value];
+ break;
+ case VgaAccessIndIo:
+ _VgaOutb (map.index, map.port + map.addr);
+ value = _VgaInb (map.port + map.value);
+ VGA_DEBUG ((stderr, "%4x/%2x -> %2x\n", map.port, map.index, value));
+ break;
+ case VgaAccessDone:
+ value = map.value;
+ VGA_DEBUG ((stderr, "direct %4x -> %2x\n", reg, value));
+ break;
+ }
+ return value;
+}
+
+void
+VgaStore (VgaCard *card, VGA16 reg, VGA8 value)
+{
+ VgaMap map;
+ VGAVOL8 *mem;
+
+ map.value = value;
+ (*card->map) (card, reg, &map, VGATRUE);
+ switch (map.access) {
+ case VgaAccessMem:
+ mem = (VGAVOL8 *) map.port;
+ *mem = value;
+ break;
+ case VgaAccessIo:
+ VGA_DEBUG ((stderr, "%4x <- %2x\n", map.port, value));
+ _VgaOutb (value, map.port);
+ break;
+ case VgaAccessIndMem:
+ mem = (VGAVOL8 *) map.port;
+ mem[map.addr] = map.index;
+ mem[map.value] = value;
+ break;
+ case VgaAccessIndIo:
+ VGA_DEBUG ((stderr, "%4x/%2x <- %2x\n", map.port, map.index, value));
+ _VgaOutb (map.index, map.port + map.addr);
+ _VgaOutb (value, map.port + map.value);
+ break;
+ case VgaAccessDone:
+ VGA_DEBUG ((stderr, "direct %4x <- %2x\n", reg, value));
+ break;
+ }
+}
+
+void
+VgaPreserve (VgaCard *card)
+{
+ VgaSave *s;
+ VGA16 id;
+
+ for (s = card->saves; s->first != VGA_REG_NONE; s++)
+ {
+ for (id = s->first; id <= s->last; id++)
+ {
+ card->values[id].cur = VgaFetch (card, id);
+ card->values[id].save = card->values[id].cur;
+ card->values[id].flags = VGA_VALUE_VALID | VGA_VALUE_SAVED;
+ }
+ }
+}
+
+void
+VgaRestore (VgaCard *card)
+{
+ VgaSave *s;
+ VGA16 id;
+
+ for (s = card->saves; s->first != VGA_REG_NONE; s++)
+ {
+ for (id = s->first; id <= s->last; id++)
+ {
+ if (card->values[id].flags & VGA_VALUE_SAVED)
+ {
+ VgaStore (card, id, card->values[id].save);
+ card->values[id].cur = card->values[id].save;
+ }
+ }
+ }
+}
+
+void
+VgaFinish (VgaCard *card)
+{
+ VGA16 id;
+
+ for (id = 0; id < card->max; id++)
+ card->values[id].flags = 0;
+}
+
+void
+_VgaSync (VgaCard *card, VGA16 id)
+{
+ if (!(card->values[id].flags & VGA_VALUE_VALID))
+ {
+ card->values[id].cur = VgaFetch (card, id);
+ card->values[id].flags |= VGA_VALUE_VALID;
+ }
+}
+
+void
+VgaSet (VgaCard *card, VgaReg *reg, VGA32 value)
+{
+ VGA8 v, mask, new;
+
+ while (reg->len)
+ {
+ if (reg->id != VGA_REG_NONE)
+ {
+ _VgaSync (card, reg->id);
+ mask = ((1 << reg->len) - 1);
+ new = value & mask;
+ mask <<= reg->base;
+ new <<= reg->base;
+ v = card->values[reg->id].cur;
+ v = v & ~mask | new;
+ card->values[reg->id].cur = v;
+ card->values[reg->id].flags |= VGA_VALUE_MODIFIED|VGA_VALUE_DIRTY;
+ }
+ value >>= reg->len;
+ reg++;
+ }
+}
+
+void
+VgaFlushReg (VgaCard *card, VgaReg *reg)
+{
+ while (reg->len)
+ {
+ if (reg->id != VGA_REG_NONE)
+ {
+ if (card->values[reg->id].flags & VGA_VALUE_DIRTY)
+ {
+ VgaStore (card, reg->id, card->values[reg->id].cur);
+ card->values[reg->id].flags &= ~VGA_VALUE_DIRTY;
+ }
+ }
+ reg++;
+ }
+
+}
+
+void
+VgaSetImm (VgaCard *card, VgaReg *reg, VGA32 value)
+{
+ VgaSet (card, reg, value);
+ VgaFlushReg (card, reg);
+}
+
+VGA32
+VgaGet (VgaCard *card, VgaReg *reg)
+{
+ VGA32 value, offset, v;
+ VGA8 mask;
+
+ value = 0;
+ offset = 0;
+ while (reg->len)
+ {
+ if (reg->id != VGA_REG_NONE)
+ {
+ _VgaSync (card, reg->id);
+ mask = ((1 << reg->len) - 1);
+ v = (card->values[reg->id].cur >> reg->base) & mask;
+ value |= (v << offset);
+ }
+ offset += reg->len;
+ reg++;
+ }
+ return value;
+}
+
+VGA32
+VgaGetImm (VgaCard *card, VgaReg *reg)
+{
+ VgaReg *r = reg;
+
+ while (r->len)
+ {
+ if (r->id != VGA_REG_NONE)
+ card->values[r->id].flags &= ~VGA_VALUE_VALID;
+ r++;
+ }
+ return VgaGet (card, reg);
+}
+
+void
+VgaFlush (VgaCard *card)
+{
+ VGA16 id;
+
+ for (id = 0; id < card->max; id++)
+ {
+ if (card->values[id].flags & VGA_VALUE_DIRTY)
+ {
+ VgaStore (card, id, card->values[id].cur);
+ card->values[id].flags &= ~VGA_VALUE_DIRTY;
+ }
+ }
+}
+
+void
+VgaFill (VgaCard *card, VGA16 low, VGA16 high)
+{
+ VGA16 id;
+
+ for (id = low; id < high; id++)
+ _VgaSync (card, id);
+}
diff --git a/hw/kdrive/src/vga.h b/hw/kdrive/src/vga.h
new file mode 100644
index 000000000..b254152cb
--- /dev/null
+++ b/hw/kdrive/src/vga.h
@@ -0,0 +1,132 @@
+/*
+ * $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: $ */
+
+#ifndef _VGA_H_
+#define _VGA_H_
+
+typedef unsigned long VGA32;
+typedef unsigned short VGA16;
+typedef unsigned char VGA8;
+typedef int VGABOOL;
+typedef volatile VGA8 VGAVOL8;
+
+#define VGATRUE 1
+#define VGAFALSE 0
+
+typedef struct _vgaReg {
+ VGA16 id;
+ VGA8 base;
+ VGA8 len;
+} VgaReg;
+
+#define VGA_REG_NONE 0xffff
+#define VGA_REG_END VGA_REG_NONE, 0, 0
+
+typedef struct _vgaValue {
+ VGA8 save;
+ VGA8 cur;
+ VGA16 flags;
+} VgaValue;
+
+#define VGA_VALUE_VALID 1 /* value ever fetched */
+#define VGA_VALUE_MODIFIED 2 /* value ever changed */
+#define VGA_VALUE_DIRTY 4 /* value needs syncing */
+#define VGA_VALUE_SAVED 8 /* value preserved */
+
+typedef enum _vgaAccess {
+ VgaAccessMem, VgaAccessIo, VgaAccessIndMem, VgaAccessIndIo,
+ VgaAccessDone,
+} VgaAccess;
+
+typedef struct _vgaMap {
+ VgaAccess access;
+ VGA32 port;
+ VGA8 addr; /* for Ind access; addr offset from port */
+ VGA8 value; /* for Ind access; value offset from port */
+ VGA8 index; /* for Ind access; index value */
+} VgaMap;
+
+#define VGA_UNLOCK_FIXED 1 /* dont save current value */
+#define VGA_UNLOCK_LOCK 2 /* execute only on relock */
+#define VGA_UNLOCK_UNLOCK 4 /* execute only on unlock */
+
+typedef struct _vgaSave {
+ VGA16 first;
+ VGA16 last;
+} VgaSave;
+
+#define VGA_SAVE_END VGA_REG_NONE, VGA_REG_NONE
+
+typedef struct _vgaCard {
+ void (*map) (struct _vgaCard *card, VGA16 reg, VgaMap *map, VGABOOL write);
+ void *closure;
+ int max;
+ VgaValue *values;
+ VgaSave *saves;
+} VgaCard;
+
+VGA8
+VgaInb (VGA16 r);
+
+void
+VgaOutb (VGA8 v, VGA16 r);
+
+void
+VgaSetImm (VgaCard *card, VgaReg *reg, VGA32 value);
+
+VGA32
+VgaGetImm (VgaCard *card, VgaReg *reg);
+
+void
+VgaSet (VgaCard *card, VgaReg *reg, VGA32 value);
+
+VGA32
+VgaGet (VgaCard *card, VgaReg *reg);
+
+void
+VgaFlush (VgaCard *card);
+
+void
+VgaFill (VgaCard *card, VGA16 low, VGA16 high);
+
+void
+VgaPreserve (VgaCard *card);
+
+void
+VgaRestore (VgaCard *card);
+
+VGA8
+VgaFetch (VgaCard *card, VGA16 id);
+
+void
+VgaStore (VgaCard *card, VGA16 id, VGA8 value);
+
+VGA8
+_VgaFetchInd (VGA16 port, VGA8 reg);
+
+void
+_VgaStoreInd (VGA16 port, VGA8 reg, VGA8 value);
+
+#endif /* _VGA_H_ */
diff --git a/hw/kdrive/trident/Imakefile b/hw/kdrive/trident/Imakefile
new file mode 100644
index 000000000..f2456a214
--- /dev/null
+++ b/hw/kdrive/trident/Imakefile
@@ -0,0 +1,15 @@
+XCOMM $XConsortium: Imakefile /main/10 1996/12/02 10:20:33 lehors $
+XCOMM $XFree86: xc/programs/Xserver/hw/nvfb/Imakefile,v 3.8 1996/12/23 06:30:19 dawes Exp $
+#include <Server.tmpl>
+
+SRCS = trident.c tridentdraw.c tridentcurs.c tridentstub.c
+
+OBJS = trident.o tridentdraw.o tridentcurs.o tridentstub.o
+
+INCLUDES = -I.. -I../fbdev -I. -I$(XBUILDINCDIR) -I$(FONTINCSRC) \
+ -I../../../fb -I../../../mi -I../../../include -I../../../os \
+ -I$(EXTINCSRC) -I$(XINCLUDESRC)
+
+NormalLibraryObjectRule()
+NormalLibraryTarget(trident,$(OBJS))
+DependTarget()
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 */
+};
diff --git a/hw/kdrive/trident/trident.h b/hw/kdrive/trident/trident.h
new file mode 100644
index 000000000..f726e0701
--- /dev/null
+++ b/hw/kdrive/trident/trident.h
@@ -0,0 +1,205 @@
+/*
+ * $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: $ */
+
+#ifndef _TRIDENT_H_
+#define _TRIDENT_H_
+#include <fbdev.h>
+
+/*
+ * offset from ioport beginning
+ */
+#define TRIDENT_COP_BASE 0xbf000
+#define TRIDENT_COP_OFF 0x00f00
+#define TRIDENT_COP_SIZE (0x2000)
+
+typedef volatile CARD8 VOL8;
+typedef volatile CARD16 VOL16;
+typedef volatile CARD32 VOL32;
+
+typedef struct _cop {
+ VOL32 src_start_xy; /* 0x00 */
+ VOL32 src_end_xy; /* 0x04 */
+ VOL32 dst_start_xy; /* 0x08 */
+ VOL32 dst_end_xy; /* 0x0c */
+ VOL32 alpha; /* 0x10 */
+ CARD8 pad14[0xc]; /* 0x14 */
+ VOL32 multi; /* 0x20 */
+
+#define COP_MULTI_CLIP_TOP_LEFT 0x10000000
+#define COP_MULTI_DEPTH 0x40000000
+#define COP_MULTI_COLOR_KEY 0x70000000
+#define COP_MULTI_STYLE 0x50000000
+#define COP_MULTI_PATTERN 0x80000000
+#define COP_MULTI_ROP 0x90000000
+#define COP_MULTI_STRIDE 0x60000000
+#define COP_MULTI_Z 0xa0000000
+#define COP_MULTI_ALPHA 0xb0000000
+#define COP_MULTI_TEXTURE 0xd0000000
+#define COP_MULTI_TEXTURE_BOUND 0xe0000000
+#define COP_MULTI_TEXTURE_ADVANCED 0x20000000
+#define COP_MULTI_MASK 0xf0000000
+
+
+#define COP_DEPTH_8 0x00000000
+#define COP_DEPTH_16 0x00000001
+#define COP_DEPTH_24_32 0x00000002
+#define COP_DEPTH_15 0x00000005
+#define COP_DEPTH_DITHER_DISABLE 0x00000008
+
+ VOL32 command; /* 0x24 */
+#define COP_OP_NULL 0x00000000
+#define COP_OP_LINE 0x20000000
+#define COP_OP_BLT 0x80000000
+#define COP_OP_TEXT 0x90000000
+#define COP_OP_POLY 0xb0000000
+#define COP_OP_POLY2 0xe0000000
+#define COP_SCL_EXPAND 0x00800000
+#define COP_SCL_OPAQUE 0x00400000
+#define COP_SCL_REVERSE 0x00200000
+#define COP_SCL_MONO_OFF 0x001c0000
+#define COP_LIT_TEXTURE 0x00004000
+#define COP_BILINEAR 0x00002000
+#define COP_OP_ZBUF 0x00000800
+#define COP_OP_ROP 0x00000400
+#define COP_OP_FG 0x00000200
+#define COP_OP_FB 0x00000080
+#define COP_X_REVERSE 0x00000004
+#define COP_CLIP 0x00000001
+ VOL32 texture_format; /* 0x28 */
+ CARD8 pad2c[0x4]; /* 0x2c */
+
+ VOL32 clip_bottom_right; /* 0x30 */
+ VOL32 dataIII; /* 0x34 */
+ VOL32 dataIV; /* 0x38 */
+ CARD8 pad3c[0x8]; /* 0x3c */
+
+ VOL32 fg; /* 0x44 */
+ VOL32 bg; /* 0x48 */
+ CARD8 pad4c[0x4]; /* 0x4c */
+
+ VOL32 pattern_fg; /* 0x50 */
+ VOL32 pattern_bg; /* 0x54 */
+ CARD8 pad58[0xc]; /* 0x58 */
+
+ VOL32 status; /* 0x64 */
+#define COP_STATUS_BE_BUSY 0x80000000
+#define COP_STATUS_DPE_BUSY 0x20000000
+#define COP_STATUS_MI_BUSY 0x10000000
+#define COP_STATUS_FIFO_BUSY 0x08000000
+#define COP_STATUS_WB_BUSY 0x00800000
+#define COP_STATUS_Z_FAILED 0x00400000
+#define COP_STATUS_EFFECTIVE 0x00200000
+#define COP_STATUS_LEFT_VIEW 0x00080000
+
+ CARD8 pad68[0x4]; /* 0x68 */
+
+ VOL32 src_offset; /* 0x6c */
+ VOL32 z_offset; /* 0x70 */
+ CARD8 pad74[0x4]; /* 0x74 */
+
+ VOL32 display_offset; /* 0x78 */
+ VOL32 dst_offset; /* 0x7c */
+ CARD8 pad80[0x34]; /* 0x80 */
+
+ VOL32 semaphore; /* 0xb4 */
+} Cop;
+
+#define TRI_XY(x,y) ((y) << 16 | (x))
+
+typedef struct _tridentSave {
+ CARD8 reg_3c4_0e; /* config port value */
+ CARD8 reg_3d4_36;
+ CARD8 reg_3d4_39;
+ CARD8 reg_3d4_62; /* GE setup */
+ CARD8 reg_3ce_21; /* DPMS */
+} TridentSave;
+
+typedef struct _tridentCardInfo {
+ FbdevPriv fb;
+ CARD8 *cop_base;
+ Cop *cop;
+ CARD32 cop_depth;
+ CARD32 cop_stride;
+ TridentSave save;
+} TridentCardInfo;
+
+#define getTridentCardInfo(kd) ((TridentCardInfo *) ((kd)->card->driver))
+#define tridentCardInfo(kd) TridentCardInfo *tridentc = getTridentCardInfo(kd)
+
+typedef struct _tridentCursor {
+ int width, height;
+ int xhot, yhot;
+ Bool has_cursor;
+ CursorPtr pCursor;
+ Pixel source, mask;
+} TridentCursor;
+
+#define TRIDENT_CURSOR_WIDTH 64
+#define TRIDENT_CURSOR_HEIGHT 64
+
+typedef struct _tridentScreenInfo {
+ CARD8 *cursor_base;
+ TridentCursor cursor;
+} TridentScreenInfo;
+
+#define getTridentScreenInfo(kd) ((TridentScreenInfo *) ((kd)->screen->driver))
+#define tridentScreenInfo(kd) TridentScreenInfo *tridents = getTridentScreenInfo(kd)
+
+Bool
+tridentDrawInit (ScreenPtr pScreen);
+
+void
+tridentDrawEnable (ScreenPtr pScreen);
+
+void
+tridentDrawDisable (ScreenPtr pScreen);
+
+void
+tridentDrawFini (ScreenPtr pScreen);
+
+CARD8
+tridentReadIndex (TridentCardInfo *tridentc, CARD16 port, CARD8 index);
+
+void
+tridentWriteIndex (TridentCardInfo *tridentc, CARD16 port, CARD8 index, CARD8 value);
+
+Bool
+tridentCursorInit (ScreenPtr pScreen);
+
+void
+tridentCursorEnable (ScreenPtr pScreen);
+
+void
+tridentCursorDisable (ScreenPtr pScreen);
+
+void
+tridentCursorFini (ScreenPtr pScreen);
+
+void
+tridentRecolorCursor (ScreenPtr pScreen, int ndef, xColorItem *pdef);
+
+extern KdCardFuncs tridentFuncs;
+
+#endif /* _TRIDENT_H_ */
diff --git a/hw/kdrive/trident/tridentcurs.c b/hw/kdrive/trident/tridentcurs.c
new file mode 100644
index 000000000..9c4ebb5d0
--- /dev/null
+++ b/hw/kdrive/trident/tridentcurs.c
@@ -0,0 +1,414 @@
+/*
+ * $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"
+#include "cursorstr.h"
+
+#define SetupCursor(s) KdScreenPriv(s); \
+ tridentCardInfo(pScreenPriv); \
+ tridentScreenInfo(pScreenPriv); \
+ TridentCursor *pCurPriv = &tridents->cursor
+
+static void
+_tridentMoveCursor (ScreenPtr pScreen, int x, int y)
+{
+ SetupCursor(pScreen);
+ CARD8 xlow, xhigh, ylow, yhigh;
+ CARD8 xoff, yoff;
+
+ x -= pCurPriv->xhot;
+ xoff = 0;
+ if (x < 0)
+ {
+ xoff = -x;
+ x = 0;
+ }
+ y -= pCurPriv->yhot;
+ yoff = 0;
+ if (y < 0)
+ {
+ yoff = -y;
+ y = 0;
+ }
+ xlow = (CARD8) x;
+ xhigh = (CARD8) (x >> 8);
+ ylow = (CARD8) y;
+ yhigh = (CARD8) (y >> 8);
+
+
+ /* This is the recommended order to move the cursor */
+
+ tridentWriteIndex (tridentc, 0x3d4, 0x41, xhigh);
+ tridentWriteIndex (tridentc, 0x3d4, 0x40, xlow);
+ tridentWriteIndex (tridentc, 0x3d4, 0x42, ylow);
+ tridentWriteIndex (tridentc, 0x3d4, 0x46, xoff);
+ tridentWriteIndex (tridentc, 0x3d4, 0x47, yoff);
+ tridentWriteIndex (tridentc, 0x3d4, 0x43, yhigh);
+}
+
+static void
+tridentMoveCursor (ScreenPtr pScreen, int x, int y)
+{
+ SetupCursor (pScreen);
+
+ if (!pCurPriv->has_cursor)
+ return;
+
+ if (!pScreenPriv->enabled)
+ return;
+
+ _tridentMoveCursor (pScreen, x, y);
+}
+
+
+static void
+tridentAllocCursorColors (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+ CursorPtr pCursor = pCurPriv->pCursor;
+ xColorItem sourceColor, maskColor;
+
+ /*
+ * Set these to an invalid pixel value so that
+ * when the store colors comes through, the cursor
+ * won't get recolored
+ */
+ pCurPriv->source = ~0;
+ pCurPriv->mask = ~0;
+ /*
+ * XXX S3 bug workaround; s3 chip doesn't use RGB values from
+ * the cursor color registers as documented, rather it uses
+ * them to index the DAC. This is in the errata though.
+ */
+ sourceColor.red = pCursor->foreRed;
+ sourceColor.green = pCursor->foreGreen;
+ sourceColor.blue = pCursor->foreBlue;
+ FakeAllocColor(pScreenPriv->pInstalledmap, &sourceColor);
+ maskColor.red = pCursor->backRed;
+ maskColor.green = pCursor->backGreen;
+ maskColor.blue = pCursor->backBlue;
+ FakeAllocColor(pScreenPriv->pInstalledmap, &maskColor);
+ FakeFreeColor(pScreenPriv->pInstalledmap, sourceColor.pixel);
+ FakeFreeColor(pScreenPriv->pInstalledmap, maskColor.pixel);
+
+ pCurPriv->source = sourceColor.pixel;
+ pCurPriv->mask = maskColor.pixel;
+ switch (pScreenPriv->screen->bitsPerPixel) {
+ case 4:
+ pCurPriv->source |= pCurPriv->source << 4;
+ pCurPriv->mask |= pCurPriv->mask << 4;
+ case 8:
+ pCurPriv->source |= pCurPriv->source << 8;
+ pCurPriv->mask |= pCurPriv->mask << 8;
+ case 16:
+ pCurPriv->source |= pCurPriv->source << 16;
+ pCurPriv->mask |= pCurPriv->mask << 16;
+ }
+}
+
+static void
+tridentSetCursorColors (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+ CursorPtr pCursor = pCurPriv->pCursor;
+ CARD32 fg, bg;
+
+ fg = pCurPriv->source;
+ bg = pCurPriv->mask;
+ tridentWriteIndex (tridentc, 0x3d4, 0x48, fg);
+ tridentWriteIndex (tridentc, 0x3d4, 0x49, fg >> 8);
+ tridentWriteIndex (tridentc, 0x3d4, 0x4a, fg >> 16);
+
+ tridentWriteIndex (tridentc, 0x3d4, 0x4c, bg);
+ tridentWriteIndex (tridentc, 0x3d4, 0x4d, bg >> 8);
+ tridentWriteIndex (tridentc, 0x3d4, 0x4e, bg >> 16);
+}
+
+void
+tridentRecolorCursor (ScreenPtr pScreen, int ndef, xColorItem *pdef)
+{
+ SetupCursor (pScreen);
+ CursorPtr pCursor = pCurPriv->pCursor;
+ xColorItem sourceColor, maskColor;
+
+ if (!pCurPriv->has_cursor || !pCursor)
+ return;
+
+ if (!pScreenPriv->enabled)
+ return;
+
+ if (pdef)
+ {
+ while (ndef)
+ {
+ if (pdef->pixel == pCurPriv->source ||
+ pdef->pixel == pCurPriv->mask)
+ break;
+ ndef--;
+ }
+ if (!ndef)
+ return;
+ }
+ tridentAllocCursorColors (pScreen);
+ tridentSetCursorColors (pScreen);
+}
+
+#define InvertBits32(v) { \
+ v = ((v & 0x55555555) << 1) | ((v >> 1) & 0x55555555); \
+ v = ((v & 0x33333333) << 2) | ((v >> 2) & 0x33333333); \
+ v = ((v & 0x0f0f0f0f) << 4) | ((v >> 4) & 0x0f0f0f0f); \
+}
+
+static void
+tridentLoadCursor (ScreenPtr pScreen, int x, int y)
+{
+ SetupCursor(pScreen);
+ CursorPtr pCursor = pCurPriv->pCursor;
+ CursorBitsPtr bits = pCursor->bits;
+ int w, h;
+ CARD32 *ram, *msk, *mskLine, *src, *srcLine;
+ int i, j;
+ int cursor_address;
+ int lwsrc;
+ unsigned char ramdac_control_;
+ CARD32 offset;
+
+ /*
+ * Allocate new colors
+ */
+ tridentAllocCursorColors (pScreen);
+
+ pCurPriv->pCursor = pCursor;
+ pCurPriv->xhot = pCursor->bits->xhot;
+ pCurPriv->yhot = pCursor->bits->yhot;
+
+ /*
+ * Stick new image into cursor memory
+ */
+ ram = (CARD32 *) tridents->cursor_base;
+ mskLine = (CARD32 *) bits->mask;
+ srcLine = (CARD32 *) bits->source;
+
+ h = bits->height;
+ if (h > TRIDENT_CURSOR_HEIGHT)
+ h = TRIDENT_CURSOR_HEIGHT;
+
+ lwsrc = BitmapBytePad(bits->width) / 4; /* words per line */
+
+ for (i = 0; i < TRIDENT_CURSOR_HEIGHT; i++) {
+ msk = mskLine;
+ src = srcLine;
+ mskLine += lwsrc;
+ srcLine += lwsrc;
+ for (j = 0; j < TRIDENT_CURSOR_WIDTH / 32; j++) {
+
+ CARD32 m, s;
+
+#if 1
+ if (i < h && j < lwsrc)
+ {
+ m = *msk++;
+ s = *src++;
+ InvertBits32(m);
+ InvertBits32(s);
+ }
+ else
+ {
+ m = 0;
+ s = 0;
+ }
+#endif
+ *ram++ = m;
+ *ram++ = s;
+ }
+ }
+
+ /* Set address for cursor bits */
+ offset = tridents->cursor_base - (CARD8 *) tridentc->fb.fb;
+ offset >>= 10;
+ tridentWriteIndex (tridentc, 0x3d4, 0x44, (CARD8) (offset & 0xff));
+ tridentWriteIndex (tridentc, 0x3d4, 0x45, (CARD8) (offset >> 8));
+
+ /* Set new color */
+ tridentSetCursorColors (pScreen);
+
+ /* Enable the cursor */
+ tridentWriteIndex (tridentc, 0x3d4, 0x50, 0xc1);
+
+ /* Move to new position */
+ tridentMoveCursor (pScreen, x, y);
+}
+
+static void
+tridentUnloadCursor (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ /* Disable cursor */
+ tridentWriteIndex (tridentc, 0x3d4, 0x50, 0);
+}
+
+static Bool
+tridentRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
+{
+ SetupCursor(pScreen);
+
+ if (!pScreenPriv->enabled)
+ return TRUE;
+
+ /* miRecolorCursor does this */
+ if (pCurPriv->pCursor == pCursor)
+ {
+ if (pCursor)
+ {
+ int x, y;
+
+ miPointerPosition (&x, &y);
+ tridentLoadCursor (pScreen, x, y);
+ }
+ }
+ return TRUE;
+}
+
+static Bool
+tridentUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
+{
+ return TRUE;
+}
+
+static void
+tridentSetCursor (ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
+{
+ SetupCursor(pScreen);
+
+ pCurPriv->pCursor = pCursor;
+
+ if (!pScreenPriv->enabled)
+ return;
+
+ if (pCursor)
+ tridentLoadCursor (pScreen, x, y);
+ else
+ tridentUnloadCursor (pScreen);
+}
+
+miPointerSpriteFuncRec tridentPointerSpriteFuncs = {
+ tridentRealizeCursor,
+ tridentUnrealizeCursor,
+ tridentSetCursor,
+ tridentMoveCursor,
+};
+
+static void
+tridentQueryBestSize (int class,
+ unsigned short *pwidth, unsigned short *pheight,
+ ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ switch (class)
+ {
+ case CursorShape:
+ if (*pwidth > pCurPriv->width)
+ *pwidth = pCurPriv->width;
+ if (*pheight > pCurPriv->height)
+ *pheight = pCurPriv->height;
+ if (*pwidth > pScreen->width)
+ *pwidth = pScreen->width;
+ if (*pheight > pScreen->height)
+ *pheight = pScreen->height;
+ break;
+ default:
+ fbQueryBestSize (class, pwidth, pheight, pScreen);
+ break;
+ }
+}
+
+Bool
+tridentCursorInit (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ if (!tridents->cursor_base)
+ {
+ pCurPriv->has_cursor = FALSE;
+ return FALSE;
+ }
+
+ pCurPriv->width = TRIDENT_CURSOR_WIDTH;
+ pCurPriv->height= TRIDENT_CURSOR_HEIGHT;
+ pScreen->QueryBestSize = tridentQueryBestSize;
+ miPointerInitialize (pScreen,
+ &tridentPointerSpriteFuncs,
+ &kdPointerScreenFuncs,
+ FALSE);
+ pCurPriv->has_cursor = TRUE;
+ pCurPriv->pCursor = NULL;
+ return TRUE;
+}
+
+void
+tridentCursorEnable (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ if (pCurPriv->has_cursor)
+ {
+ if (pCurPriv->pCursor)
+ {
+ int x, y;
+
+ miPointerPosition (&x, &y);
+ tridentLoadCursor (pScreen, x, y);
+ }
+ else
+ tridentUnloadCursor (pScreen);
+ }
+}
+
+void
+tridentCursorDisable (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ if (!pScreenPriv->enabled)
+ return;
+
+ if (pCurPriv->has_cursor)
+ {
+ if (pCurPriv->pCursor)
+ {
+ tridentUnloadCursor (pScreen);
+ }
+ }
+}
+
+void
+tridentCursorFini (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ pCurPriv->pCursor = NULL;
+}
diff --git a/hw/kdrive/trident/tridentdraw.c b/hw/kdrive/trident/tridentdraw.c
new file mode 100644
index 000000000..f64444c53
--- /dev/null
+++ b/hw/kdrive/trident/tridentdraw.c
@@ -0,0 +1,859 @@
+/*
+ * $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"
+#include "tridentdraw.h"
+
+#include "Xmd.h"
+#include "gcstruct.h"
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "regionstr.h"
+#include "mistruct.h"
+#include "fontstruct.h"
+#include "dixfontstr.h"
+#include "fb.h"
+#include "migc.h"
+#include "miline.h"
+
+CARD8 tridentRop[16] = {
+ /* GXclear */ 0x00, /* 0 */
+ /* GXand */ 0x88, /* src AND dst */
+ /* GXandReverse */ 0x44, /* src AND NOT dst */
+ /* GXcopy */ 0xcc, /* src */
+ /* GXandInverted*/ 0x22, /* NOT src AND dst */
+ /* GXnoop */ 0xaa, /* dst */
+ /* GXxor */ 0x66, /* src XOR dst */
+ /* GXor */ 0xee, /* src OR dst */
+ /* GXnor */ 0x11, /* NOT src AND NOT dst */
+ /* GXequiv */ 0x99, /* NOT src XOR dst */
+ /* GXinvert */ 0x55, /* NOT dst */
+ /* GXorReverse */ 0xdd, /* src OR NOT dst */
+ /* GXcopyInverted*/ 0x33, /* NOT src */
+ /* GXorInverted */ 0xbb, /* NOT src OR dst */
+ /* GXnand */ 0x77, /* NOT src OR NOT dst */
+ /* GXset */ 0xff, /* 1 */
+};
+
+#define tridentFillPix(bpp,pixel) {\
+ if (bpp == 8) \
+ { \
+ pixel = pixel & 0xff; \
+ pixel = pixel | pixel << 8; \
+ } \
+ if (bpp <= 16) \
+ { \
+ pixel = pixel & 0xffff; \
+ pixel = pixel | pixel << 16; \
+ } \
+}
+void
+tridentFillBoxSolid (DrawablePtr pDrawable, int nBox, BoxPtr pBox,
+ unsigned long pixel, int alu)
+{
+ SetupTrident(pDrawable->pScreen);
+ CARD32 cmd;
+
+ tridentFillPix(pDrawable->bitsPerPixel,pixel);
+ _tridentInit(cop,tridentc);
+ _tridentSetSolidRect(cop,pixel,alu,cmd);
+ while (nBox--)
+ {
+ _tridentRect(cop,pBox->x1,pBox->y1,pBox->x2-1,pBox->y2-1,cmd);
+ pBox++;
+ }
+ _tridentWaitIdleEmpty(cop);
+}
+
+void
+tridentCopyNtoN (DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ BoxPtr pbox,
+ int nbox,
+ int dx,
+ int dy,
+ Bool reverse,
+ Bool upsidedown,
+ Pixel bitplane,
+ void *closure)
+{
+ SetupTrident(pDstDrawable->pScreen);
+ int srcX, srcY, dstX, dstY;
+ int w, h;
+ CARD32 flags;
+ CARD32 cmd;
+ CARD8 alu;
+
+ if (pGC)
+ {
+ alu = pGC->alu;
+ if (sourceInvarient (pGC->alu))
+ {
+ tridentFillBoxSolid (pDstDrawable, nbox, pbox, 0, pGC->alu);
+ return;
+ }
+ }
+ else
+ alu = GXcopy;
+
+ _tridentInit(cop,tridentc);
+ cop->multi = COP_MULTI_PATTERN;
+ cop->multi = COP_MULTI_ROP | tridentRop[alu];
+ if (reverse)
+ upsidedown = TRUE;
+ cmd = COP_OP_BLT | COP_SCL_OPAQUE | COP_OP_ROP | COP_OP_FB;
+ if (upsidedown)
+ cmd |= COP_X_REVERSE;
+ while (nbox--)
+ {
+ if (upsidedown)
+ {
+ cop->src_start_xy = TRI_XY (pbox->x2 + dx - 1,
+ pbox->y2 + dy - 1);
+ cop->src_end_xy = TRI_XY (pbox->x1 + dx,
+ pbox->y1 + dy);
+ cop->dst_start_xy = TRI_XY (pbox->x2 - 1,
+ pbox->y2 - 1);
+ cop->dst_end_xy = TRI_XY (pbox->x1,
+ pbox->y1);
+ }
+ else
+ {
+ cop->src_start_xy = TRI_XY (pbox->x1 + dx,
+ pbox->y1 + dy);
+ cop->src_end_xy = TRI_XY (pbox->x2 + dx - 1,
+ pbox->y2 + dy - 1);
+ cop->dst_start_xy = TRI_XY (pbox->x1,
+ pbox->y1);
+ cop->dst_end_xy = TRI_XY (pbox->x2 - 1,
+ pbox->y2 - 1);
+ }
+ cop->command = cmd;
+ pbox++;
+ }
+ _tridentWaitIdleEmpty(cop);
+}
+
+RegionPtr
+tridentCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
+ int srcx, int srcy, int width, int height, int dstx, int dsty)
+{
+ KdScreenPriv(pDstDrawable->pScreen);
+ FbBits depthMask;
+
+ depthMask = FbFullMask (pDstDrawable->depth);
+ if ((pGC->planemask & depthMask) == depthMask &&
+ pSrcDrawable->type == DRAWABLE_WINDOW &&
+ pDstDrawable->type == DRAWABLE_WINDOW)
+ {
+ return fbDoCopy (pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy, width, height,
+ dstx, dsty, tridentCopyNtoN, 0, 0);
+ }
+ return fbCopyArea (pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy, width, height, dstx, dsty);
+}
+
+BOOL
+tridentFillOk (GCPtr pGC)
+{
+ FbBits depthMask;
+
+ depthMask = FbFullMask(pGC->depth);
+ if ((pGC->planemask & depthMask) != depthMask)
+ return FALSE;
+ switch (pGC->fillStyle) {
+ case FillSolid:
+ return TRUE;
+#if 0
+ case FillTiled:
+ return (tridentPatternDimOk (pGC->tile.pixmap->drawable.width) &&
+ tridentPatternDimOk (pGC->tile.pixmap->drawable.height));
+ case FillStippled:
+ case FillOpaqueStippled:
+ return (tridentPatternDimOk (pGC->stipple->drawable.width) &&
+ tridentPatternDimOk (pGC->stipple->drawable.height));
+#endif
+ }
+ return FALSE;
+}
+
+void
+tridentFillSpans (DrawablePtr pDrawable, GCPtr pGC, int n,
+ DDXPointPtr ppt, int *pwidth, int fSorted)
+{
+ SetupTrident(pDrawable->pScreen);
+ DDXPointPtr pptFree;
+ FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC);
+ int *pwidthFree;/* copies of the pointers to free */
+ CARD32 cmd;
+ int nTmp;
+ INT16 x, y;
+ int width;
+ CARD32 pixel;
+
+ if (!tridentFillOk (pGC))
+ {
+ fbFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted);
+ return;
+ }
+ nTmp = n * miFindMaxBand(fbGetCompositeClip(pGC));
+ pwidthFree = (int *)ALLOCATE_LOCAL(nTmp * sizeof(int));
+ pptFree = (DDXPointRec *)ALLOCATE_LOCAL(nTmp * sizeof(DDXPointRec));
+ if(!pptFree || !pwidthFree)
+ {
+ if (pptFree) DEALLOCATE_LOCAL(pptFree);
+ if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree);
+ return;
+ }
+ n = miClipSpans(fbGetCompositeClip(pGC),
+ ppt, pwidth, n,
+ pptFree, pwidthFree, fSorted);
+ pwidth = pwidthFree;
+ ppt = pptFree;
+ _tridentInit(cop,tridentc);
+ switch (pGC->fillStyle) {
+ case FillSolid:
+ pixel = pGC->fgPixel;
+ tridentFillPix (pDrawable->bitsPerPixel,pixel);
+ _tridentSetSolidRect(cop,pixel,pGC->alu,cmd);
+ break;
+#if 0
+ case FillTiled:
+ cmd = tridentTilePrepare (pGC->tile.pixmap,
+ pGC->patOrg.x + pDrawable->x,
+ pGC->patOrg.y + pDrawable->y,
+ pGC->alu);
+ break;
+ default:
+ cmd = tridentStipplePrepare (pDrawable, pGC);
+ break;
+#endif
+ }
+ while (n--)
+ {
+ x = ppt->x;
+ y = ppt->y;
+ ppt++;
+ width = *pwidth++;
+ if (width)
+ {
+ _tridentRect(cop,x,y,x + width,y,cmd);
+ }
+ }
+ _tridentWaitIdleEmpty (cop);
+ DEALLOCATE_LOCAL(pptFree);
+ DEALLOCATE_LOCAL(pwidthFree);
+}
+
+#define NUM_STACK_RECTS 1024
+
+void
+tridentPolyFillRect (DrawablePtr pDrawable, GCPtr pGC,
+ int nrectFill, xRectangle *prectInit)
+{
+ SetupTrident(pDrawable->pScreen);
+ xRectangle *prect;
+ RegionPtr prgnClip;
+ register BoxPtr pbox;
+ register BoxPtr pboxClipped;
+ BoxPtr pboxClippedBase;
+ BoxPtr pextent;
+ BoxRec stackRects[NUM_STACK_RECTS];
+ FbGCPrivPtr fbPriv = fbGetGCPrivate (pGC);
+ int numRects;
+ int n;
+ int xorg, yorg;
+ int x, y;
+
+ if (!tridentFillOk (pGC))
+ {
+ fbPolyFillRect (pDrawable, pGC, nrectFill, prectInit);
+ return;
+ }
+ prgnClip = fbGetCompositeClip(pGC);
+ xorg = pDrawable->x;
+ yorg = pDrawable->y;
+
+ if (xorg || yorg)
+ {
+ prect = prectInit;
+ n = nrectFill;
+ while(n--)
+ {
+ prect->x += xorg;
+ prect->y += yorg;
+ prect++;
+ }
+ }
+
+ prect = prectInit;
+
+ numRects = REGION_NUM_RECTS(prgnClip) * nrectFill;
+ if (numRects > NUM_STACK_RECTS)
+ {
+ pboxClippedBase = (BoxPtr)xalloc(numRects * sizeof(BoxRec));
+ if (!pboxClippedBase)
+ return;
+ }
+ else
+ pboxClippedBase = stackRects;
+
+ pboxClipped = pboxClippedBase;
+
+ if (REGION_NUM_RECTS(prgnClip) == 1)
+ {
+ int x1, y1, x2, y2, bx2, by2;
+
+ pextent = REGION_RECTS(prgnClip);
+ x1 = pextent->x1;
+ y1 = pextent->y1;
+ x2 = pextent->x2;
+ y2 = pextent->y2;
+ while (nrectFill--)
+ {
+ if ((pboxClipped->x1 = prect->x) < x1)
+ pboxClipped->x1 = x1;
+
+ if ((pboxClipped->y1 = prect->y) < y1)
+ pboxClipped->y1 = y1;
+
+ bx2 = (int) prect->x + (int) prect->width;
+ if (bx2 > x2)
+ bx2 = x2;
+ pboxClipped->x2 = bx2;
+
+ by2 = (int) prect->y + (int) prect->height;
+ if (by2 > y2)
+ by2 = y2;
+ pboxClipped->y2 = by2;
+
+ prect++;
+ if ((pboxClipped->x1 < pboxClipped->x2) &&
+ (pboxClipped->y1 < pboxClipped->y2))
+ {
+ pboxClipped++;
+ }
+ }
+ }
+ else
+ {
+ int x1, y1, x2, y2, bx2, by2;
+
+ pextent = REGION_EXTENTS(pGC->pScreen, prgnClip);
+ x1 = pextent->x1;
+ y1 = pextent->y1;
+ x2 = pextent->x2;
+ y2 = pextent->y2;
+ while (nrectFill--)
+ {
+ BoxRec box;
+
+ if ((box.x1 = prect->x) < x1)
+ box.x1 = x1;
+
+ if ((box.y1 = prect->y) < y1)
+ box.y1 = y1;
+
+ bx2 = (int) prect->x + (int) prect->width;
+ if (bx2 > x2)
+ bx2 = x2;
+ box.x2 = bx2;
+
+ by2 = (int) prect->y + (int) prect->height;
+ if (by2 > y2)
+ by2 = y2;
+ box.y2 = by2;
+
+ prect++;
+
+ if ((box.x1 >= box.x2) || (box.y1 >= box.y2))
+ continue;
+
+ n = REGION_NUM_RECTS (prgnClip);
+ pbox = REGION_RECTS(prgnClip);
+
+ /* clip the rectangle to each box in the clip region
+ this is logically equivalent to calling Intersect()
+ */
+ while(n--)
+ {
+ pboxClipped->x1 = max(box.x1, pbox->x1);
+ pboxClipped->y1 = max(box.y1, pbox->y1);
+ pboxClipped->x2 = min(box.x2, pbox->x2);
+ pboxClipped->y2 = min(box.y2, pbox->y2);
+ pbox++;
+
+ /* see if clipping left anything */
+ if(pboxClipped->x1 < pboxClipped->x2 &&
+ pboxClipped->y1 < pboxClipped->y2)
+ {
+ pboxClipped++;
+ }
+ }
+ }
+ }
+ if (pboxClipped != pboxClippedBase)
+ {
+ switch (pGC->fillStyle) {
+ case FillSolid:
+ tridentFillBoxSolid(pDrawable,
+ pboxClipped-pboxClippedBase, pboxClippedBase,
+ pGC->fgPixel, pGC->alu);
+ break;
+#if 0
+ case FillTiled:
+ tridentFillBoxTiled(pDrawable,
+ pboxClipped-pboxClippedBase, pboxClippedBase,
+ pGC->tile.pixmap,
+ pGC->patOrg.x + pDrawable->x,
+ pGC->patOrg.y + pDrawable->y,
+ pGC->alu);
+ break;
+ case FillStippled:
+ case FillOpaqueStippled:
+ tridentFillBoxStipple (pDrawable, pGC,
+ pboxClipped-pboxClippedBase, pboxClippedBase);
+ break;
+#endif
+ }
+ }
+ if (pboxClippedBase != stackRects)
+ xfree(pboxClippedBase);
+}
+
+void
+tridentSolidBoxClipped (DrawablePtr pDrawable,
+ RegionPtr pClip,
+ int x1,
+ int y1,
+ int x2,
+ int y2,
+ FbBits fg)
+{
+ SetupTrident (pDrawable->pScreen);
+ BoxPtr pbox;
+ int nbox;
+ int partX1, partX2, partY1, partY2;
+ CARD32 cmd;
+
+ _tridentInit (cop, tridentc);
+ _tridentSetSolidRect (cop, fg, GXcopy, cmd);
+
+ for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip);
+ nbox--;
+ pbox++)
+ {
+ partX1 = pbox->x1;
+ if (partX1 < x1)
+ partX1 = x1;
+
+ partX2 = pbox->x2;
+ if (partX2 > x2)
+ partX2 = x2;
+
+ if (partX2 <= partX1)
+ continue;
+
+ partY1 = pbox->y1;
+ if (partY1 < y1)
+ partY1 = y1;
+
+ partY2 = pbox->y2;
+ if (partY2 > y2)
+ partY2 = y2;
+
+ if (partY2 <= partY1)
+ continue;
+
+ _tridentRect(cop,partX1, partY1, partX2-1, partY2-1,cmd);
+ }
+ _tridentWaitIdleEmpty(cop);
+}
+
+void
+tridentImageGlyphBlt (DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x,
+ int y,
+ unsigned int nglyph,
+ CharInfoPtr *ppciInit,
+ pointer pglyphBase)
+{
+ FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
+ CharInfoPtr *ppci;
+ CharInfoPtr pci;
+ unsigned char *pglyph; /* pointer bits in glyph */
+ int gWidth, gHeight; /* width and height of glyph */
+ FbStride gStride; /* stride of glyph */
+ Bool opaque;
+ int n;
+ int gx, gy;
+ void (*glyph) (FbBits *,
+ FbStride,
+ int,
+ FbStip *,
+ FbBits,
+ int,
+ int);
+ FbBits *dst;
+ FbStride dstStride;
+ int dstBpp;
+ FbBits depthMask;
+
+ depthMask = FbFullMask(pDrawable->depth);
+ if ((pGC->planemask & depthMask) != depthMask)
+ {
+ fbImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppciInit, pglyphBase);
+ return;
+ }
+ glyph = 0;
+ fbGetDrawable (pDrawable, dst, dstStride, dstBpp);
+ switch (dstBpp) {
+ case 8: glyph = fbGlyph8; break;
+ case 16: glyph = fbGlyph16; break;
+ case 24: glyph = fbGlyph24; break;
+ case 32: glyph = fbGlyph32; break;
+ }
+
+ x += pDrawable->x;
+ y += pDrawable->y;
+
+ if (TERMINALFONT (pGC->font) && !glyph)
+ {
+ opaque = TRUE;
+ }
+ else
+ {
+ int xBack, widthBack;
+ int yBack, heightBack;
+
+ ppci = ppciInit;
+ n = nglyph;
+ widthBack = 0;
+ while (n--)
+ widthBack += (*ppci++)->metrics.characterWidth;
+
+ xBack = x;
+ if (widthBack < 0)
+ {
+ xBack += widthBack;
+ widthBack = -widthBack;
+ }
+ yBack = y - FONTASCENT(pGC->font);
+ heightBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
+ tridentSolidBoxClipped (pDrawable,
+ fbGetCompositeClip(pGC),
+ xBack,
+ yBack,
+ xBack + widthBack,
+ yBack + heightBack,
+ pPriv->bg);
+ opaque = FALSE;
+ }
+
+ ppci = ppciInit;
+ while (nglyph--)
+ {
+ pci = *ppci++;
+ pglyph = FONTGLYPHBITS(pglyphBase, pci);
+ gWidth = GLYPHWIDTHPIXELS(pci);
+ gHeight = GLYPHHEIGHTPIXELS(pci);
+ if (gWidth && gHeight)
+ {
+ gx = x + pci->metrics.leftSideBearing;
+ gy = y - pci->metrics.ascent;
+ if (glyph && gWidth <= sizeof (FbStip) * 8 &&
+ fbGlyphIn (fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight))
+ {
+ (*glyph) (dst + gy * dstStride,
+ dstStride,
+ dstBpp,
+ (FbStip *) pglyph,
+ pPriv->fg,
+ gx,
+ gHeight);
+ }
+ else
+ {
+ gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof (FbStip);
+ fbPutXYImage (pDrawable,
+ fbGetCompositeClip(pGC),
+ pPriv->fg,
+ pPriv->bg,
+ pPriv->pm,
+ GXcopy,
+ opaque,
+
+ gx,
+ gy,
+ gWidth, gHeight,
+
+ (FbStip *) pglyph,
+ gStride,
+ 0);
+ }
+ }
+ x += pci->metrics.characterWidth;
+ }
+}
+
+static const GCOps tridentOps = {
+ tridentFillSpans,
+ fbSetSpans,
+ fbPutImage,
+ tridentCopyArea,
+ fbCopyPlane,
+ fbPolyPoint,
+ fbPolyLine,
+ fbPolySegment,
+ miPolyRectangle,
+ fbPolyArc,
+ miFillPolygon,
+ tridentPolyFillRect,
+ fbPolyFillArc,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ tridentImageGlyphBlt,
+ fbPolyGlyphBlt,
+ fbPushPixels,
+#ifdef NEED_LINEHELPER
+ ,NULL
+#endif
+};
+
+void
+tridentValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable)
+{
+ FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC);
+
+ fbValidateGC (pGC, changes, pDrawable);
+
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ pGC->ops = (GCOps *) &tridentOps;
+ else
+ pGC->ops = (GCOps *) &fbGCOps;
+}
+
+GCFuncs tridentGCFuncs = {
+ tridentValidateGC,
+ miChangeGC,
+ miCopyGC,
+ miDestroyGC,
+ miChangeClip,
+ miDestroyClip,
+ miCopyClip
+};
+
+int
+tridentCreateGC (GCPtr pGC)
+{
+ if (!fbCreateGC (pGC))
+ return FALSE;
+
+ if (pGC->depth != 1)
+ pGC->funcs = &tridentGCFuncs;
+
+ return TRUE;
+}
+
+void
+tridentCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ KdScreenPriv(pScreen);
+ RegionRec rgnDst;
+ int dx, dy;
+ WindowPtr pwinRoot;
+
+ pwinRoot = WindowTable[pWin->drawable.pScreen->myNum];
+
+ dx = ptOldOrg.x - pWin->drawable.x;
+ dy = ptOldOrg.y - pWin->drawable.y;
+ REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
+
+ REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0);
+
+ REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
+
+ fbCopyRegion ((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot,
+ 0,
+ &rgnDst, dx, dy, tridentCopyNtoN, 0, 0);
+
+ REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
+}
+
+void
+tridentPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
+{
+ KdScreenPriv(pWin->drawable.pScreen);
+ PixmapPtr pTile;
+
+ if (!REGION_NUM_RECTS(pRegion))
+ return;
+ switch (what) {
+ case PW_BACKGROUND:
+ switch (pWin->backgroundState) {
+ case None:
+ return;
+ case ParentRelative:
+ do {
+ pWin = pWin->parent;
+ } while (pWin->backgroundState == ParentRelative);
+ (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion,
+ what);
+ return;
+#if 0
+ case BackgroundPixmap:
+ pTile = pWin->background.pixmap;
+ if (tridentPatternDimOk (pTile->drawable.width) &&
+ tridentPatternDimOk (pTile->drawable.height))
+ {
+ tridentFillBoxTiled ((DrawablePtr)pWin,
+ (int)REGION_NUM_RECTS(pRegion),
+ REGION_RECTS(pRegion),
+ pTile,
+ pWin->drawable.x, pWin->drawable.y, GXcopy);
+ return;
+ }
+ break;
+#endif
+ case BackgroundPixel:
+ tridentFillBoxSolid((DrawablePtr)pWin,
+ (int)REGION_NUM_RECTS(pRegion),
+ REGION_RECTS(pRegion),
+ pWin->background.pixel, GXcopy);
+ return;
+ }
+ break;
+ case PW_BORDER:
+ if (pWin->borderIsPixel)
+ {
+ tridentFillBoxSolid((DrawablePtr)pWin,
+ (int)REGION_NUM_RECTS(pRegion),
+ REGION_RECTS(pRegion),
+ pWin->border.pixel, GXcopy);
+ return;
+ }
+#if 0
+ else
+ {
+ pTile = pWin->border.pixmap;
+ if (tridentPatternDimOk (pTile->drawable.width) &&
+ tridentPatternDimOk (pTile->drawable.height))
+ {
+ tridentFillBoxTiled ((DrawablePtr)pWin,
+ (int)REGION_NUM_RECTS(pRegion),
+ REGION_RECTS(pRegion),
+ pTile,
+ pWin->drawable.x, pWin->drawable.y, GXcopy);
+ return;
+ }
+ }
+#endif
+ break;
+ }
+ fbPaintWindow (pWin, pRegion, what);
+}
+
+Bool
+tridentDrawInit (ScreenPtr pScreen)
+{
+ /*
+ * Replace various fb screen functions
+ */
+ pScreen->CreateGC = tridentCreateGC;
+ pScreen->CopyWindow = tridentCopyWindow;
+ pScreen->PaintWindowBackground = tridentPaintWindow;
+ pScreen->PaintWindowBorder = tridentPaintWindow;
+
+ return TRUE;
+}
+
+void
+tridentDrawEnable (ScreenPtr pScreen)
+{
+ SetupTrident(pScreen);
+ CARD32 cmd;
+ CARD32 base;
+ CARD16 stride;
+ CARD32 format;
+ int tries;
+
+ stride = pScreenPriv->screen->pixelStride;
+ switch (pScreenPriv->screen->bitsPerPixel) {
+ case 8:
+ format = COP_DEPTH_8;
+ break;
+ case 16:
+ format = COP_DEPTH_16;
+ break;
+ case 24:
+ format = COP_DEPTH_24_32;
+ break;
+ case 32:
+ format = COP_DEPTH_24_32;
+ break;
+ }
+ /*
+ * compute a few things which will be set every time the
+ * accelerator is used; this avoids problems with APM
+ */
+ tridentc->cop_depth = COP_MULTI_DEPTH | format;
+ tridentc->cop_stride = COP_MULTI_STRIDE | (stride << 16) | (stride);
+
+#define NUM_TRIES 100000
+ for (tries = 0; tries < NUM_TRIES; tries++)
+ if (!(cop->status & COP_STATUS_BUSY))
+ break;
+ if (cop->status & COP_STATUS_BUSY)
+ FatalError ("Can't initialize graphics coprocessor");
+ cop->multi = COP_MULTI_CLIP_TOP_LEFT;
+ cop->multi = COP_MULTI_MASK | 0;
+ cop->src_offset = 0;
+ cop->dst_offset = 0;
+ cop->z_offset = 0;
+ cop->clip_bottom_right = 0x0fff0fff;
+
+ _tridentInit(cop,tridentc);
+ _tridentSetSolidRect(cop, pScreen->blackPixel, GXcopy, cmd);
+ _tridentRect (cop, 0, 0,
+ pScreenPriv->screen->width, pScreenPriv->screen->height,
+ cmd);
+ _tridentWaitIdleEmpty (cop);
+}
+
+void
+tridentDrawDisable (ScreenPtr pScreen)
+{
+}
+
+void
+tridentDrawFini (ScreenPtr pScreen)
+{
+}
diff --git a/hw/kdrive/trident/tridentdraw.h b/hw/kdrive/trident/tridentdraw.h
new file mode 100644
index 000000000..5fa64d2a7
--- /dev/null
+++ b/hw/kdrive/trident/tridentdraw.h
@@ -0,0 +1,63 @@
+/*
+ * $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: $ */
+
+#ifndef _TRIDENTDRAW_H_
+#define _TRIDENTDRAW_H_
+
+#define SetupTrident(s) KdScreenPriv(s); \
+ tridentCardInfo(pScreenPriv); \
+ Cop *cop = tridentc->cop
+
+#define _tridentInit(cop,tridentc) { \
+ if ((cop)->status == 0xffffffff) tridentSetMMIO(tridentc); \
+ (cop)->multi = (tridentc)->cop_depth; \
+ (cop)->multi = (tridentc)->cop_stride; \
+} \
+
+#define _tridentSetSolidRect(cop,pix,alu,cmd) {\
+ cop->multi = COP_MULTI_PATTERN; \
+ cop->multi = COP_MULTI_ROP | tridentRop[alu]; \
+ cop->fg = (pix); \
+ cmd = COP_OP_BLT | COP_SCL_OPAQUE | COP_OP_ROP | COP_OP_FG; \
+}
+
+#define _tridentRect(cop,x1,y1,x2,y2,cmd) { \
+ (cop)->dst_start_xy = TRI_XY (x1,y1); \
+ (cop)->dst_end_xy = TRI_XY(x2,y2); \
+ (cop)->command = (cmd); \
+}
+
+#define COP_STATUS_BUSY (COP_STATUS_BE_BUSY | \
+ COP_STATUS_DPE_BUSY | \
+ COP_STATUS_MI_BUSY | \
+ COP_STATUS_FIFO_BUSY)
+
+#define _tridentWaitDone(cop) while ((cop)->status & COP_STATUS_BUSY)
+
+#define _tridentWaitIdleEmpty(cop) _tridentWaitDone(cop);
+
+#define sourceInvarient(alu) (((alu) & 3) == (((alu) >> 2) & 3))
+
+#endif
diff --git a/hw/kdrive/trident/tridentstub.c b/hw/kdrive/trident/tridentstub.c
new file mode 100644
index 000000000..b0005e7c7
--- /dev/null
+++ b/hw/kdrive/trident/tridentstub.c
@@ -0,0 +1,54 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999 SuSE, Inc.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+/* $XFree86: $ */
+
+#include "trident.h"
+
+void
+InitCard (char *name)
+{
+ KdCardAttr attr;
+
+ if (LinuxFindPci (0x1023, 0x9525, 0, &attr))
+ KdCardInfoAdd (&tridentFuncs, &attr, 0);
+}
+
+void
+InitOutput (ScreenInfo *pScreenInfo, int argc, char **argv)
+{
+ KdInitOutput (pScreenInfo, argc, argv);
+}
+
+void
+InitInput (int argc, char **argv)
+{
+ KdInitInput (&Ps2MouseFuncs, &LinuxKeyboardFuncs);
+}
+
+void
+OsVendorInit (void)
+{
+ KdOsInit (&LinuxFuncs);
+}
diff --git a/hw/kdrive/trio/Imakefile b/hw/kdrive/trio/Imakefile
new file mode 100644
index 000000000..0e34e706d
--- /dev/null
+++ b/hw/kdrive/trio/Imakefile
@@ -0,0 +1,21 @@
+XCOMM $XConsortium: Imakefile /main/10 1996/12/02 10:20:33 lehors $
+XCOMM $XFree86: xc/programs/Xserver/hw/nvfb/Imakefile,v 3.8 1996/12/23 06:30:19 dawes Exp $
+#include <Server.tmpl>
+
+SRCS = s3.c s3clock.c s3cmap.c s3curs.c s3draw.c s3gc.c s3stub.c
+
+OBJS = s3.o s3clock.o s3cmap.o s3curs.o s3draw.o s3gc.o s3stub.o
+
+INCLUDES = -I.. -I. -I$(XBUILDINCDIR) -I$(FONTINCSRC) \
+ -I../../../fb -I../../../mi -I../../../include -I../../../os \
+ -I$(EXTINCSRC) -I$(XINCLUDESRC)
+
+DEFINES = -DS3_TRIO
+
+NormalLibraryObjectRule()
+NormalLibraryTarget(trio,$(OBJS))
+DependTarget()
+
+LinkSourceFile(s3draw.h,../savage)
+LinkSourceFile(s3draw.c,../savage)
+LinkSourceFile(s3gc.c,../savage)
diff --git a/hw/kdrive/trio/s3.c b/hw/kdrive/trio/s3.c
new file mode 100644
index 000000000..3233173cb
--- /dev/null
+++ b/hw/kdrive/trio/s3.c
@@ -0,0 +1,1298 @@
+/*
+ * $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 "s3.h"
+
+#define REGISTERS_OFFSET (0x1000000)
+#define PACKED_OFFSET (0x8100)
+
+/*
+ * Clock synthesis:
+ *
+ * f_out = f_ref * ((M + 2) / ((N + 2) * (1 << R)))
+ *
+ * Constraints:
+ *
+ * 1. 135MHz <= f_ref * ((M + 2) / (N + 2)) <= 270 MHz
+ * 2. N >= 1
+ *
+ * Vertical refresh rate = clock / ((hsize + hblank) * (vsize + vblank))
+ * Horizontal refresh rate = clock / (hsize + hblank)
+ */
+
+#define DEFAULT_S3_TIMING 1
+
+S3Timing s3Timings[] = {
+ /* FP BP BLANK */
+ /* M N R blank bios5 */
+ { 640, 480, 60,
+ 16, 48, 160, /* horizontal 31.321 KHz */
+ 10, 33, 45, /* vertical 59.568 Hz */
+ 26, 0, 3, /* pixel 25.057 MHz */
+ },
+
+ { 800, 600, 85,
+ 32, 152, 248, /* horizontal 53.673 KHz */
+ 1, 27, 31, /* vertical 85.060 Hz */
+ 108, 5, 2, /* pixel 56.249 MHz */
+ },
+ { 800, 600, 75,
+ 16, 160, 256, /* horizontal 46.891 KHz */
+ 1, 21, 25, /* vertical 75.025 Hz */
+ 81, 4, 2, /* pixel 49.516 MHz */
+ },
+ { 800, 600, 72,
+ 56, 64, 240, /* horizontal 48.186 KHz */
+ 37, 23, 66, /* vertical 72.351 Hz */
+ 26, 0, 2, /* pixel 50.113 MHz */
+ },
+
+ { 1024, 768, 85,
+ 48, 208, 352, /* horizontal 68.676 KHz */
+ 1, 36, 40, /* vertical 84.996 Hz */
+ 64, 3, 1, /* pixel 94.499 MHz */
+ },
+ { 1024, 768, 75,
+ 16, 176, 288, /* horizontal 60.022 KHz */
+ 1, 28, 32, /* vertical 75.028 Hz */
+ 20, 0, 1, /* pixel 78.749 MHz */
+ },
+ { 1024, 768, 70,
+ 24, 144, 304, /* horizontal 56.604 KHz */
+ 3, 29, 38, /* vertical 70.227 Hz */
+ 40, 2, 1, /* pixel 75.170 MHz */
+ },
+ { 1024, 768, 66,
+ 24, 144, 304, /* horizontal 53.234 KHz */
+ 3, 29, 38, /* vertical 66.047 Hz */
+ 77, 6, 1, /* pixel 70.695 MHz */
+ },
+
+ { 1152, 900, 85,
+ 48, 208, 384, /* horizontal 79.900 KHz */
+ 1, 32, 38, /* vertical 85.181 Hz */
+ 118, 5, 1, /* pixel 122.726 MHz */
+ },
+ { 1152, 900, 75,
+ 32, 208, 384, /* horizontal 70.495 Khz */
+ 1, 32, 38, /* vertical 75.154 Hz */
+ 119, 6, 1, /* pixel 108.280 MHz */
+ },
+ { 1152, 900, 70,
+ 32, 208, 384, /* horizontal 65.251 KHz */
+ 2, 32, 38, /* vertical 69.564 Hz */
+ 12, 0, 0, /* pixel 100.226 MHz */
+ },
+ { 1152, 900, 66,
+ 32, 208, 384, /* horizontal 61.817 KHz */
+ 1, 32, 38, /* vertical 65.903 Hz */
+ 124, 17, 0, /* pixel 94.951 MHz */
+ },
+ { 1280, 1024, 85,
+ 16, 248, 416, /* horizontal 90.561 KHz */
+ 1, 40, 45, /* vertical 84.717 Hz */
+ 116, 9, 0, /* pixel 153.593 MHz */
+ },
+ { 1280, 1024, 75,
+ 16, 248, 408, /* horizontal 80.255 KHz */
+ 1, 38, 42, /* vertical 75.285 Hz */
+ 111, 4, 1, /* pixel 134.828 MHz */
+ },
+ { 1280, 1024, 70,
+ 32, 248, 400, /* horizontal 74.573 KHz */
+ 0, 36, 39, /* vertical 70.153 Hz */
+ 68, 2, 1, /* pixel 125.283 MHz */
+ },
+ { 1280, 1024, 66,
+ 32, 248, 400, /* horizontal 70.007 KHz */
+ 0, 36, 39, /* vertical 65.858 Hz */
+ 113, 5, 1, /* pixel 117.612 MHz */
+ },
+
+ { 1600, 1200, 85,
+ 64, 304, 560, /* horizontal 106.059 KHz */
+ 1, 46, 50, /* vertical 84.847 Hz */
+ 126, 6, 0, /* pixel 229.088 MHz */
+ },
+ { 1600, 1200, 75,
+ 64, 304, 560, /* horizontal 93.748 KHz */
+ 1, 46, 50, /* vertical 74.999 Hz */
+ 97, 5, 0, /* pixel 202.497 MHz */
+ },
+ { 1600, 1200, 70,
+ 56, 304, 588, /* horizontal 87.524 KHz */
+ 1, 46, 50, /* vertical 70.019 Hz */
+ 105, 6, 0, /* pixel 191.503 MHz */
+ },
+ { 1600, 1200, 65,
+ 56, 308, 524, /* horizontal 80.050 KHz */
+ 1, 38, 42, /* vertical 64.453 Hz */
+ 93, 6, 0, /* pixel 170.026 MHz */
+ },
+};
+
+#define NUM_S3_TIMINGS (sizeof (s3Timings) / sizeof (s3Timings[0]))
+
+CARD8
+_s3ReadIndexRegister (volatile CARD8 *base, CARD8 index)
+{
+ CARD8 ret;
+ *base = index;
+ ret = *(base + 1);
+ DRAW_DEBUG ((DEBUG_CRTC, " 0x%3x 0x%02x -> 0x%02x",
+ ((int) base) & 0xfff, index, ret));
+ return ret;
+}
+
+void
+_s3WriteIndexRegister (volatile CARD8 *base, CARD8 index, CARD8 value)
+{
+ DRAW_DEBUG ((DEBUG_CRTC, " 0x%3x 0x%02x <- 0x%02x",
+ ((int) base) & 0xfff, index, value));
+ *base = index;
+ *(base + 1) = value;
+}
+
+/*
+ * Map the S3 card and detect its configuration. Do not touch the card
+ */
+
+static void
+_s3LoadCrtc (S3Ptr s3, S3Crtc *crtc)
+{
+ crtc->h_total_0_7 = GetCrtc (s3, 0x00);
+ crtc->h_display_end_0_7 = GetCrtc (s3, 0x01);
+ crtc->h_blank_start_0_7 = GetCrtc (s3, 0x02);
+ crtc->_h_blank_end = GetCrtc (s3, 0x03);
+ crtc->h_sync_start_0_7 = GetCrtc (s3, 0x04);
+ crtc->_h_sync_end = GetCrtc (s3, 0x05);
+ crtc->v_total_0_7 = GetCrtc (s3, 0x06);
+ crtc->crtc_overflow = GetCrtc (s3, 0x07);
+ crtc->preset_row_scan = GetCrtc (s3, 0x08);
+ crtc->_max_scan_line = GetCrtc (s3, 0x09);
+
+ crtc->start_address_8_15 = GetCrtc (s3, 0x0c);
+ crtc->start_address_0_7 = GetCrtc (s3, 0x0d);
+
+ crtc->v_retrace_start_0_7 = GetCrtc (s3, 0x10);
+ crtc->_v_retrace_end = GetCrtc (s3, 0x11);
+ crtc->v_display_end_0_7 = GetCrtc (s3, 0x12);
+ crtc->screen_off_0_7 = GetCrtc (s3, 0x13);
+
+ crtc->v_blank_start_0_7 = GetCrtc (s3, 0x15);
+ crtc->v_blank_end_0_7 = GetCrtc (s3, 0x16);
+
+ crtc->line_compare_0_7 = GetCrtc (s3, 0x18);
+
+ crtc->memory_configuration = GetCrtc (s3, 0x31);
+
+ crtc->misc_1 = GetCrtc (s3, 0x3a);
+ crtc->h_start_fifo_fetch_0_7 = GetCrtc (s3, 0x3b);
+
+ crtc->mode_control = GetCrtc (s3, 0x42);
+
+ crtc->hardware_cursor_mode = GetCrtc (s3, 0x45);
+ crtc->cursor_address_8_15 = GetCrtc (s3, 0x4C);
+ crtc->cursor_address_0_7 = GetCrtc (s3, 0x4D);
+
+ crtc->extended_system_control_1 = GetCrtc (s3, 0x50);
+ crtc->extended_system_control_2 = GetCrtc (s3, 0x51);
+
+ crtc->extended_memory_control = GetCrtc (s3, 0x53);
+
+ crtc->extended_ramdac_control = GetCrtc (s3, 0x55);
+
+ crtc->extended_horizontal_overflow = GetCrtc (s3, 0x5d);
+ crtc->extended_vertical_overflow = GetCrtc (s3, 0x5e);
+
+ crtc->l_parm_0_7 = GetCrtc (s3, 0x62);
+
+ crtc->extended_misc_control = GetCrtc (s3, 0x65);
+
+ crtc->extended_misc_control_2 = GetCrtc (s3, 0x67);
+
+ crtc->configuration_3 = GetCrtc (s3, 0x68);
+
+ crtc->extended_system_control_3 = GetCrtc (s3, 0x69);
+
+ crtc->extended_bios_5 = GetCrtc (s3, 0x6d);
+
+ crtc->extended_sequencer_b = GetSrtc (s3, 0x0b);
+ crtc->extended_sequencer_d = GetSrtc (s3, 0x0d);
+ crtc->dclk_value_low = GetSrtc (s3, 0x12);
+ crtc->dclk_value_high = GetSrtc (s3, 0x13);
+ crtc->control_2 = GetSrtc (s3, 0x15);
+ crtc->ramdac_control = GetSrtc (s3, 0x18);
+
+ crtc->dclk_value_low_savage = GetSrtc (s3, 0x36);
+ crtc->dclk_pll_m0_savage_0_7 = GetSrtc (s3, 0x37);
+ crtc->dclk_pll_m1_savage_0_7 = GetSrtc (s3, 0x38);
+ crtc->extended_seq_39 = GetSrtc (s3, 0x39);
+
+ fprintf (stderr, "SR1A 0x%x SR1B 0x%x\n",
+ GetSrtc (s3, 0x1a),
+ GetSrtc (s3, 0x1b));
+ fprintf (stderr, "SR36 0x%x SR37 0x%x SR38 0x%x SR39 0x%x\n",
+ GetSrtc (s3, 0x36),
+ GetSrtc (s3, 0x37),
+ GetSrtc (s3, 0x38),
+ GetSrtc (s3, 0x39));
+/* combine values */
+
+ switch (crtc_ge_screen_width(crtc)) {
+ case 0:
+ if (crtc->enable_two_page)
+ crtc->ge_screen_pitch = 2048;
+ else
+ crtc->ge_screen_pitch = 1024;
+ break;
+ case 1:
+ crtc->ge_screen_pitch = 640;
+ break;
+ case 2:
+ /* ignore magic 1600x1200x4 mode */
+ crtc->ge_screen_pitch = 800;
+ break;
+ case 3:
+ crtc->ge_screen_pitch = 1280;
+ break;
+ case 4:
+ crtc->ge_screen_pitch = 1152;
+ break;
+ case 5:
+ crtc->ge_screen_pitch = 0; /* reserved */
+ break;
+ case 6:
+ crtc->ge_screen_pitch = 1600;
+ break;
+ case 7:
+ crtc->ge_screen_pitch = 0; /* reserved */
+ break;
+ }
+ switch (crtc->pixel_length) {
+ case 0:
+ crtc->bits_per_pixel = 8;
+ crtc->pixel_width = (crtc_h_display_end(crtc) + 1) * 8;
+ break;
+ case 1:
+ crtc->bits_per_pixel = 16;
+ crtc->pixel_width = (crtc_h_display_end(crtc) + 1) * 4;
+ break;
+ case 3:
+ crtc->bits_per_pixel = 32;
+ crtc->pixel_width = (crtc_h_display_end(crtc) + 1) * 8;
+ break;
+ }
+ crtc->double_pixel_mode = 0;
+ switch (crtc->color_mode) {
+ case 0x0:
+ crtc->depth = 8; break;
+ case 0x1:
+ crtc->depth = 8; crtc->double_pixel_mode = 1; break;
+ case 0x3:
+ crtc->depth = 15; break;
+ case 0x5:
+ crtc->depth = 16; break;
+ case 0x7:
+ crtc->depth = 24; break; /* unused */
+ case 0xd:
+ crtc->depth = 24; break;
+ }
+}
+
+static void
+_s3SetBlank (S3Ptr s3, Bool blank)
+{
+ CARD8 clock_mode;
+
+ DRAW_DEBUG ((DEBUG_S3INIT, "3c4 at 0x%x\n", &s3->crt_vga_3c4));
+ clock_mode = _s3ReadIndexRegister (&s3->crt_vga_3c4, 0x01);
+ if (blank)
+ clock_mode |= 0x20;
+ else
+ clock_mode &= ~0x20;
+ _s3WaitVRetrace (s3);
+ _s3WriteIndexRegister (&s3->crt_vga_3c4, 0x01, clock_mode);
+ DRAW_DEBUG ((DEBUG_S3INIT, "blank is set to 0x%x", clock_mode));
+}
+
+static void
+_s3SetDepth (S3Ptr s3, S3Crtc *crtc)
+{
+ CARD8 save_3c2;
+ _s3SetBlank (s3, TRUE);
+ PutCrtc(s3, 0x38, 0x48);
+ PutCrtc(s3, 0x39, 0xA0);
+ PutCrtc(s3, 0x00, crtc->h_total_0_7);
+ PutCrtc(s3, 0x01, crtc->h_display_end_0_7);
+ PutCrtc(s3, 0x02, crtc->h_blank_start_0_7);
+ PutCrtc(s3, 0x03, crtc->_h_blank_end);
+ PutCrtc(s3, 0x04, crtc->h_sync_start_0_7);
+ PutCrtc(s3, 0x05, crtc->_h_sync_end);
+ PutCrtc(s3, 0x06, crtc->v_total_0_7);
+ PutCrtc(s3, 0x07, crtc->crtc_overflow);
+ PutCrtc(s3, 0x09, crtc->_max_scan_line);
+ PutCrtc(s3, 0x0c, crtc->start_address_8_15);
+ PutCrtc(s3, 0x0d, crtc->start_address_0_7);
+ PutCrtc(s3, 0x10, crtc->v_retrace_start_0_7);
+ PutCrtc(s3, 0x11, crtc->_v_retrace_end);
+ PutCrtc(s3, 0x12, crtc->v_display_end_0_7);
+ PutCrtc(s3, 0x13, crtc->screen_off_0_7);
+ PutCrtc(s3, 0x15, crtc->v_blank_start_0_7);
+ PutCrtc(s3, 0x16, crtc->v_blank_end_0_7);
+ PutCrtc(s3, 0x18, crtc->line_compare_0_7);
+ PutCrtc(s3, 0x31, crtc->memory_configuration);
+ PutCrtc(s3, 0x3a, crtc->misc_1);
+ PutCrtc(s3, 0x3b, crtc->h_start_fifo_fetch_0_7);
+ PutCrtc(s3, 0x42, crtc->mode_control);
+ PutCrtc(s3, 0x45, crtc->hardware_cursor_mode);
+ PutCrtc(s3, 0x4c, crtc->cursor_address_8_15);
+ PutCrtc(s3, 0x4d, crtc->cursor_address_0_7);
+ PutCrtc(s3, 0x50, crtc->extended_system_control_1);
+ PutCrtc(s3, 0x51, crtc->extended_system_control_2);
+ PutCrtc(s3, 0x53, crtc->extended_memory_control);
+ PutCrtc(s3, 0x55, crtc->extended_ramdac_control);
+ PutCrtc(s3, 0x5d, crtc->extended_horizontal_overflow);
+ PutCrtc(s3, 0x5e, crtc->extended_vertical_overflow);
+ PutCrtc(s3, 0x62, crtc->l_parm_0_7);
+ PutCrtc(s3, 0x65, crtc->extended_misc_control);
+ PutCrtc(s3, 0x67, crtc->extended_misc_control_2);
+ PutCrtc(s3, 0x68, crtc->configuration_3);
+ PutCrtc(s3, 0x69, crtc->extended_system_control_3);
+ PutCrtc(s3, 0x6d, crtc->extended_bios_5);
+ PutCrtc(s3, 0x39, 0x00);
+ PutCrtc(s3, 0x38, 0x00);
+ PutSrtc(s3, 0x0b, crtc->extended_sequencer_b);
+ PutSrtc(s3, 0x0d, crtc->extended_sequencer_d);
+ /*
+ * Move new dclk/mclk values into PLL
+ */
+ save_3c2 = s3->crt_vga_3cc;
+ DRAW_DEBUG ((DEBUG_S3INIT, "save_3c2 0x%x", save_3c2));
+ s3->crt_vga_3c2 = 0x0f;
+
+ PutSrtc (s3, 0x36, crtc->dclk_value_low_savage);
+ PutSrtc (s3, 0x37, crtc->dclk_pll_m0_savage_0_7);
+ PutSrtc (s3, 0x38, crtc->dclk_pll_m1_savage_0_7);
+ PutSrtc (s3, 0x39, crtc->extended_seq_39);
+ PutSrtc(s3, 0x12, crtc->dclk_value_low);
+ PutSrtc(s3, 0x13, crtc->dclk_value_high);
+
+ DRAW_DEBUG ((DEBUG_S3INIT, "Set PLL load enable, frobbing clk_load..."));
+ crtc->dfrq_en = 1;
+ PutSrtc(s3, 0x15, crtc->control_2);
+ PutSrtc(s3, 0x18, crtc->ramdac_control);
+
+ DRAW_DEBUG ((DEBUG_S3INIT, "Clk load frobbed, restoring 3c2 to 0x%x", save_3c2));
+ s3->crt_vga_3c2 = save_3c2;
+
+ DRAW_DEBUG ((DEBUG_S3INIT, "Enabling display"));
+ _s3SetBlank (s3, FALSE);
+}
+
+void
+_s3RestoreCrtc (S3Ptr s3, S3Crtc *crtc)
+{
+ _s3SetDepth (s3, crtc);
+}
+
+s3Reset (S3CardInfo *s3c)
+{
+ S3Ptr s3 = s3c->s3;
+ S3Save *save = &s3c->save;
+ CARD8 *cursor_base;
+
+ LockS3 (s3c);
+
+ _s3UnlockExt (s3);
+
+ _s3RestoreCrtc (s3, &save->crtc);
+
+ /* set foreground */
+ /* Reset cursor color stack pointers */
+ (void) GetCrtc(s3, 0x45);
+ PutCrtc(s3, 0x4a, save->cursor_fg);
+ /* XXX for deeper screens? */
+
+ /* set background */
+ /* Reset cursor color stack pointers */
+ (void) GetCrtc(s3, 0x45);
+ PutCrtc(s3, 0x4b, save->cursor_bg);
+
+ _s3LockExt (s3);
+
+ /* graphics engine state */
+ s3->alt_mix = save->alt_mix;
+ s3->write_mask = save->write_mask;
+ s3->fg = save->fg;
+ s3->bg = save->bg;
+ /* XXX should save and restore real values? */
+ s3->scissors_tl = 0x00000000;
+ s3->scissors_br = 0x0fff0fff;
+
+ _s3WriteIndexRegister (&s3->crt_vga_3c4, 0x01, save->clock_mode);
+ PutSrtc(s3, 0x08, save->locksrtc);
+ PutCrtc(s3, 0x39, save->lock2);
+ PutCrtc(s3, 0x38, save->lock1);
+
+ UnlockS3 (s3c);
+}
+
+void
+s3Save (S3CardInfo *s3c)
+{
+ S3Ptr s3 = s3c->s3;
+ S3Save *save = &s3c->save;
+ S3Crtc newCrtc;
+ CARD8 t1, t2;
+ CARD8 *cursor_base;
+
+ LockS3 (s3c);
+
+ save->alt_mix = s3->alt_mix;
+ save->write_mask = s3->write_mask;
+ save->fg = s3->fg;
+ save->bg = s3->bg;
+
+ save->lock1 = GetCrtc(s3, 0x38);
+ save->lock2 = GetCrtc(s3, 0x39);
+ save->locksrtc = GetSrtc (s3, 0x08);
+
+ /* unlock srtc registers to read them */
+ PutSrtc (s3, 0x08, 0x06);
+
+ save->clock_mode = _s3ReadIndexRegister (&s3->crt_vga_3c4, 0x01);
+
+ _s3UnlockExt (s3);
+ save->cursor_fg = GetCrtc(s3, 0x4a);
+ save->cursor_bg = GetCrtc(s3, 0x4b);
+
+ _s3LoadCrtc (s3, &save->crtc);
+
+ _s3LockExt (s3);
+
+ UnlockS3 (s3c);
+}
+Bool
+s3CardInit (KdCardInfo *card)
+{
+ S3CardInfo *s3c;
+ S3Ptr s3;
+ int size;
+ CARD8 *registers;
+ CARD32 s3FrameBuffer;
+ CARD32 s3Registers;
+ CARD8 *temp_buffer;
+ CARD32 max_memory;
+
+ DRAW_DEBUG ((DEBUG_S3INIT, "s3CardInit"));
+ s3c = (S3CardInfo *) xalloc (sizeof (S3CardInfo));
+ if (!s3c)
+ {
+ DRAW_DEBUG ((DEBUG_FAILURE, "can't alloc s3 card info"));
+ goto bail0;
+ }
+
+ memset (s3c, '\0', sizeof (S3CardInfo));
+
+ card->driver = s3c;
+
+ if (card->attr.naddr > 1)
+ {
+ s3FrameBuffer = card->attr.address[1];
+ s3Registers = card->attr.address[0];
+ max_memory = 32 * 1024 * 1024;
+ s3c->savage = TRUE;
+ }
+ else
+ {
+ s3FrameBuffer = card->attr.address[0];
+ s3Registers = s3FrameBuffer + REGISTERS_OFFSET;
+ max_memory = 4 * 1024 * 1024;
+ s3c->savage = FALSE;
+ }
+
+ fprintf (stderr, "S3 at 0x%x/0x%x\n", s3Registers, s3FrameBuffer);
+ registers = KdMapDevice (s3Registers,
+ sizeof (S3) + PACKED_OFFSET);
+ if (!registers)
+ {
+ ErrorF ("Can't map s3 device\n");
+ goto bail2;
+ }
+ s3 = (S3Ptr) (registers + PACKED_OFFSET);
+ s3c->registers = registers;
+ s3c->s3 = s3;
+
+#if 0
+ s3->crt_vga_3c3 = 1; /* wake up part from deep sleep */
+ s3->crt_vga_3c2 = 0x01 | 0x02 | 0x0c;
+
+ s3->crt_vga_3c4 = 0x58;
+ s3->crt_vga_3c5 = 0x10 | 0x3;
+#endif
+
+ /*
+ * Can't trust S3 register value for frame buffer amount, must compute
+ */
+ temp_buffer = KdMapDevice (s3FrameBuffer, max_memory);
+
+ s3c->memory = KdFrameBufferSize (temp_buffer, max_memory);
+
+ fprintf (stderr, "Frame buffer 0x%x\n", s3c->memory);
+
+ DRAW_DEBUG ((DEBUG_S3INIT, "Detected frame buffer %d", s3c->memory));
+
+ KdUnmapDevice (temp_buffer, 4096 * 1024);
+
+ if (!s3c->memory)
+ {
+ ErrorF ("Can't detect s3 frame buffer at 0x%x\n", s3FrameBuffer);
+ goto bail3;
+ }
+
+ s3c->frameBuffer = KdMapDevice (s3FrameBuffer, s3c->memory);
+ if (!s3c->frameBuffer)
+ {
+ ErrorF ("Can't map s3 frame buffer\n");
+ goto bail3;
+ }
+
+ card->driver = s3c;
+
+ return TRUE;
+bail3:
+ KdUnmapDevice ((void *) s3, sizeof (S3));
+bail2:
+bail1:
+ xfree (s3c);
+bail0:
+ return FALSE;
+}
+
+Bool
+s3ScreenInit (KdScreenInfo *screen)
+{
+ KdCardInfo *card = screen->card;
+ S3CardInfo *s3c = (S3CardInfo *) card->driver;
+ S3ScreenInfo *s3s;
+ int screen_size;
+ int memory;
+ int requested_memory;
+ int v_total, h_total;
+ int byte_width;
+ int pixel_width;
+ int m, n, r;
+ int i;
+ S3Timing *t;
+
+ DRAW_DEBUG ((DEBUG_S3INIT, "s3ScreenInit"));
+ s3s = (S3ScreenInfo *) xalloc (sizeof (S3ScreenInfo));
+ if (!s3s)
+ return FALSE;
+
+ memset (s3s, '\0', sizeof (S3ScreenInfo));
+
+ if (!screen->width || !screen->height)
+ {
+ screen->width = 800;
+ screen->height = 600;
+ screen->rate = 72;
+ }
+ if (!screen->depth)
+ screen->depth = 8;
+
+ DRAW_DEBUG ((DEBUG_S3INIT, "Requested parameters %dx%dx%d",
+ screen->width, screen->height, screen->rate));
+ for (i = 0, t = s3Timings; i < NUM_S3_TIMINGS; i++, t++)
+ {
+ DRAW_DEBUG ((DEBUG_S3INIT, "Available parameters %dx%dx%d",
+ t->horizontal, t->vertical, t->rate));
+ if (t->horizontal >= screen->width &&
+ t->vertical >= screen->height &&
+ (!screen->rate || t->rate <= screen->rate))
+ break;
+ }
+ if (i == NUM_S3_TIMINGS)
+ t = &s3Timings[DEFAULT_S3_TIMING];
+ screen->rate = t->rate;
+ screen->width = t->horizontal;
+ screen->height = t->vertical;
+#if 0
+ s3GetClock (t, &m, &n, &r,
+ s3c->savage ? 511 : 127,
+ s3c->savage ? 127 : 31,
+ s3c->savage ? 4 : 3);
+#else
+ s3GetClock (t, &m, &n, &r, 127, 31, 3);
+#endif
+#if 1
+ fprintf (stderr, "computed %d,%d,%d (%d) provided %d,%d,%d (%d)\n",
+ m, n, r, S3_CLOCK(m,n,r),
+ t->dac_m, t->dac_n, t->dac_r,
+ S3_CLOCK(t->dac_m, t->dac_n, t->dac_r));
+#endif
+ /*
+ * Can only operate in pixel-doubled mode at 8 bits per pixel
+ */
+ if (s3c->savage)
+ {
+ if (screen->depth > 16 && S3_CLOCK(m,n,r) > S3_MAX_CLOCK)
+ screen->depth = 16;
+ }
+ else
+ {
+ if (screen->depth > 8 && S3_CLOCK(m,n,r) > S3_MAX_CLOCK)
+ screen->depth = 8;
+ }
+
+ for (;;)
+ {
+ if (screen->depth >= 24)
+ {
+ screen->depth = 24;
+ screen->bitsPerPixel = 32;
+ }
+ else if (screen->depth >= 16)
+ {
+ screen->depth = 16;
+ screen->bitsPerPixel = 16;
+ }
+ else if (screen->depth >= 15)
+ {
+ screen->depth = 15;
+ screen->bitsPerPixel = 16;
+ }
+ else
+ {
+ screen->depth = 8;
+ screen->bitsPerPixel = 8;
+ }
+
+ /* Normalize width to supported values */
+
+ if (screen->width >= 1600)
+ screen->width = 1600;
+ else if (screen->width >= 1280)
+ screen->width = 1280;
+ else if (screen->width >= 1152)
+ screen->width = 1152;
+ else if (screen->width >= 1024)
+ screen->width = 1024;
+ else if (screen->width >= 800)
+ screen->width = 800;
+ else
+ screen->width = 640;
+
+ byte_width = screen->width * (screen->bitsPerPixel >> 3);
+ pixel_width = screen->width;
+ screen->pixelStride = pixel_width;
+ screen->byteStride = byte_width;
+
+ screen_size = byte_width * screen->height;
+
+ if (screen_size <= s3c->memory)
+ break;
+
+ /*
+ * Fix requested depth and geometry until it works
+ */
+ if (screen->depth > 16)
+ screen->depth = 16;
+ else if (screen->depth > 8)
+ screen->depth = 8;
+ else if (screen->width > 1152)
+ {
+ screen->width = 1152;
+ screen->height = 900;
+ }
+ else if (screen->width > 1024)
+ {
+ screen->width = 1024;
+ screen->height = 768;
+ }
+ else if (screen->width > 800)
+ {
+ screen->width = 800;
+ screen->height = 600;
+ }
+ else if (screen->width > 640)
+ {
+ screen->width = 640;
+ screen->height = 480;
+ }
+ else
+ {
+ xfree (s3s);
+ return FALSE;
+ }
+ }
+
+ memory = s3c->memory - screen_size;
+
+ /*
+ * Stick frame buffer at start of memory
+ */
+ screen->frameBuffer = s3c->frameBuffer;
+
+ /*
+ * Stick cursor at end of memory
+ */
+ if (memory >= 2048)
+ {
+ s3s->cursor_base = s3c->frameBuffer + (s3c->memory - 2048);
+ memory -= 2048;
+ }
+ else
+ s3s->cursor_base = 0;
+
+ /*
+ * Use remaining memory for off-screen storage, but only use
+ * one piece (either right or bottom).
+ */
+ if (memory >= byte_width * S3_TILE_SIZE)
+ {
+ s3s->offscreen = s3c->frameBuffer + screen_size;
+ s3s->offscreen_x = 0;
+ s3s->offscreen_y = screen_size / byte_width;
+ s3s->offscreen_width = pixel_width;
+ s3s->offscreen_height = memory / byte_width;
+ memory -= s3s->offscreen_height * byte_width;
+ }
+ else if (pixel_width - screen->width >= S3_TILE_SIZE)
+ {
+ s3s->offscreen = s3c->frameBuffer + screen->width;
+ s3s->offscreen_x = screen->width;
+ s3s->offscreen_y = 0;
+ s3s->offscreen_width = pixel_width - screen->width;
+ s3s->offscreen_height = screen->height;
+ }
+ else
+ s3s->offscreen = 0;
+
+ DRAW_DEBUG ((DEBUG_S3INIT, "depth %d bits %d", screen->depth, screen->bitsPerPixel));
+
+ DRAW_DEBUG ((DEBUG_S3INIT, "Screen size %dx%d memory %d",
+ screen->width, screen->height, s3c->memory));
+ DRAW_DEBUG ((DEBUG_S3INIT, "frame buffer 0x%x cursor 0x%x offscreen 0x%x",
+ s3c->frameBuffer, s3s->cursor_base, s3s->offscreen));
+ DRAW_DEBUG ((DEBUG_S3INIT, "offscreen %dx%d+%d+%d",
+ s3s->offscreen_width, s3s->offscreen_height,
+ s3s->offscreen_x, s3s->offscreen_y));
+
+ switch (screen->depth) {
+ case 8:
+ screen->visuals = ((1 << StaticGray) |
+ (1 << GrayScale) |
+ (1 << StaticColor) |
+ (1 << PseudoColor) |
+ (1 << TrueColor) |
+ (1 << DirectColor));
+ screen->blueMask = 0x00;
+ screen->greenMask = 0x00;
+ screen->redMask = 0x00;
+ break;
+ case 15:
+ screen->visuals = (1 << TrueColor);
+ screen->blueMask = 0x001f;
+ screen->greenMask = 0x03e0;
+ screen->redMask = 0x7c00;
+ break;
+ case 16:
+ screen->visuals = (1 << TrueColor);
+ screen->blueMask = 0x001f;
+ screen->greenMask = 0x07e0;
+ screen->redMask = 0xf800;
+ break;
+ case 24:
+ screen->visuals = (1 << TrueColor);
+ screen->blueMask = 0x0000ff;
+ screen->greenMask = 0x00ff00;
+ screen->redMask = 0xff0000;
+ break;
+ }
+
+ screen->driver = s3s;
+
+ return TRUE;
+}
+
+void
+s3Preserve (KdCardInfo *card)
+{
+ S3CardInfo *s3c = card->driver;
+
+ s3Save (s3c);
+}
+
+/*
+ * Enable the card for rendering. Manipulate the initial settings
+ * of the card here.
+ */
+void
+s3Enable (ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ KdCardInfo *card = pScreenPriv->card;
+ KdScreenInfo *screen = pScreenPriv->screen;
+ s3CardInfo (pScreenPriv);
+ s3ScreenInfo (pScreenPriv);
+
+ S3Crtc crtcR, *crtc;
+ int hactive, hblank, hfp, hbp;
+ int vactive, vblank, vfp, vbp;
+ int hsize;
+
+ int h_total;
+ int h_display_end;
+ int h_blank_start;
+ int h_blank_end;
+ int h_sync_start;
+ int h_sync_end;
+ int h_screen_off;
+ int h_start_fifo_fetch;
+
+ int v_total;
+ int v_retrace_start;
+ int v_retrace_end;
+ int v_display_end;
+ int v_blank_start;
+ int v_blank_end;
+
+ int h_adjust;
+ int h_sync_extend_;
+ int h_blank_extend_;
+ int i;
+ CARD16 cursor_address;
+ S3Timing *t;
+ int m, n, r;
+
+ DRAW_DEBUG ((DEBUG_S3INIT, "s3Enable"));
+
+ DRAW_DEBUG ((DEBUG_S3INIT, "requested bpp %d current %d",
+ pScreenPriv->bitsPerPixel, s3c->save.crtc.bits_per_pixel));
+
+ for (i = 0; i < NUM_S3_TIMINGS; i++)
+ {
+ t = &s3Timings[i];
+
+ if (t->horizontal == screen->width &&
+ t->vertical == screen->height &&
+ t->rate <= screen->rate)
+ break;
+ }
+ if (i == NUM_S3_TIMINGS)
+ t = &s3Timings[DEFAULT_S3_TIMING];
+
+ hfp = t->hfp;
+ hbp = t->hbp;
+ hblank = t->hblank;
+ hactive = t->horizontal;
+
+ vfp = t->vfp;
+ vbp = t->vbp;
+ vblank = t->vblank;
+ vactive = t->vertical;
+
+ crtcR = s3c->save.crtc;
+ crtc = &crtcR;
+
+#if 0
+ if (s3c->savage)
+ {
+ m = ((int) crtc->dclk_pll_m_savage_8 << 8) | crtc->dclk_pll_m0_savage_0_7;
+ n = (crtc->dclk_pll_n_savage_6 << 6) | crtc->dclk_pll_n_savage_0_5;
+ r = (crtc->dclk_pll_r_savage_2 << 2) | crtc->dclk_pll_r_savage_0_1;
+ fprintf (stderr, "old clock %d, %d, %d\n", m, n, r);
+ s3GetClock (t, &m, &n, &r, 127, 31, 3);
+#if 0
+ s3GetClock (t, &m, &n, &r, 511, 127, 4);
+ crtc->dclk_pll_m0_savage_0_7 = m;
+ crtc->dclk_pll_m1_savage_0_7 = m;
+ crtc->dclk_pll_m_savage_8 = m >> 8;
+ crtc->dclk_pll_n_savage_0_5 = n;
+ crtc->dclk_pll_n_savage_6 = n >> 6;
+ crtc->dclk_pll_r_savage_0_1 = r;
+ crtc->dclk_pll_r_savage_2 = r >> 2;
+ crtc->dclk_pll_select_savage = 1;
+#endif
+ fprintf (stderr, "new clock %d, %d, %d\n", m, n, r);
+ }
+ else
+ {
+ s3GetClock (t, &m, &n, &r, 127, 31, 3);
+ crtc->dclk_pll_m_trio = m;
+ crtc->dclk_pll_n_trio = n;
+ crtc->dclk_pll_r_trio = r;
+ }
+
+ if (!s3c->savage)
+ {
+ crtc->alt_refresh_count = 0x02;
+ crtc->enable_alt_refresh = 1;
+ }
+ else
+ {
+ crtc->alt_refresh_count = 1;
+ crtc->enable_alt_refresh = 0;
+ }
+ crtc->enable_256_or_more = 1;
+
+ DRAW_DEBUG ((DEBUG_S3INIT, "memory_bus_size %d\n", crtc->memory_bus_size));
+ if (!s3c->savage)
+ crtc->memory_bus_size = 1;
+
+ if (!s3c->savage)
+ crtc->dclk_over_2 = 0;
+ crtc->dclk_invert = 0;
+ crtc->enable_clock_double = 0;
+ crtc->delay_blank = 0;
+ if (!s3c->savage)
+ crtc->extended_bios_5 = 0;
+ /*
+ * Compute character lengths for horizontal timing values
+ */
+ switch (screen->bitsPerPixel) {
+ case 8:
+ hactive = screen->width / 8;
+ hblank /= 8;
+ hfp /= 8;
+ hbp /= 8;
+ h_screen_off = hactive;
+ crtc->pixel_length = 0;
+ crtc->color_mode = 0;
+ /*
+ * Set up for double-pixel mode, switch color modes,
+ * divide the dclk and delay h blank by 2 dclks
+ */
+ if (S3_CLOCK(m, n, r) > S3_MAX_CLOCK)
+ {
+ DRAW_DEBUG ((DEBUG_S3INIT, "S3 clock %g > 80MHz, using pixel double mode",
+ S3_CLOCK(crtc->dclk_pll_m, crtc->dclk_pll_n,
+ crtc->dclk_pll_r)));
+ crtc->color_mode = 1;
+ crtc->dclk_over_2 = 1;
+ crtc->enable_clock_double = 1;
+ crtc->delay_blank = 2;
+ crtc->extended_bios_5 = 2;
+ }
+ h_adjust = 1;
+ break;
+ case 16:
+ if (s3c->savage)
+ {
+ hactive = screen->width / 4;
+ hblank /= 4;
+ hfp /= 4;
+ hbp /= 4;
+ h_screen_off = hactive * 2;
+ crtc->pixel_length = 1;
+ if (S3_CLOCK(m,n,r) > S3_MAX_CLOCK)
+ {
+ if (crtc->depth == 15)
+ crtc->color_mode = 3;
+ else
+ crtc->color_mode = 5;
+ crtc->dclk_over_2 = 1;
+ crtc->enable_clock_double = 1;
+ crtc->delay_blank = 2;
+ }
+ else
+ {
+ if (crtc->depth == 15)
+ crtc->color_mode = 2;
+ else
+ crtc->color_mode = 4;
+ crtc->dclk_over_2 = 0;
+ crtc->enable_clock_double = 0;
+ }
+ h_adjust = 1;
+ }
+ else
+ {
+ hactive = screen->width / 4;
+ hblank /= 4;
+ hfp /= 4;
+ hbp /= 4;
+ h_screen_off = hactive;
+ crtc->pixel_length = 1;
+ crtc->extended_bios_5 = 2;
+ if (crtc->depth == 15)
+ crtc->color_mode = 3;
+ else
+ crtc->color_mode = 5;
+ h_adjust = 2;
+ }
+ break;
+ case 32:
+ hactive = screen->width / 8;
+ hblank /= 8;
+ hfp /= 8;
+ hbp /= 8;
+ h_screen_off = hactive * 4;
+ crtc->pixel_length = 3;
+ crtc->color_mode = 0xd;
+ h_adjust = 1;
+ break;
+ }
+#endif
+
+ /*
+ * X server starts frame buffer at top of memory
+ */
+ DRAW_DEBUG ((DEBUG_S3INIT, "Old start address 0x%x\n",
+ crtc_start_address (crtc)));
+ crtc_set_start_address (crtc, 0);
+
+#if 0
+ /*
+ * Compute horizontal register values from timings
+ */
+ h_total = hactive + hblank - 5;
+ h_display_end = hactive - 1;
+ h_blank_start = h_display_end;
+ h_blank_end = h_blank_start + hblank - h_adjust;
+ h_sync_start = hactive + hfp + h_adjust;
+ h_sync_end = h_sync_start + hblank - hbp - hfp;
+ h_start_fifo_fetch = h_total - 5;
+
+ DRAW_DEBUG ((DEBUG_S3INIT, "blank_end 0x%x sync_end 0x%x sync_start 0x%x\n",
+ h_blank_end, h_sync_end, h_sync_start));
+
+ if (h_blank_end - h_blank_start > 0x40)
+ h_blank_extend_ = 1;
+ else
+ h_blank_extend_ = 0;
+
+ if (h_sync_end - h_sync_start > 0x20)
+ h_sync_extend_ = 1;
+ else
+ h_sync_extend_ = 0;
+
+ DRAW_DEBUG ((DEBUG_S3INIT, "blank_end 0x%x sync_end 0x%x extend %d\n",
+ h_blank_end, h_sync_end, h_sync_extend_));
+
+ crtc_set_h_total(crtc, h_total);
+ crtc_set_h_display_end (crtc, h_display_end);
+ crtc_set_h_blank_start (crtc, h_blank_start);
+ crtc_set_h_blank_end (crtc, h_blank_end);
+ crtc_set_h_sync_start (crtc, h_sync_start);
+ crtc_set_h_sync_end (crtc, h_sync_end);
+ crtc_set_screen_off (crtc, h_screen_off);
+ crtc_set_h_start_fifo_fetch (crtc, h_start_fifo_fetch);
+ crtc->h_sync_extend = h_sync_extend_;
+ crtc->h_blank_extend = h_blank_extend_;
+
+
+ v_total = vactive + vblank - 2;
+ v_retrace_start = vactive + vfp - 1;
+ v_retrace_end = v_retrace_start + vblank - vbp - 1;
+ v_display_end = vactive - 1;
+ v_blank_start = vactive - 1;
+ v_blank_end = v_blank_start + vblank - 1;
+
+ crtc_set_v_total(crtc, v_total);
+ crtc_set_v_retrace_start (crtc, v_retrace_start);
+ crtc->v_retrace_end_0_3 = v_retrace_end;
+ crtc_set_v_display_end (crtc, v_display_end);
+ crtc_set_v_blank_start (crtc, v_blank_start);
+ crtc->v_blank_end_0_7 = v_blank_end;
+#endif
+
+ /*
+ * Set cursor
+ */
+ if (!screen->softCursor)
+ {
+ cursor_address = (s3s->cursor_base - screen->frameBuffer) / 1024;
+
+ crtc->cursor_address_0_7 = cursor_address;
+ crtc->cursor_address_8_15 = cursor_address >> 8;
+ crtc->hardware_cursor_ms_x11 = 0;
+ crtc->hardware_cursor_enable = 1;
+ }
+ else
+ crtc->hardware_cursor_enable = 0;
+
+ /*
+ * Set accelerator
+ */
+ switch (screen->width) {
+ case 640: crtc_set_ge_screen_width(crtc,1); break;
+ case 800: crtc_set_ge_screen_width(crtc,2); break;
+ case 1024: crtc_set_ge_screen_width(crtc,0); break;
+ case 1152: crtc_set_ge_screen_width(crtc,4); break;
+ case 1280: crtc_set_ge_screen_width(crtc,3); break;
+ case 1600: crtc_set_ge_screen_width(crtc,6); break;
+ }
+
+ /*
+ * Set depth values
+ */
+ crtc->bits_per_pixel = screen->bitsPerPixel;
+ crtc->depth = screen->depth;
+
+ crtc->l_parm_0_7 = screen->width / 4; /* Undocumented. */
+
+ crtc->disable_v_retrace_int = 1; /* don't let retrace interrupt */
+
+ DRAW_DEBUG ((DEBUG_S3INIT, "new h total %d display_end %d",
+ crtc_h_total(crtc),
+ crtc_h_display_end(crtc)));
+ DRAW_DEBUG ((DEBUG_S3INIT, " sync_start %d sync_end %d (%d)",
+ crtc_h_sync_start(crtc),
+ crtc_h_sync_end(crtc), h_sync_end));
+
+ DRAW_DEBUG ((DEBUG_S3INIT, " blank_start %d blank_end %d",
+ crtc_h_blank_start(crtc),
+ crtc_h_blank_end(crtc)));
+
+ DRAW_DEBUG ((DEBUG_S3INIT, " screen_off %d start_fifo %d",
+ crtc_screen_off(crtc), crtc_h_start_fifo_fetch(crtc)));
+
+ DRAW_DEBUG ((DEBUG_S3INIT, " active %d blank %d fp %d bp %d",
+ hactive, hblank, hfp, hbp));
+
+ DRAW_DEBUG ((DEBUG_S3INIT, "new v total %d display_end %d",
+ crtc_v_total(crtc),
+ crtc_v_display_end(crtc)));
+ DRAW_DEBUG ((DEBUG_S3INIT, " retrace_start %d retrace_end %d (%d)",
+ crtc_v_retrace_start(crtc),
+ crtc->v_retrace_end,
+ v_retrace_end));
+ DRAW_DEBUG ((DEBUG_S3INIT, " blank_start %d blank_end %d",
+ crtc_v_blank_start(crtc),
+ crtc->v_blank_end_0_7));
+
+ DRAW_DEBUG ((DEBUG_S3INIT, " active %d blank %d fp %d bp %d",
+ vactive, vblank, vfp, vbp));
+
+ /*
+ * Set DPMS to normal
+ */
+ crtc->hsync_control = 0;
+ crtc->vsync_control = 0;
+
+ LockS3 (s3c);
+ _s3SetDepth (s3c->s3, crtc);
+ UnlockS3 (s3c);
+}
+
+void
+s3Disable (ScreenPtr pScreen)
+{
+}
+
+void
+s3Restore (KdCardInfo *card)
+{
+ S3CardInfo *s3c = card->driver;
+
+ s3Reset (s3c);
+}
+
+void
+_s3SetSync (S3CardInfo *s3c, int hsync, int vsync)
+{
+ /* this abuses the macros defined to access the crtc structure */
+ union extended_sequencer_d_u _extended_sequencer_d_u;
+ S3Ptr s3 = s3c->s3;
+
+ extended_sequencer_d = s3c->save.crtc.extended_sequencer_d;
+ hsync_control = hsync;
+ vsync_control = vsync;
+ PutSrtc (s3, 0x0d, extended_sequencer_d);
+}
+
+Bool
+s3DPMS (ScreenPtr pScreen, int mode)
+{
+ KdScreenPriv(pScreen);
+ s3CardInfo(pScreenPriv);
+
+ switch (mode) {
+ case KD_DPMS_NORMAL:
+ _s3SetSync (s3c, 0, 0);
+ _s3SetBlank (s3c->s3, FALSE);
+ break;
+ case KD_DPMS_STANDBY:
+ _s3SetBlank (s3c->s3, TRUE);
+ _s3SetSync (s3c, 1, 0);
+ break;
+ case KD_DPMS_SUSPEND:
+ _s3SetBlank (s3c->s3, TRUE);
+ _s3SetSync (s3c, 0, 1);
+ break;
+ case KD_DPMS_POWERDOWN:
+ _s3SetBlank (s3c->s3, TRUE);
+ _s3SetSync (s3c, 1, 1);
+ break;
+ }
+ return TRUE;
+}
+
+void
+s3ScreenFini (KdScreenInfo *screen)
+{
+ S3ScreenInfo *s3s = (S3ScreenInfo *) screen->driver;
+
+ xfree (s3s);
+ screen->driver = 0;
+}
+
+void
+s3CardFini (KdCardInfo *card)
+{
+ S3CardInfo *s3c = (S3CardInfo *) card->driver;
+
+ KdUnmapDevice (s3c->frameBuffer, s3c->memory);
+ KdUnmapDevice (s3c->registers, sizeof (S3) + PACKED_OFFSET);
+/* DeleteCriticalSection (&s3c->lock); */
+ xfree (s3c);
+ card->driver = 0;
+}
+
+KdCardFuncs s3Funcs = {
+ s3CardInit,
+ s3ScreenInit,
+ s3Preserve,
+ s3Enable,
+ s3DPMS,
+ s3Disable,
+ s3Restore,
+ s3ScreenFini,
+ s3CardFini,
+ s3CursorInit,
+ s3CursorEnable,
+ s3CursorDisable,
+ s3CursorFini,
+ s3RecolorCursor,
+ s3DrawInit,
+ s3DrawEnable,
+ s3DrawDisable,
+ s3DrawFini,
+ s3GetColors,
+ s3PutColors,
+};
diff --git a/hw/kdrive/trio/s3.h b/hw/kdrive/trio/s3.h
new file mode 100644
index 000000000..97374045f
--- /dev/null
+++ b/hw/kdrive/trio/s3.h
@@ -0,0 +1,1238 @@
+/*
+ * $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: $ */
+
+#ifndef _S3_H_
+#define _S3_H_
+
+#include "kdrive.h"
+
+#define PLATFORM 300
+
+#define DRAW_DEBUG(a)
+
+#define DEBUG_S3INIT (DEBUG_ACCEL)
+#define DEBUG_CRTC (DEBUG_ACCEL+1)
+#define DEBUG_PATTERN (DEBUG_ACCEL+2)
+#define DEBUG_RECT (DEBUG_ACCEL+3)
+#define DEBUG_PAINT_WINDOW (DEBUG_ACCEL+4)
+#define DEBUG_SET (DEBUG_ACCEL+5)
+#define DEBUG_RENDER (DEBUG_ACCEL+6)
+#define DEBUG_REGISTERS (DEBUG_ACCEL+7)
+#define DEBUG_ARCS (DEBUG_ACCEL+8)
+#define DEBUG_TEXT (DEBUG_ACCEL+9)
+#define DEBUG_POLYGON (DEBUG_ACCEL+10)
+#define DEBUG_CLIP (DEBUG_ACCEL+11)
+
+/* VESA Approved Register Definitions */
+
+/*
+ * Linear Addressing 000 0000 - 0ff ffff (16m)
+ * Image data transfer 100 0000 - 100 7fff (32k)
+ * PCI config 100 8000 - 100 8043
+ * Packed enhanced regs 100 8100 - 100 814a
+ * Streams regs 100 8180 - 100 81ff
+ * Current Y pos 100 82e8
+ * CRT VGA 3b? regs 100 83b0 - 100 83bf
+ * CRT VGA 3c? regs 100 83c0 - 100 83cf
+ * CRT VGA 3d? regs 100 83d0 - 100 83df
+ * Subsystem status (42e8h) 100 8504
+ * Advanced function (42e8h) 100 850c
+ * Enhanced regs 100 86e8 - 100 eeea
+ * Local peripheral bus 100 ff00 - 100 ff5c
+ *
+ * We don't care about the image transfer or PCI regs, so
+ * this structure starts at the packed enhanced regs
+ */
+
+typedef volatile CARD32 VOL32;
+typedef volatile CARD16 VOL16;
+typedef volatile CARD8 VOL8;
+
+typedef volatile struct _s3 {
+ VOL32 alt_curxy; /* 8100 */
+ VOL32 _pad0; /* 8104 */
+ VOL32 alt_step; /* 8108 */
+ VOL32 _pad1; /* 810c */
+ VOL32 err_term; /* 8110 */
+ VOL32 _pad2; /* 8114 */
+ VOL32 cmd_gp_stat; /* 8118 */
+ VOL32 short_stroke; /* 811c */
+ VOL32 bg; /* 8120 */
+ VOL32 fg; /* 8124 */
+ VOL32 write_mask; /* 8128 */
+ VOL32 read_mask; /* 812c */
+ VOL32 color_cmp; /* 8130 */
+ VOL32 alt_mix; /* 8134 */
+ VOL32 scissors_tl; /* 8138 */
+ VOL32 scissors_br; /* 813c */
+ VOL16 pix_cntl; /* 8140 */
+ VOL16 mult_misc2; /* 8142 */
+ VOL32 mult_misc_read_sel; /* 8144 */
+ VOL32 alt_pcnt; /* 8148 min_axis_pcnt, maj_axis_pcnt */
+ VOL8 _pad3[0x19c]; /* 814c */
+ VOL16 cur_y; /* 82e8 */
+ VOL8 _pad4[0xc6]; /* 82ea */
+
+ VOL8 crt_vga_3b0; /* 83b0 */
+ VOL8 crt_vga_3b1; /* 83b1 */
+ VOL8 crt_vga_3b2; /* 83b2 */
+ VOL8 crt_vga_3b3; /* 83b3 */
+ VOL8 crt_vga_3b4; /* 83b4 */
+ VOL8 crt_vga_3b5; /* 83b5 */
+ VOL8 crt_vga_3b6; /* 83b6 */
+ VOL8 crt_vga_3b7; /* 83b7 */
+ VOL8 crt_vga_3b8; /* 83b8 */
+ VOL8 crt_vga_3b9; /* 83b9 */
+ VOL8 crt_vga_3ba; /* 83ba */
+ VOL8 crt_vga_3bb; /* 83bb */
+ VOL8 crt_vga_3bc; /* 83bc */
+ VOL8 crt_vga_3bd; /* 83bd */
+ VOL8 crt_vga_3be; /* 83be */
+ VOL8 crt_vga_3bf; /* 83bf */
+
+ VOL8 crt_vga_3c0; /* 83c0 */
+ VOL8 crt_vga_3c1; /* 83c1 */
+ VOL8 crt_vga_3c2; /* 83c2 */
+ VOL8 crt_vga_3c3; /* 83c3 */
+ VOL8 crt_vga_3c4; /* 83c4 */
+ VOL8 crt_vga_3c5; /* 83c5 */
+ VOL8 crt_vga_dac_ad_mk; /* 83c6 */
+ VOL8 crt_vga_dac_rd_ad; /* 83c7 */
+ VOL8 crt_vga_dac_wt_ad; /* 83c8 */
+ VOL8 crt_vga_dac_data; /* 83c9 */
+ VOL8 crt_vga_3ca; /* 83ca */
+ VOL8 crt_vga_3cb; /* 83cb */
+ VOL8 crt_vga_3cc; /* 83cc */
+ VOL8 crt_vga_3cd; /* 83cd */
+ VOL8 crt_vga_3ce; /* 83ce */
+ VOL8 crt_vga_3cf; /* 83cf */
+
+ VOL8 crt_vga_3d0; /* 83d0 */
+ VOL8 crt_vga_3d1; /* 83d1 */
+ VOL8 crt_vga_3d2; /* 83d2 */
+ VOL8 crt_vga_3d3; /* 83d3 */
+ VOL8 crt_vga_3d4; /* 83d4 */
+ VOL8 crt_vga_3d5; /* 83d5 */
+ VOL8 crt_vga_3d6; /* 83d6 */
+ VOL8 crt_vga_3d7; /* 83d7 */
+ VOL8 crt_vga_3d8; /* 83d8 */
+ VOL8 crt_vga_3d9; /* 83d9 */
+ VOL8 crt_vga_status_1; /* 83da */
+ VOL8 crt_vga_3db; /* 83db */
+ VOL8 crt_vga_3dc; /* 83dc */
+ VOL8 crt_vga_3dd; /* 83dd */
+ VOL8 crt_vga_3de; /* 83de */
+ VOL8 crt_vga_3df; /* 83df */
+
+ VOL8 _pad5[0x124]; /* 83e0 */
+ VOL16 subsys_status; /* 8504 */
+ VOL8 _pad6[0x6]; /* 8506 */
+ VOL16 adv_control; /* 850c */
+ VOL8 _pad7[0x1da]; /* 850e */
+ VOL16 cur_x; /* 86e8 */
+ VOL8 _pad8[0x3fe]; /* 86ea */
+ VOL16 desty_axstp; /* 8ae8 */
+ VOL8 _pad9[0x3fe]; /* 8aea */
+ VOL16 destx_diastp; /* 8ee8 */
+ VOL8 _pad10[0x3fe]; /* 8eea */
+ VOL16 enh_err_term; /* 92e8 */
+ VOL8 _pad11[0x3fe]; /* 92ea */
+ VOL16 maj_axis_pcnt; /* 96e8 */
+ VOL8 _pad12[0x3fe]; /* 96ea */
+ VOL16 enh_cmd_gp_stat; /* 9ae8 */
+ VOL8 _pad13[0x3fe]; /* 9aea */
+ VOL16 enh_short_stroke; /* 9ee8 */
+ VOL8 _pad14[0x3fe]; /* 9eea */
+ VOL16 enh_bg; /* a2e8 */
+ VOL8 _pad15[0x3fe]; /* a2ea */
+ VOL16 enh_fg; /* a6e8 */
+ VOL8 _pad16[0x3fe]; /* a6ea */
+ VOL16 enh_wrt_mask; /* aae8 */
+ VOL8 _pad17[0x3fe]; /* aaea */
+ VOL16 enh_rd_mask; /* aee8 */
+ VOL8 _pad18[0x3fe]; /* aeea */
+ VOL16 enh_color_cmp; /* b2e8 */
+ VOL8 _pad19[0x3fe]; /* b2ea */
+ VOL16 enh_bg_mix; /* b6e8 */
+ VOL8 _pad20[0x3fe]; /* b6ea */
+ VOL16 enh_fg_mix; /* bae8 */
+ VOL8 _pad21[0x3fe]; /* baea */
+ VOL16 enh_rd_reg_dt; /* bee8 */
+ VOL8 _pad22[0x23fe]; /* beea */
+ VOL32 pix_trans; /* e2e8 */
+} S3, *S3Ptr;
+
+#define VGA_STATUS_1_DTM 0x01
+#define VGA_STATUS_1_VSY 0x08
+
+#define DAC_MASK 0x03c6
+#define DAC_R_INDEX 0x03c7
+#define DAC_W_INDEX 0x03c8
+#define DAC_DATA 0x03c9
+#define DISP_STAT 0x02e8
+#define H_TOTAL 0x02e8
+#define H_DISP 0x06e8
+#define H_SYNC_STRT 0x0ae8
+#define H_SYNC_WID 0x0ee8
+#define V_TOTAL 0x12e8
+#define V_DISP 0x16e8
+#define V_SYNC_STRT 0x1ae8
+#define V_SYNC_WID 0x1ee8
+#define DISP_CNTL 0x22e8
+#define ADVFUNC_CNTL 0x4ae8
+#define SUBSYS_STAT 0x42e8
+#define SUBSYS_CNTL 0x42e8
+#define ROM_PAGE_SEL 0x46e8
+#define CUR_Y 0x82e8
+#define CUR_X 0x86e8
+#define DESTY_AXSTP 0x8ae8
+#define DESTX_DIASTP 0x8ee8
+#define ERR_TERM 0x92e8
+#define MAJ_AXIS_PCNT 0x96e8
+#define GP_STAT 0x9ae8
+#define CMD 0x9ae8
+#define SHORT_STROKE 0x9ee8
+#define BKGD_COLOR 0xa2e8
+#define FRGD_COLOR 0xa6e8
+#define WRT_MASK 0xaae8
+#define RD_MASK 0xaee8
+#define COLOR_CMP 0xb2e8
+#define BKGD_MIX 0xb6e8
+#define FRGD_MIX 0xbae8
+#define MULTIFUNC_CNTL 0xbee8
+#define MIN_AXIS_PCNT 0x0000
+#define SCISSORS_T 0x1000
+#define SCISSORS_L 0x2000
+#define SCISSORS_B 0x3000
+#define SCISSORS_R 0x4000
+#define MEM_CNTL 0x5000
+#define PATTERN_L 0x8000
+#define PATTERN_H 0x9000
+#define PIX_CNTL 0xa000
+#define PIX_TRANS 0xe2e8
+
+/* Advanced Function Control Regsiter */
+#define CLKSEL 0x0004
+#define DISABPASSTHRU 0x0001
+
+/* Graphics Processor Status Register */
+
+#define GPNSLOT 13
+
+#define GPBUSY_1 0x0080
+#define GPBUSY_2 0x0040
+#define GPBUSY_3 0x0020
+#define GPBUSY_4 0x0010
+#define GPBUSY_5 0x0008
+#define GPBUSY_6 0x0004
+#define GPBUSY_7 0x0002
+#define GPBUSY_8 0x0001
+#define GPBUSY_9 0x8000
+#define GPBUSY_10 0x4000
+#define GPBUSY_11 0x2000
+#define GPBUSY_12 0x1000
+#define GPBUSY_13 0x0800
+
+#define GPEMPTY 0x0400
+#define GPBUSY 0x0200
+#define DATDRDY 0x0100
+
+/* Command Register */
+#define CMD_NOP 0x0000
+#define CMD_LINE 0x2000
+#define CMD_RECT 0x4000
+#define CMD_RECTV1 0x6000
+#define CMD_RECTV2 0x8000
+#define CMD_LINEAF 0xa000
+#define CMD_BITBLT 0xc000
+#define CMD_PATBLT 0xe000
+#define CMD_OP_MSK 0xe000
+#define BYTSEQ 0x1000
+#define _32BITNOPAD 0x0600
+#define _32BIT 0x0400
+#define _16BIT 0x0200
+#define _8BIT 0x0000
+#define PCDATA 0x0100
+#define INC_Y 0x0080
+#define YMAJAXIS 0x0040
+#define INC_X 0x0020
+#define DRAW 0x0010
+#define LINETYPE 0x0008
+#define LASTPIX 0x0004 /* Draw last pixel in line */
+#define PLANAR 0x0002
+#define WRTDATA 0x0001
+
+/* Background Mix Register */
+#define BSS_BKGDCOL 0x0000
+#define BSS_FRGDCOL 0x0020
+#define BSS_PCDATA 0x0040
+#define BSS_BITBLT 0x0060
+
+/* Foreground Mix Register */
+#define FSS_BKGDCOL 0x0000
+#define FSS_FRGDCOL 0x0020
+#define FSS_PCDATA 0x0040
+#define FSS_BITBLT 0x0060
+
+/* The Mixes */
+#define MIX_MASK 0x001f
+
+#define MIX_NOT_DST 0x0000
+#define MIX_0 0x0001
+#define MIX_1 0x0002
+#define MIX_DST 0x0003
+#define MIX_NOT_SRC 0x0004
+#define MIX_XOR 0x0005
+#define MIX_XNOR 0x0006
+#define MIX_SRC 0x0007
+#define MIX_NAND 0x0008
+#define MIX_NOT_SRC_OR_DST 0x0009
+#define MIX_SRC_OR_NOT_DST 0x000a
+#define MIX_OR 0x000b
+#define MIX_AND 0x000c
+#define MIX_SRC_AND_NOT_DST 0x000d
+#define MIX_NOT_SRC_AND_DST 0x000e
+#define MIX_NOR 0x000f
+
+#define MIX_MIN 0x0010
+#define MIX_DST_MINUS_SRC 0x0011
+#define MIX_SRC_MINUS_DST 0x0012
+#define MIX_PLUS 0x0013
+#define MIX_MAX 0x0014
+#define MIX_HALF__DST_MINUS_SRC 0x0015
+#define MIX_HALF__SRC_MINUS_DST 0x0016
+#define MIX_AVERAGE 0x0017
+#define MIX_DST_MINUS_SRC_SAT 0x0018
+#define MIX_SRC_MINUS_DST_SAT 0x001a
+#define MIX_HALF__DST_MINUS_SRC_SAT 0x001c
+#define MIX_HALF__SRC_MINUS_DST_SAT 0x001e
+#define MIX_AVERAGE_SAT 0x001f
+
+/* Pixel Control Register */
+#define MIXSEL_FRGDMIX 0x0000
+#define MIXSEL_PATT 0x0040
+#define MIXSEL_EXPPC 0x0080
+#define MIXSEL_EXPBLT 0x00c0
+#define COLCMPOP_F 0x0000
+#define COLCMPOP_T 0x0008
+#define COLCMPOP_GE 0x0010
+#define COLCMPOP_LT 0x0018
+#define COLCMPOP_NE 0x0020
+#define COLCMPOP_EQ 0x0028
+#define COLCMPOP_LE 0x0030
+#define COLCMPOP_GT 0x0038
+#define PLANEMODE 0x0004
+
+#define FIFO_SLOTS 13
+
+#if 0
+/* Wait for one slot to become available */
+#define _s3WaitSlot(s3) { \
+ DRAW_DEBUG ((DEBUG_CRTC, "_s3WaitSlot 0x%x", (s3)->cmd_gp_stat)); \
+ while ((s3)->cmd_gp_stat & GPBUSY_1) ; \
+ DRAW_DEBUG ((DEBUG_CRTC, " s3 slot available")); \
+}
+
+/* Wait until queue is empty */
+#define _s3WaitEmpty(s3) { \
+ DRAW_DEBUG ((DEBUG_CRTC, "_s3WaitEmpty 0x%x", (s3)->cmd_gp_stat)); \
+ while (!((s3)->cmd_gp_stat & GPEMPTY)) ; \
+ DRAW_DEBUG ((DEBUG_CRTC, " s3 empty")); \
+}
+
+/* Wait until GP is idle and queue is empty */
+#define _s3WaitIdleEmpty(s3) { \
+ DRAW_DEBUG ((DEBUG_CRTC, "_s3WaitIdleEmpty 0x%x", (s3)->cmd_gp_stat)); \
+ while (((s3)->cmd_gp_stat & (GPBUSY|GPEMPTY)) != GPEMPTY) ; \
+ DRAW_DEBUG ((DEBUG_CRTC, " s3 idle empty")); \
+}
+
+/* Wait until GP is idle */
+#define _s3WaitIdle(s3) { \
+ DRAW_DEBUG ((DEBUG_CRTC, "_s3WaitIdle 0x%x", (s3)->cmd_gp_stat)); \
+ while ((s3)->cmd_gp_stat & GPBUSY) ; \
+ DRAW_DEBUG ((DEBUG_CRTC, " s3 idle")); \
+}
+#endif
+#define _s3WaitSlot(s3)
+#define _s3WaitEmpty(s3)
+#define _s3WaitIdleEmpty(s3)
+#define _s3WaitIdle(s3)
+
+typedef struct _s3Cursor {
+ int width, height;
+ int xhot, yhot;
+ Bool has_cursor;
+ CursorPtr pCursor;
+ Pixel source, mask;
+} S3Cursor;
+
+typedef struct _s3PatternCache {
+ int id;
+ int x, y;
+} S3PatternCache;
+
+typedef struct _s3Patterns {
+ S3PatternCache *cache;
+ int ncache;
+ int last_used;
+ int last_id;
+} S3Patterns;
+
+typedef struct _crtc {
+ CARD8 h_total_0_7; /* CR0 */
+ CARD8 h_display_end_0_7; /* CR1 */
+ CARD8 h_blank_start_0_7; /* CR2 */
+ union {
+ struct {
+ CARD8 _h_blank_end_0_4 : 5;
+ CARD8 _display_skew : 2;
+ CARD8 : 1;
+ } _h_blank_end_s;
+ CARD8 __h_blank_end; /* CR3 */
+ } _h_blank_end_u;
+#define h_blank_end_0_4 _h_blank_end_u._h_blank_end_s._h_blank_end_0_4
+#define display_skew _h_blank_end_u._h_blank_end_s._display_skew
+#define _h_blank_end _h_blank_end_u.__h_blank_end
+
+ CARD8 h_sync_start_0_7; /* CR4 */
+
+ union {
+ struct {
+ CARD8 _h_sync_end_0_4 : 5;
+ CARD8 _horizontal_skew : 2;
+ CARD8 _h_blank_end_5 : 1;
+ } _h_sync_end_s;
+ CARD8 __h_sync_end; /* CR5 */
+ } _h_sync_end_u;
+
+#define h_sync_end_0_4 _h_sync_end_u._h_sync_end_s._h_sync_end_0_4
+#define horizontal_skew _h_sync_end_u._h_sync_end_s._horizontal_skew
+#define h_blank_end_5 _h_sync_end_u._h_sync_end_s._h_blank_end_5
+#define _h_sync_end _h_sync_end_u.__h_sync_end
+
+ CARD8 v_total_0_7; /* CR6 */
+
+ union {
+ struct {
+ CARD8 _v_total_8 : 1;
+ CARD8 _v_display_end_8 : 1;
+ CARD8 _v_retrace_start_8 : 1;
+ CARD8 _v_blank_start_8 : 1;
+ CARD8 _line_compare_8 : 1;
+ CARD8 _v_total_9 : 1;
+ CARD8 _v_display_end_9 : 1;
+ CARD8 _v_retrace_start_9 : 1;
+ } _crtc_overflow_s;
+ CARD8 _crtc_overflow; /* CR7 */
+ } _crtc_overflow_u;
+
+#define v_total_8 _crtc_overflow_u._crtc_overflow_s._v_total_8
+#define v_display_end_8 _crtc_overflow_u._crtc_overflow_s._v_display_end_8
+#define v_retrace_start_8 _crtc_overflow_u._crtc_overflow_s._v_retrace_start_8
+#define v_blank_start_8 _crtc_overflow_u._crtc_overflow_s._v_blank_start_8
+#define line_compare_8 _crtc_overflow_u._crtc_overflow_s._line_compare_8
+#define v_total_9 _crtc_overflow_u._crtc_overflow_s._v_total_9
+#define v_display_end_9 _crtc_overflow_u._crtc_overflow_s._v_display_end_9
+#define v_retrace_start_9 _crtc_overflow_u._crtc_overflow_s._v_retrace_start_9
+#define crtc_overflow _crtc_overflow_u._crtc_overflow
+
+ CARD8 preset_row_scan; /* CR8 (unused) */
+
+ union {
+ struct {
+ CARD8 _max_scan_line : 5;
+ CARD8 _v_blank_start_9 : 1;
+ CARD8 _line_compare_9 : 1;
+ CARD8 _double_scan : 1;
+ } _max_scan_line_s;
+ CARD8 __max_scan_line; /* CR9 */
+ } _max_scan_line_u;
+
+#define max_scan_line _max_scan_line_u._max_scan_line_s._max_scan_line
+#define v_blank_start_9 _max_scan_line_u._max_scan_line_s._v_blank_start_9
+#define line_compare_9 _max_scan_line_u._max_scan_line_s._line_compare_9
+#define double_scan _max_scan_line_u._max_scan_line_s._double_scan
+#define _max_scan_line _max_scan_line_u.__max_scan_line
+
+ CARD8 cursor_start;
+ CARD8 cursor_end;
+
+ CARD8 start_address_8_15; /* CRC */
+ CARD8 start_address_0_7; /* CRD */
+
+ CARD8 cursor_loc_high;
+ CARD8 cursor_loc_low;
+
+ CARD8 v_retrace_start_0_7; /* CR10 */
+ union {
+ struct {
+ CARD8 _v_retrace_end_0_3 : 4;
+ CARD8 _clear_v_retrace_int : 1;
+ CARD8 _disable_v_retrace_int : 1;
+ CARD8 _refresh_cycle_select : 1;
+ CARD8 _lock_crtc : 1;
+ } _v_retrace_end_s;
+ CARD8 __v_retrace_end; /* CR11 */
+ } _v_retrace_end_u;
+
+#define v_retrace_end_0_3 _v_retrace_end_u._v_retrace_end_s._v_retrace_end_0_3
+#define clear_v_retrace_int _v_retrace_end_u._v_retrace_end_s._clear_v_retrace_int
+#define disable_v_retrace_int _v_retrace_end_u._v_retrace_end_s._disable_v_retrace_int
+#define refresh_cycle_select _v_retrace_end_u._v_retrace_end_s._refresh_cycle_select
+#define lock_crtc _v_retrace_end_u._v_retrace_end_s._lock_crtc
+#define _v_retrace_end _v_retrace_end_u.__v_retrace_end
+
+ CARD8 v_display_end_0_7; /* CR12 */
+
+ CARD8 screen_off_0_7; /* CR13 */
+
+ union {
+ struct {
+ CARD8 _underline_location : 5;
+ CARD8 _count_by_four : 1;
+ CARD8 _doubleword_mode : 1;
+ CARD8 : 1;
+ } _underline_location_s;
+ CARD8 __underline_location; /* CR14 (unused) */
+ } _underline_location_u;
+
+#define underline_location _underline_location_u._underline_location_s._underline_location
+#define count_by_four _underline_location_u._underline_location_s._count_by_four
+#define doubleword_mode _underline_location_u._underline_location_s._doubleword_mode
+#define _underline_location _underline_location_u.__underline_location
+
+ CARD8 v_blank_start_0_7; /* CR15 */
+ CARD8 v_blank_end_0_7; /* CR16 */
+
+ union {
+ struct {
+ CARD8 _two_bk_cga : 1;
+ CARD8 _four_bk_cga : 1;
+ CARD8 _v_total_double : 1;
+ CARD8 _word_mode : 1;
+ CARD8 : 1;
+ CARD8 _address_wrap : 1;
+ CARD8 _byte_mode : 1;
+ CARD8 _hardware_reset : 1;
+ } _crtc_mode_s;
+ CARD8 _crtc_mode; /* CR17 (unused) */
+ } _crtc_mode_u;
+
+ CARD8 line_compare_0_7; /* CR18 (unused) */
+
+ union {
+ struct {
+ CARD8 _enable_base_offset : 1;
+ CARD8 _enable_two_page : 1;
+ CARD8 _enable_vga_16_bit : 1;
+ CARD8 _enhanced_mode_mapping : 1;
+ CARD8 _old_display_start : 2;
+ CARD8 _enable_high_speed_text : 1;
+ CARD8 : 1;
+ } _memory_configuration_s;
+ CARD8 _memory_configuration; /* CR31 (unused) */
+ } _memory_configuration_u;
+
+#define memory_configuration _memory_configuration_u._memory_configuration
+#define enable_base_offset _memory_configuration_u._memory_configuration_s._enable_base_offset
+#define enable_two_page _memory_configuration_u._memory_configuration_s._enable_two_page
+#define enable_vga_16_bit _memory_configuration_u._memory_configuration_s._enable_vga_16_bit
+#define enhanved_mode_mapping _memory_configuration_u._memory_configuration_s._enhanced_mode_mapping
+#define old_display_start _memory_configuration_u._memory_configuration_s._old_display_start
+#define enable_high_speed_text _memory_configuration_u._memory_configuration_s._enable_high_speed_text
+
+ union {
+ struct {
+ CARD8 _alt_refresh_count : 2;
+ CARD8 _enable_alt_refresh : 1;
+ CARD8 _enable_top_memory : 1;
+ CARD8 _enable_256_or_more : 1;
+ CARD8 _high_speed_text : 1;
+ CARD8 : 1;
+ CARD8 _pci_burst_disabled : 1;
+ } _misc_1_s;
+ CARD8 _misc_1; /* CR3A */
+ } _misc_1_u;
+#define misc_1 _misc_1_u._misc_1
+#define alt_refresh_count _misc_1_u._misc_1_s._alt_refresh_count
+#define enable_alt_refresh _misc_1_u._misc_1_s._enable_alt_refresh
+#define enable_top_memory _misc_1_u._misc_1_s._enable_top_memory
+#define enable_256_or_more _misc_1_u._misc_1_s._enable_256_or_more
+#define high_speed_text _misc_1_u._misc_1_s._high_speed_text
+#define pci_burst_disabled _misc_1_u._misc_1_s._pci_burst_disabled
+
+ CARD8 h_start_fifo_fetch_0_7; /* CR3B */
+
+ union {
+ struct {
+ CARD8 : 5;
+ CARD8 interlace : 1;
+ CARD8 : 2;
+ } _mode_control_s;
+ CARD8 _mode_control; /* CR42 */
+ } _mode_control_u;
+
+#define mode_control _mode_control_u._mode_control
+
+ union {
+ struct {
+ CARD8 : 2;
+ CARD8 _old_screen_off_8 : 1;
+ CARD8 : 4;
+ CARD8 h_counter_double_mode : 1;
+ } _extended_mode_s;
+ CARD8 _extended_mode; /* CR43 (unused) */
+ } _extended_mode_u;
+
+#define extended_mode _extended_mode_u._extended_mode
+#define old_screen_off_8 _extended_mode_u._extended_mode_s._old_screen_off_8
+
+ union {
+ struct {
+ CARD8 _hardware_cursor_enable : 1;
+ CARD8 : 3;
+ CARD8 _hardware_cursor_right : 1;
+ CARD8 : 3;
+ } _hardware_cursor_mode_s;
+ CARD8 _hardware_cursor_mode; /* CR45 */
+ } _hardware_cursor_mode_u;
+
+#define hardware_cursor_mode _hardware_cursor_mode_u._hardware_cursor_mode
+#define hardware_cursor_enable _hardware_cursor_mode_u._hardware_cursor_mode_s._hardware_cursor_enable
+
+ CARD8 cursor_address_8_15; /* CR4C */
+ CARD8 cursor_address_0_7; /* CR4D */
+
+ union {
+ struct {
+ CARD8 _ge_screen_width_2 : 1;
+ CARD8 : 3;
+ CARD8 _pixel_length : 2;
+ CARD8 _ge_screen_width_0_1 : 2;
+ } _extended_system_control_1_s;
+ CARD8 _extended_system_control_1; /* CR50 */
+ } _extended_system_control_1_u;
+#define ge_screen_width_2 _extended_system_control_1_u._extended_system_control_1_s._ge_screen_width_2
+#define pixel_length _extended_system_control_1_u._extended_system_control_1_s._pixel_length
+#define ge_screen_width_0_1 _extended_system_control_1_u._extended_system_control_1_s._ge_screen_width_0_1
+#define extended_system_control_1 _extended_system_control_1_u._extended_system_control_1
+
+ union {
+ struct {
+ CARD8 : 4;
+ CARD8 _screen_off_8_9 : 2;
+ CARD8 : 2;
+ } _extended_system_control_2_s;
+ CARD8 _extended_system_control_2; /* CR51 */
+ } _extended_system_control_2_u;
+#define extended_system_control_2 _extended_system_control_2_u._extended_system_control_2
+#define screen_off_8_9 _extended_system_control_2_u._extended_system_control_2_s._screen_off_8_9
+
+ union {
+ struct {
+ CARD8 : 1;
+ CARD8 big_endian_linear : 2;
+ CARD8 mmio_select : 2;
+ CARD8 mmio_window : 1;
+ CARD8 swap_nibbles : 1;
+ CARD8 : 1;
+ } _extended_memory_control_s;
+ CARD8 _extended_memory_control; /* CR53 */
+ } _extended_memory_control_u;
+#define extended_memory_control _extended_memory_control_u._extended_memory_control
+
+ union {
+ struct {
+ CARD8 : 2;
+ CARD8 _enable_gir : 1;
+ CARD8 : 1;
+ CARD8 _hardware_cursor_ms_x11 : 1;
+ CARD8 : 2;
+ CARD8 _tri_state_off_vclk : 1;
+ } _extended_ramdac_control_s;
+ CARD8 _extended_ramdac_control; /* CR55 */
+ } _extended_ramdac_control_u;
+#define extended_ramdac_control _extended_ramdac_control_u._extended_ramdac_control
+#define hardware_cursor_ms_x11 _extended_ramdac_control_u._extended_ramdac_control_s._hardware_cursor_ms_x11
+
+
+ union {
+ struct {
+ CARD8 _h_total_8 : 1;
+ CARD8 _h_display_end_8 : 1;
+ CARD8 _h_blank_start_8 : 1;
+ CARD8 _h_blank_extend : 1; /* extend h_blank by 64 */
+ CARD8 _h_sync_start_8 : 1;
+ CARD8 _h_sync_extend : 1; /* extend h_sync by 32 */
+ CARD8 _h_start_fifo_fetch_8 : 1;
+ CARD8 : 1;
+ } _extended_horizontal_overflow_s;
+ CARD8 _extended_horizontal_overflow; /* CR5D */
+ } _extended_horizontal_overflow_u;
+#define extended_horizontal_overflow _extended_horizontal_overflow_u._extended_horizontal_overflow
+#define h_total_8 _extended_horizontal_overflow_u._extended_horizontal_overflow_s._h_total_8
+#define h_display_end_8 _extended_horizontal_overflow_u._extended_horizontal_overflow_s._h_display_end_8
+#define h_blank_start_8 _extended_horizontal_overflow_u._extended_horizontal_overflow_s._h_blank_start_8
+#define h_blank_extend _extended_horizontal_overflow_u._extended_horizontal_overflow_s._h_blank_extend
+#define h_sync_start_8 _extended_horizontal_overflow_u._extended_horizontal_overflow_s._h_sync_start_8
+#define h_sync_extend _extended_horizontal_overflow_u._extended_horizontal_overflow_s._h_sync_extend
+#define h_start_fifo_fetch_8 _extended_horizontal_overflow_u._extended_horizontal_overflow_s._h_start_fifo_fetch_8
+
+
+ union {
+ struct {
+ CARD8 _v_total_10 : 1;
+ CARD8 _v_display_end_10 : 1;
+ CARD8 _v_blank_start_10 : 1;
+ CARD8 : 1;
+ CARD8 _v_retrace_start_10 : 1;
+ CARD8 : 1;
+ CARD8 _line_compare_10 : 1;
+ CARD8 : 1;
+ } _extended_vertical_overflow_s;
+ CARD8 _extended_vertical_overflow; /* CR5E */
+ } _extended_vertical_overflow_u;
+#define extended_vertical_overflow _extended_vertical_overflow_u._extended_vertical_overflow
+#define v_total_10 _extended_vertical_overflow_u._extended_vertical_overflow_s._v_total_10
+#define v_display_end_10 _extended_vertical_overflow_u._extended_vertical_overflow_s._v_display_end_10
+#define v_blank_start_10 _extended_vertical_overflow_u._extended_vertical_overflow_s._v_blank_start_10
+#define v_retrace_start_10 _extended_vertical_overflow_u._extended_vertical_overflow_s._v_retrace_start_10
+#define line_compare_10 _extended_vertical_overflow_u._extended_vertical_overflow_s._line_compare_10
+
+
+ CARD8 l_parm_0_7; /* CR62 (undocumented) */
+
+ union {
+ struct {
+ CARD8 : 3;
+ CARD8 _delay_blank : 2;
+ CARD8 : 3;
+ } _extended_misc_control_s;
+ CARD8 _extended_misc_control; /* CR65 */
+ } _extended_misc_control_u;
+#define extended_misc_control _extended_misc_control_u._extended_misc_control
+#define delay_blank _extended_misc_control_u._extended_misc_control_s._delay_blank
+
+ union {
+ struct {
+ CARD8 _v_clock_phase : 1;
+ CARD8 : 3;
+ CARD8 _color_mode : 4;
+ } _extended_misc_control_2_s;
+ CARD8 _extended_misc_control_2; /* CR67 */
+ } _extended_misc_control_2_u;
+
+#define v_clock_phase _extended_misc_control_2_u._extended_misc_control_2_s._v_clock_phase
+#define color_mode _extended_misc_control_2_u._extended_misc_control_2_s._color_mode
+#define extended_misc_control_2 _extended_misc_control_2_u._extended_misc_control_2
+
+
+ union {
+ struct {
+ CARD8 cas_oe_str : 2;
+ CARD8 ras_low : 1;
+ CARD8 ras_precharge : 1;
+ CARD8 : 3;
+ CARD8 _memory_bus_size : 1; /* 0 = 32, 1 = 32/64 */
+ } _configuration_3_s;
+ CARD8 _configuration_3; /* CR68 */
+ } _configuration_3_u;
+#define configuration_3 _configuration_3_u._configuration_3
+#define memory_bus_size _configuration_3_u._configuration_3_s._memory_bus_size
+
+ union {
+ struct {
+ CARD8 _start_address_16_19 : 4;
+ CARD8 : 4;
+ } _extended_system_control_3_s;
+ CARD8 _extended_system_control_3; /* CR69 */
+ } _extended_system_control_3_u;
+#define extended_system_control_3 _extended_system_control_3_u._extended_system_control_3
+#define start_address_16_19 _extended_system_control_3_u._extended_system_control_3_s._start_address_16_19
+
+ CARD8 extended_bios_5; /* CR6D */
+
+ union {
+ struct {
+ CARD8 dot_clock_vclki : 1; /* testing only */
+ CARD8 vclki_with_vafc : 1; /* feature connector */
+ CARD8 : 1;
+ CARD8 bpp_24_mode : 1; /* 24 bpp mode */
+ CARD8 alt_color_mode : 4; /* feature connector mode */
+ } _extended_sequencer_b_s;
+ CARD8 _extended_sequencer_b; /* SRB */
+ } _extended_sequencer_b_u;
+
+#define extended_sequencer_b _extended_sequencer_b_u._extended_sequencer_b
+
+ union extended_sequencer_d_u {
+ struct {
+ CARD8 enable_feature : 1;
+ CARD8 lpb_feature : 1;
+ CARD8 : 2;
+ CARD8 _hsync_control : 2;
+ CARD8 _vsync_control : 2;
+ } _extended_sequencer_d_s;
+ CARD8 _extended_sequencer_d;
+ } _extended_sequencer_d_u;
+
+#define extended_sequencer_d _extended_sequencer_d_u._extended_sequencer_d
+#define hsync_control _extended_sequencer_d_u._extended_sequencer_d_s._hsync_control
+#define vsync_control _extended_sequencer_d_u._extended_sequencer_d_s._vsync_control
+
+ union {
+ struct {
+ CARD8 _dclk_pll_n : 5;
+ CARD8 _dclk_pll_r : 2;
+ CARD8 : 1;
+ } _dclk_value_low_s;
+ CARD8 _dclk_value_low; /* SR12 */
+ } _dclk_value_low_u;
+
+#define dclk_value_low _dclk_value_low_u._dclk_value_low
+#define dclk_pll_n_trio _dclk_value_low_u._dclk_value_low_s._dclk_pll_n
+#define dclk_pll_r_trio _dclk_value_low_u._dclk_value_low_s._dclk_pll_r
+
+ union {
+ struct {
+ CARD8 _dclk_pll_m : 7;
+ CARD8 : 1;
+ } _dclk_value_high_s;
+ CARD8 _dclk_value_high; /* SR13 */
+ } _dclk_value_high_u;
+
+#define dclk_value_high _dclk_value_high_u._dclk_value_high
+#define dclk_pll_m_trio _dclk_value_high_u._dclk_value_high_s._dclk_pll_m
+
+ union {
+ struct {
+ CARD8 _mfrq_en : 1;
+ CARD8 _dfrq_en : 1;
+ CARD8 _mclk_out : 1;
+ CARD8 _vclk_out : 1;
+ CARD8 _dclk_over_2 : 1;
+ CARD8 _clk_load : 1;
+ CARD8 _dclk_invert : 1;
+ CARD8 _ena_2_cycle_write : 1;
+ } _control_2_s;
+ CARD8 _control_2; /* SR15 */
+ } _control_2_u;
+
+#define control_2 _control_2_u._control_2
+#define mfrq_en _control_2_u._control_2_s._mfrq_en
+#define dfrq_en _control_2_u._control_2_s._dfrq_en
+#define mclk_out _control_2_u._control_2_s._mclk_out
+#define vclk_out _control_2_u._control_2_s._vclk_out
+#define dclk_over_2 _control_2_u._control_2_s._dclk_over_2
+#define clk_load _control_2_u._control_2_s._clk_load
+#define dclk_invert _control_2_u._control_2_s._dclk_invert
+#define ena_2_cycle_write _control_2_u._control_2_s._ena_2_cycle_write
+
+ union {
+ struct {
+ CARD8 : 5;
+ CARD8 _dac_power_down : 1;
+ CARD8 _lut_write_control : 1;
+ CARD8 _enable_clock_double : 1;
+ } _ramdac_control_s;
+ CARD8 _ramdac_control; /* SR18 */
+ } _ramdac_control_u;
+
+#define ramdac_control _ramdac_control_u._ramdac_control
+#define enable_clock_double _ramdac_control_u._ramdac_control_s._enable_clock_double
+
+ union {
+ struct {
+ CARD8 _dclk_pll_n : 6;
+ CARD8 _dclk_pll_r : 2;
+ } _dclk_value_low_s;
+ CARD8 _dclk_value_low; /* SR36 */
+ } _dclk_value_low_savage_u;
+
+#define dclk_value_low_savage _dclk_value_low_savage_u._dclk_value_low
+#define dclk_pll_n_savage_0_5 _dclk_value_low_savage_u._dclk_value_low_s._dclk_pll_n
+#define dclk_pll_r_savage_0_1 _dclk_value_low_savage_u._dclk_value_low_s._dclk_pll_r
+
+ CARD8 dclk_pll_m0_savage_0_7; /* SR37 */
+ CARD8 dclk_pll_m1_savage_0_7; /* SR38 */
+
+ struct {
+ CARD8 _dclk_pll_m : 8;
+ } _dclk_value_high_s_savage;
+
+ union {
+ struct {
+ CARD8 _dclk_select : 1;
+ CARD8 : 1;
+ CARD8 _dclk_pll_r_2 : 1;
+ CARD8 _dclk_pll_m_8 : 1;
+ CARD8 _dclk_pll_n_6 : 1;
+ CARD8 _pce : 1;
+ CARD8 _ccg : 1;
+ CARD8 _csp : 1;
+ } _extended_seq_39_s;
+ CARD8 _extended_seq_39; /* SR39 */
+ } _extended_seq_39_u;
+
+#define extended_seq_39 _extended_seq_39_u._extended_seq_39
+#define dclk_pll_select_savage _extended_seq_39_u._extended_seq_39_s._dclk_select
+#define dclk_pll_r_savage_2 _extended_seq_39_u._extended_seq_39_s._dclk_pll_r_2
+#define dclk_pll_m_savage_8 _extended_seq_39_u._extended_seq_39_s._dclk_pll_m_8
+#define dclk_pll_n_savage_6 _extended_seq_39_u._extended_seq_39_s._dclk_pll_n_6
+
+ /* computed values */
+ CARD16 ge_screen_pitch;
+ CARD8 bits_per_pixel;
+ CARD8 depth;
+ CARD8 double_pixel_mode;
+ CARD16 pixel_width;
+} S3Crtc;
+
+#define crtc_v_total(crtc) ((crtc)->v_total_0_7 | \
+ ((crtc)->v_total_8 << 8) | \
+ ((crtc)->v_total_9 << 9) | \
+ ((crtc)->v_total_10 << 10))
+
+#define crtc_set_v_total(crtc,v) { \
+ ((crtc))->v_total_0_7 = (v); \
+ ((crtc))->v_total_8 = (v) >> 8; \
+ ((crtc))->v_total_9 = (v) >> 9; \
+ ((crtc))->v_total_10 = (v) >> 10; \
+}
+
+#define crtc_v_display_end(crtc) ((crtc)->v_display_end_0_7 | \
+ ((crtc)->v_display_end_8 << 8) | \
+ ((crtc)->v_display_end_9 << 9) | \
+ ((crtc)->v_display_end_10 << 10))
+
+#define crtc_set_v_display_end(crtc,v) {\
+ ((crtc))->v_display_end_0_7 = (v); \
+ ((crtc))->v_display_end_8 = (v) >> 8; \
+ ((crtc))->v_display_end_9 = (v) >> 9; \
+ ((crtc))->v_display_end_10 = (v) >> 10; \
+}
+
+#define crtc_v_retrace_start(crtc) ((crtc)->v_retrace_start_0_7 | \
+ ((crtc)->v_retrace_start_8 << 8) | \
+ ((crtc)->v_retrace_start_9 << 9) | \
+ ((crtc)->v_retrace_start_10 << 10))
+
+#define crtc_set_v_retrace_start(crtc,v) {\
+ ((crtc))->v_retrace_start_0_7 = (v); \
+ ((crtc))->v_retrace_start_8 = (v) >> 8; \
+ ((crtc))->v_retrace_start_9 = (v) >> 9; \
+ ((crtc))->v_retrace_start_10 = (v) >> 10; \
+}
+
+#define crtc_v_blank_start(crtc) ((crtc)->v_blank_start_0_7 | \
+ ((crtc)->v_blank_start_8 << 8) | \
+ ((crtc)->v_blank_start_9 << 9) | \
+ ((crtc)->v_blank_start_10 << 10))
+
+#define crtc_set_v_blank_start(crtc,v) {\
+ ((crtc))->v_blank_start_0_7 = (v); \
+ ((crtc))->v_blank_start_8 = (v) >> 8; \
+ ((crtc))->v_blank_start_9 = (v) >> 9; \
+ ((crtc))->v_blank_start_10 = (v) >> 10; \
+}
+
+#define crtc_h_total(crtc) ((crtc)->h_total_0_7 | \
+ ((crtc)->h_total_8 << 8))
+
+#define crtc_set_h_total(crtc,v) {\
+ ((crtc))->h_total_0_7 = (v); \
+ ((crtc))->h_total_8 = (v) >> 8; \
+}
+
+#define crtc_h_display_end(crtc) ((crtc)->h_display_end_0_7 | \
+ ((crtc)->h_display_end_8 << 8))
+
+#define crtc_set_h_display_end(crtc,v) {\
+ ((crtc))->h_display_end_0_7 = (v); \
+ ((crtc))->h_display_end_8 = (v) >> 8; \
+}
+
+#define crtc_h_blank_start(crtc) ((crtc)->h_blank_start_0_7 | \
+ ((crtc)->h_blank_start_8 << 8))
+
+#define crtc_set_h_blank_start(crtc,v) {\
+ ((crtc))->h_blank_start_0_7 = (v); \
+ ((crtc))->h_blank_start_8 = (v) >> 8; \
+}
+
+#define crtc_h_blank_end(crtc) ((crtc)->h_blank_end_0_4 | \
+ ((crtc)->h_blank_end_5 << 5))
+
+#define crtc_set_h_blank_end(crtc,v) {\
+ ((crtc))->h_blank_end_0_4 = (v); \
+ ((crtc))->h_blank_end_5 = (v) >> 5; \
+}
+
+#define crtc_h_sync_start(crtc) ((crtc)->h_sync_start_0_7 | \
+ ((crtc)->h_sync_start_8 << 8))
+
+#define crtc_set_h_sync_start(crtc,v) {\
+ ((crtc))->h_sync_start_0_7 = (v); \
+ ((crtc))->h_sync_start_8 = (v) >> 8; \
+}
+
+#define crtc_h_sync_end(crtc) ((crtc)->h_sync_end_0_4)
+
+#define crtc_set_h_sync_end(crtc,v) {\
+ ((crtc))->h_sync_end_0_4 = (v); \
+}
+
+#define crtc_screen_off(crtc) ((crtc)->screen_off_0_7 | \
+ (((crtc)->screen_off_8_9 ? \
+ ((crtc))->screen_off_8_9 : \
+ ((crtc))->old_screen_off_8) << 8))
+
+#define crtc_set_screen_off(crtc,v) {\
+ ((crtc))->screen_off_0_7 = (v); \
+ ((crtc))->old_screen_off_8 = 0; \
+ ((crtc))->screen_off_8_9 = (v) >> 8; \
+}
+
+#define crtc_ge_screen_width(crtc) ((crtc)->ge_screen_width_0_1 | \
+ ((crtc)->ge_screen_width_2 << 2))
+
+#define crtc_set_ge_screen_width(crtc,v) { \
+ (crtc)->ge_screen_width_0_1 = (v); \
+ (crtc)->ge_screen_width_2 = (v) >> 2; \
+}
+
+#define crtc_h_start_fifo_fetch(crtc) ((crtc)->h_start_fifo_fetch_0_7 | \
+ ((crtc)->h_start_fifo_fetch_8 << 8))
+
+#define crtc_set_h_start_fifo_fetch(crtc,v) {\
+ (crtc)->h_start_fifo_fetch_0_7 = (v); \
+ (crtc)->h_start_fifo_fetch_8 = (v) >> 8; \
+}
+
+#define crtc_start_address(crtc) ((crtc)->start_address_0_7 | \
+ ((crtc)->start_address_8_15 << 8) | \
+ ((crtc)->start_address_16_19 << 16))
+
+#define crtc_set_start_address(crtc,v) {\
+ (crtc)->start_address_0_7 = (v); \
+ (crtc)->start_address_8_15 = (v) >> 8; \
+ (crtc)->start_address_16_19 = (v) >> 16; \
+}
+
+#define crtc_line_compare(crtc) ((crtc)->line_compare_0_7 | \
+ ((crtc)->line_compare_8 << 8) | \
+ ((crtc)->line_compare_9 << 9) | \
+ ((crtc)->line_compare_10 << 10))
+
+#define crtc_set_line_compare(crtc,v) { \
+ ((crtc))->line_compare_0_7 = (v); \
+ ((crtc))->line_compare_8 = (v) >> 8; \
+ ((crtc))->line_compare_9 = (v) >> 9; \
+ ((crtc))->line_compare_10 = (v) >> 10; \
+}
+
+
+#define GetCrtc(s3,i) _s3ReadIndexRegister (&(s3)->crt_vga_3d4, (i))
+#define PutCrtc(s3,i,v) _s3WriteIndexRegister (&(s3)->crt_vga_3d4, (i), (v))
+
+#define GetSrtc(s3,i) _s3ReadIndexRegister (&(s3)->crt_vga_3c4, (i))
+#define PutSrtc(s3,i,v) _s3WriteIndexRegister (&(s3)->crt_vga_3c4, (i), (v))
+
+#define S3_CLOCK_REF 14318 /* KHz */
+
+#define S3_CLOCK(m,n,r) (S3_CLOCK_REF * ((m) + 2) / (((n) + 2) * (1 << (r))))
+
+#if PLATFORM == 200
+#define S3_MAX_CLOCK 80000 /* KHz */
+#endif
+#if PLATFORM == 300
+#define S3_MAX_CLOCK 135000 /* KHz */
+#endif
+
+typedef struct _s3Timing {
+ /* label */
+ int horizontal;
+ int vertical;
+ int rate;
+ /* horizontal timing */
+ int hfp; /* front porch */
+ int hbp; /* back porch */
+ int hblank; /* blanking */
+ /* vertical timing */
+ int vfp; /* front porch */
+ int vbp; /* back porch */
+ int vblank; /* blanking */
+ /* clock values */
+ int dac_m;
+ int dac_n;
+ int dac_r;
+} S3Timing;
+
+typedef struct _s3Save {
+ CARD8 cursor_fg;
+ CARD8 cursor_bg;
+ CARD8 lock1;
+ CARD8 lock2;
+ CARD8 locksrtc;
+ CARD8 clock_mode;
+ CARD32 alt_mix;
+ CARD32 write_mask;
+ CARD32 fg;
+ CARD32 bg;
+ S3Crtc crtc;
+} S3Save;
+
+typedef struct _s3CardInfo {
+ S3Ptr s3; /* pointer to register structure */
+ int memory; /* amount of memory */
+ CARD8 *frameBuffer; /* pointer to frame buffer */
+ CARD8 *registers; /* pointer to register map */
+ S3Save save;
+ Bool savage;
+} S3CardInfo;
+
+typedef struct _s3ScreenInfo {
+ CARD8 *cursor_base; /* pointer to cursor area */
+ CARD8 *offscreen; /* pointer to offscreen area */
+ int offscreen_y; /* top y coordinate of offscreen area */
+ int offscreen_x; /* top x coordinate of offscreen area */
+ int offscreen_width; /* width of offscreen area */
+ int offscreen_height; /* height of offscreen area */
+ S3Cursor cursor;
+ S3Patterns patterns;
+} S3ScreenInfo;
+
+#define LockS3(s3c)
+#define UnlockS3(s3c)
+
+#define getS3CardInfo(kd) ((S3CardInfo *) ((kd)->card->driver))
+#define s3CardInfo(kd) S3CardInfo *s3c = getS3CardInfo(kd)
+
+#define getS3ScreenInfo(kd) ((S3ScreenInfo *) ((kd)->screen->driver))
+#define s3ScreenInfo(kd) S3ScreenInfo *s3s = getS3ScreenInfo(kd)
+
+Bool s3CardInit (KdCardInfo *);
+Bool s3ScreenInit (KdScreenInfo *);
+void s3Enable (ScreenPtr pScreen);
+void s3Disable (ScreenPtr pScreen);
+void s3Fini (ScreenPtr pScreen);
+
+Bool s3CursorInit (ScreenPtr pScreen);
+void s3CursorEnable (ScreenPtr pScreen);
+void s3CursorDisable (ScreenPtr pScreen);
+void s3CursorFini (ScreenPtr pScreen);
+void s3RecolorCursor (ScreenPtr pScreen, int ndef, xColorItem *pdefs);
+
+Bool s3DrawInit (ScreenPtr pScreen);
+void s3DrawEnable (ScreenPtr pScreen);
+void s3DrawDisable (ScreenPtr pScreen);
+void s3DrawFini (ScreenPtr pScreen);
+
+void s3GetColors (ScreenPtr pScreen, int ndef, xColorItem *pdefs);
+void s3PutColors (ScreenPtr pScreen, int ndef, xColorItem *pdefs);
+
+void S3InitCard (KdCardAttr *attr);
+
+void s3GetClock (S3Timing *t, int *Mp, int *Np, int *Rp, int maxM, int maxN, int maxR);
+
+CARD8 _s3ReadIndexRegister (VOL8 *base, CARD8 index);
+void _s3WriteIndexRegister (VOL8 *base, CARD8 index, CARD8 value);
+
+extern KdCardFuncs s3Funcs;
+
+/*
+ * Wait for the begining of the retrace interval
+ */
+
+#define S3_RETRACE_LOOP_CHECK if (++_loop_count > 300000) {\
+ DRAW_DEBUG ((DEBUG_FAILURE, "S3 wait loop failed at %s:%d", \
+ __FILE__, __LINE__)); \
+ break; \
+}
+
+#define _s3WaitVRetrace(s3) { \
+ VOL8 *_status = &s3->crt_vga_status_1; \
+ int _loop_count; \
+ DRAW_DEBUG ((DEBUG_CRTC, "_s3WaitVRetrace 0x%x", *_status)); \
+ _loop_count = 0; \
+ while ((*_status & VGA_STATUS_1_VSY) != 0) S3_RETRACE_LOOP_CHECK; \
+ _loop_count = 0; \
+ while ((*_status & VGA_STATUS_1_VSY) == 0) S3_RETRACE_LOOP_CHECK; \
+}
+/*
+ * Wait for the begining of the retrace interval
+ */
+#define _s3WaitVRetraceEnd(s3) { \
+ VOL8 *_status = &s3->crt_vga_status_1; \
+ int _loop_count; \
+ DRAW_DEBUG ((DEBUG_CRTC, "_s3WaitVRetraceEnd 0x%x", *_status)); \
+ _loop_count = 0; \
+ while ((*_status & VGA_STATUS_1_VSY) == 0) S3_RETRACE_LOOP_CHECK; \
+ _loop_count = 0; \
+ while ((*_status & VGA_STATUS_1_VSY) != 0) S3_RETRACE_LOOP_CHECK; \
+}
+
+/*
+ * This extension register must contain a magic bit pattern to enable
+ * the remaining extended registers
+ */
+
+#define _s3UnlockExt(s3) _s3WriteIndexRegister (&s3->crt_vga_3d4, 0x39, 0xa0)
+#define _s3LockExt(s3) _s3WriteIndexRegister (&s3->crt_vga_3d4, 0x39, 0x00)
+
+#define S3_CURSOR_WIDTH 64
+#define S3_CURSOR_HEIGHT 64
+#define S3_CURSOR_SIZE ((S3_CURSOR_WIDTH * S3_CURSOR_HEIGHT + 7) / 8)
+
+#define S3_TILE_SIZE 8
+
+/*
+ * Ok, so the S3 is broken -- it expects bitmaps to come MSB bit order,
+ * but it's willing to take them in LSB byte order. These macros
+ * flip bits around without flipping bytes. Instead of using a table
+ * and burning memory bandwidth, do them in place with the CPU.
+ */
+
+/* The MIPS compiler automatically places these constants in registers */
+#define S3InvertBits32(v) { \
+ v = ((v & 0x55555555) << 1) | ((v >> 1) & 0x55555555); \
+ v = ((v & 0x33333333) << 2) | ((v >> 2) & 0x33333333); \
+ v = ((v & 0x0f0f0f0f) << 4) | ((v >> 4) & 0x0f0f0f0f); \
+}
+
+#define S3InvertBits16(v) { \
+ v = ((v & 0x5555) << 1) | ((v >> 1) & 0x5555); \
+ v = ((v & 0x3333) << 2) | ((v >> 2) & 0x3333); \
+ v = ((v & 0x0f0f) << 4) | ((v >> 4) & 0x0f0f); \
+}
+
+#define S3InvertBits8(v) { \
+ v = ((v & 0x55) << 1) | ((v >> 1) & 0x55); \
+ v = ((v & 0x33) << 2) | ((v >> 2) & 0x33); \
+ v = ((v & 0x0f) << 4) | ((v >> 4) & 0x0f); \
+}
+
+#endif /* _S3_H_ */
diff --git a/hw/kdrive/trio/s3clock.c b/hw/kdrive/trio/s3clock.c
new file mode 100644
index 000000000..1c4f893dd
--- /dev/null
+++ b/hw/kdrive/trio/s3clock.c
@@ -0,0 +1,89 @@
+/*
+ * $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 "s3.h"
+
+/*
+ * Clock synthesis:
+ *
+ * f_out = f_ref * ((M + 2) / ((N + 2) * (1 << R)))
+ *
+ * Constraints:
+ *
+ * 1. 135MHz <= f_ref * ((M + 2) / (N + 2)) <= 270 MHz
+ * 2. N >= 1
+ *
+ * Vertical refresh rate = clock / ((hsize + hblank) * (vsize + vblank))
+ * Horizontal refresh rate = clock / (hsize + hblank)
+ */
+
+/* all in kHz */
+#define MIN_VCO 180000.0
+#define MAX_VCO 360000.0
+
+void
+s3GetClock (S3Timing *t, int *Mp, int *Np, int *Rp, int maxM, int maxN, int maxR)
+{
+ int M, N, R, bestM, bestN;
+ int f_vco, f_out;
+ int target;
+ int err, abserr, besterr;
+
+ target = ((t->horizontal + t->hblank) *
+ (t->vertical + t->vblank) *
+ t->rate) / 1000;
+ /*
+ * Compute correct R value to keep VCO in range
+ */
+ for (R = 0; R <= maxR; R++)
+ {
+ f_vco = target * (1 << R);
+ if (MIN_VCO <= f_vco && f_vco < MAX_VCO)
+ break;
+ }
+
+ /* M = f_out / f_ref * ((N + 2) * (1 << R)); */
+ besterr = target;
+ for (N = 0; N <= maxN; N++)
+ {
+ M = (target * (N + 2) * (1 << R) + (S3_CLOCK_REF/2)) / S3_CLOCK_REF - 2;
+ if (0 <= M && M <= maxM)
+ {
+ f_out = S3_CLOCK(M,N,R);
+ err = target - f_out;
+ if (err < 0)
+ err = -err;
+ if (err < besterr)
+ {
+ besterr = err;
+ bestM = M;
+ bestN = N;
+ }
+ }
+ }
+ *Mp = bestM;
+ *Np = bestN;
+ *Rp = R;
+}
diff --git a/hw/kdrive/trio/s3cmap.c b/hw/kdrive/trio/s3cmap.c
new file mode 100644
index 000000000..c8bf633ed
--- /dev/null
+++ b/hw/kdrive/trio/s3cmap.c
@@ -0,0 +1,70 @@
+/*
+ * $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 "s3.h"
+
+void
+s3GetColors (ScreenPtr pScreen, int ndef, xColorItem *pdefs)
+{
+ KdScreenPriv(pScreen);
+ s3CardInfo(pScreenPriv);
+ S3Ptr s3 = s3c->s3;
+ VOL8 *dac_rd_ad = &s3->crt_vga_dac_rd_ad;
+ VOL8 *dac_data = &s3->crt_vga_dac_data;
+
+ LockS3 (s3c);
+ while (ndef--)
+ {
+ *dac_rd_ad = pdefs->pixel;
+ pdefs->red = *dac_data << 10;
+ pdefs->green = *dac_data << 10;
+ pdefs->blue = *dac_data << 10;
+ pdefs++;
+ }
+ UnlockS3(s3c);
+}
+
+void
+s3PutColors (ScreenPtr pScreen, int ndef, xColorItem *pdefs)
+{
+ KdScreenPriv(pScreen);
+ s3CardInfo(pScreenPriv);
+ S3Ptr s3 = s3c->s3;
+ VOL8 *dac_wt_ad = &s3->crt_vga_dac_wt_ad;
+ VOL8 *dac_data = &s3->crt_vga_dac_data;
+
+ LockS3(s3c);
+ _s3WaitVRetrace (s3);
+ while (ndef--)
+ {
+ *dac_wt_ad = pdefs->pixel;
+ *dac_data = pdefs->red >> 10;
+ *dac_data = pdefs->green >> 10;
+ *dac_data = pdefs->blue >> 10;
+ pdefs++;
+ }
+ UnlockS3(s3c);
+}
+
diff --git a/hw/kdrive/trio/s3curs.c b/hw/kdrive/trio/s3curs.c
new file mode 100644
index 000000000..6cbdd4f7a
--- /dev/null
+++ b/hw/kdrive/trio/s3curs.c
@@ -0,0 +1,433 @@
+/*
+ * $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 "s3.h"
+#include "cursorstr.h"
+
+#define SetupCursor(s) KdScreenPriv(s); \
+ s3CardInfo(pScreenPriv); \
+ s3ScreenInfo(pScreenPriv); \
+ S3Ptr s3 = s3c->s3; \
+ S3Cursor *pCurPriv = &s3s->cursor
+
+static void
+_s3MoveCursor (ScreenPtr pScreen, int x, int y)
+{
+ SetupCursor(pScreen);
+ CARD8 xlow, xhigh, ylow, yhigh;
+ CARD8 xoff, yoff;
+
+ x -= pCurPriv->xhot;
+ xoff = 0;
+ if (x < 0)
+ {
+ xoff = -x;
+ x = 0;
+ }
+ y -= pCurPriv->yhot;
+ yoff = 0;
+ if (y < 0)
+ {
+ yoff = -y;
+ y = 0;
+ }
+ xlow = (CARD8) x;
+ xhigh = (CARD8) (x >> 8);
+ ylow = (CARD8) y;
+ yhigh = (CARD8) (y >> 8);
+
+
+ /* This is the recommended order to move the cursor */
+
+ _s3WriteIndexRegister (&s3->crt_vga_3d4, 0x46, xhigh);
+ _s3WriteIndexRegister (&s3->crt_vga_3d4, 0x47, xlow);
+ _s3WriteIndexRegister (&s3->crt_vga_3d4, 0x49, ylow);
+ _s3WriteIndexRegister (&s3->crt_vga_3d4, 0x4e, xoff);
+ _s3WriteIndexRegister (&s3->crt_vga_3d4, 0x4f, yoff);
+ _s3WriteIndexRegister (&s3->crt_vga_3d4, 0x48, yhigh);
+}
+
+static void
+s3MoveCursor (ScreenPtr pScreen, int x, int y)
+{
+ SetupCursor (pScreen);
+
+ if (!pCurPriv->has_cursor)
+ return;
+
+ if (!pScreenPriv->enabled)
+ return;
+
+ LockS3(s3c);
+ _s3UnlockExt(s3);
+ _s3MoveCursor (pScreen, x, y);
+ _s3LockExt(s3);
+ UnlockS3(s3c);
+}
+
+static void
+s3AllocCursorColors (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+ CursorPtr pCursor = pCurPriv->pCursor;
+ xColorItem sourceColor, maskColor;
+
+ /*
+ * Set these to an invalid pixel value so that
+ * when the store colors comes through, the cursor
+ * won't get recolored
+ */
+ pCurPriv->source = ~0;
+ pCurPriv->mask = ~0;
+ /*
+ * XXX S3 bug workaround; s3 chip doesn't use RGB values from
+ * the cursor color registers as documented, rather it uses
+ * them to index the DAC. This is in the errata though.
+ */
+ sourceColor.red = pCursor->foreRed;
+ sourceColor.green = pCursor->foreGreen;
+ sourceColor.blue = pCursor->foreBlue;
+ FakeAllocColor(pScreenPriv->pInstalledmap, &sourceColor);
+ maskColor.red = pCursor->backRed;
+ maskColor.green = pCursor->backGreen;
+ maskColor.blue = pCursor->backBlue;
+ FakeAllocColor(pScreenPriv->pInstalledmap, &maskColor);
+ FakeFreeColor(pScreenPriv->pInstalledmap, sourceColor.pixel);
+ FakeFreeColor(pScreenPriv->pInstalledmap, maskColor.pixel);
+
+ pCurPriv->source = sourceColor.pixel;
+ pCurPriv->mask = maskColor.pixel;
+ switch (pScreenPriv->screen->bitsPerPixel) {
+ case 4:
+ pCurPriv->source |= pCurPriv->source << 4;
+ pCurPriv->mask |= pCurPriv->mask << 4;
+ case 8:
+ pCurPriv->source |= pCurPriv->source << 8;
+ pCurPriv->mask |= pCurPriv->mask << 8;
+ case 16:
+ pCurPriv->source |= pCurPriv->source << 16;
+ pCurPriv->mask |= pCurPriv->mask << 16;
+ }
+}
+
+static void
+_s3SetCursorColors (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+ /* set foreground */
+ /* Reset cursor color stack pointers */
+ (void) _s3ReadIndexRegister(&s3->crt_vga_3d4, 0x45);
+ _s3WriteIndexRegister (&s3->crt_vga_3d4, 0x4a, pCurPriv->source);
+ _s3WriteIndexRegister (&s3->crt_vga_3d4, 0x4a, pCurPriv->source >> 8);
+ _s3WriteIndexRegister (&s3->crt_vga_3d4, 0x4a, pCurPriv->source >> 16);
+
+ /* set background */
+ /* Reset cursor color stack pointers */
+ (void) _s3ReadIndexRegister(&s3->crt_vga_3d4, 0x45);
+ _s3WriteIndexRegister (&s3->crt_vga_3d4, 0x4b, pCurPriv->mask);
+ _s3WriteIndexRegister (&s3->crt_vga_3d4, 0x4b, pCurPriv->mask >> 8);
+ _s3WriteIndexRegister (&s3->crt_vga_3d4, 0x4b, pCurPriv->mask >> 16);
+}
+
+void
+s3RecolorCursor (ScreenPtr pScreen, int ndef, xColorItem *pdef)
+{
+ SetupCursor (pScreen);
+ CursorPtr pCursor = pCurPriv->pCursor;
+ xColorItem sourceColor, maskColor;
+
+ if (!pCurPriv->has_cursor || !pCursor)
+ return;
+
+ if (!pScreenPriv->enabled)
+ return;
+
+ if (pdef)
+ {
+ while (ndef)
+ {
+ if (pdef->pixel == pCurPriv->source ||
+ pdef->pixel == pCurPriv->mask)
+ break;
+ ndef--;
+ }
+ if (!ndef)
+ return;
+ }
+ s3AllocCursorColors (pScreen);
+ LockS3 (s3c);
+ _s3UnlockExt(s3);
+ _s3SetCursorColors (pScreen);
+ _s3LockExt (s3);
+ UnlockS3 (s3c);
+}
+
+static void
+s3LoadCursor (ScreenPtr pScreen, int x, int y)
+{
+ SetupCursor(pScreen);
+ CursorPtr pCursor = pCurPriv->pCursor;
+ CursorBitsPtr bits = pCursor->bits;
+ int w, h;
+ unsigned char r[2], g[2], b[2];
+ unsigned short *ram, *msk, *mskLine, *src, *srcLine;
+ unsigned short and, xor;
+ int i, j;
+ int cursor_address;
+ int wsrc;
+ unsigned char ramdac_control_;
+
+ /*
+ * Allocate new colors
+ */
+ s3AllocCursorColors (pScreen);
+
+ /*
+ * Lock S3 so the cursor doesn't move while we're setting it
+ */
+ LockS3(s3c);
+
+ pCurPriv->pCursor = pCursor;
+ pCurPriv->xhot = pCursor->bits->xhot;
+ pCurPriv->yhot = pCursor->bits->yhot;
+
+ /*
+ * Stick new image into cursor memory
+ */
+ ram = (unsigned short *) s3s->cursor_base;
+ mskLine = (unsigned short *) bits->mask;
+ srcLine = (unsigned short *) bits->source;
+
+ h = bits->height;
+ if (h > S3_CURSOR_HEIGHT)
+ h = S3_CURSOR_HEIGHT;
+
+ wsrc = BitmapBytePad(bits->width) / 2; /* words per line */
+
+ for (i = 0; i < S3_CURSOR_HEIGHT; i++) {
+ msk = mskLine;
+ src = srcLine;
+ mskLine += wsrc;
+ srcLine += wsrc;
+ for (j = 0; j < S3_CURSOR_WIDTH / 16; j++) {
+
+ unsigned short m, s;
+
+ if (i < h && j < wsrc)
+ {
+ m = *msk++;
+ s = *src++;
+ xor = m & s;
+ and = ~m;
+ }
+ else
+ {
+ and = 0xffff;
+ xor = 0x0000;
+ }
+
+ S3InvertBits16(and);
+ *ram++ = and;
+ S3InvertBits16(xor);
+ *ram++ = xor;
+ }
+ }
+
+ _s3WaitIdle (s3);
+ _s3UnlockExt (s3);
+
+ /* Set new color */
+ _s3SetCursorColors (pScreen);
+
+ /* Enable the cursor */
+ _s3WriteIndexRegister (&s3->crt_vga_3d4, 0x45, 0x01);
+
+ /* Wait for VRetrace to make sure the position is read */
+ _s3WaitVRetrace (s3);
+
+ /* Move to new position */
+ _s3MoveCursor (pScreen, x, y);
+
+ _s3LockExt (s3);
+ UnlockS3(s3c);
+}
+
+static void
+s3UnloadCursor (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ LockS3 (s3c);
+ _s3UnlockExt(s3);
+
+ /* Disable cursor */
+ _s3WriteIndexRegister (&s3->crt_vga_3d4, 0x45, 0);
+
+ _s3LockExt(s3);
+ UnlockS3 (s3c);
+}
+
+static Bool
+s3RealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
+{
+ SetupCursor(pScreen);
+
+ if (!pScreenPriv->enabled)
+ return TRUE;
+
+ /* miRecolorCursor does this */
+ if (pCurPriv->pCursor == pCursor)
+ {
+ if (pCursor)
+ {
+ int x, y;
+
+ miPointerPosition (&x, &y);
+ s3LoadCursor (pScreen, x, y);
+ }
+ }
+ return TRUE;
+}
+
+static Bool
+s3UnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
+{
+ return TRUE;
+}
+
+static void
+s3SetCursor (ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
+{
+ SetupCursor(pScreen);
+
+ pCurPriv->pCursor = pCursor;
+
+ if (!pScreenPriv->enabled)
+ return;
+
+ if (pCursor)
+ s3LoadCursor (pScreen, x, y);
+ else
+ s3UnloadCursor (pScreen);
+}
+
+miPointerSpriteFuncRec s3PointerSpriteFuncs = {
+ s3RealizeCursor,
+ s3UnrealizeCursor,
+ s3SetCursor,
+ s3MoveCursor,
+};
+
+static void
+s3QueryBestSize (int class,
+ unsigned short *pwidth, unsigned short *pheight,
+ ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ switch (class)
+ {
+ case CursorShape:
+ if (*pwidth > pCurPriv->width)
+ *pwidth = pCurPriv->width;
+ if (*pheight > pCurPriv->height)
+ *pheight = pCurPriv->height;
+ if (*pwidth > pScreen->width)
+ *pwidth = pScreen->width;
+ if (*pheight > pScreen->height)
+ *pheight = pScreen->height;
+ break;
+ default:
+ fbQueryBestSize (class, pwidth, pheight, pScreen);
+ break;
+ }
+}
+
+Bool
+s3CursorInit (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ if (!s3s->cursor_base)
+ {
+ pCurPriv->has_cursor = FALSE;
+ return FALSE;
+ }
+
+ pCurPriv->width = S3_CURSOR_WIDTH;
+ pCurPriv->height= S3_CURSOR_HEIGHT;
+ pScreen->QueryBestSize = s3QueryBestSize;
+ miPointerInitialize (pScreen,
+ &s3PointerSpriteFuncs,
+ &kdPointerScreenFuncs,
+ FALSE);
+ pCurPriv->has_cursor = TRUE;
+ pCurPriv->pCursor = NULL;
+ return TRUE;
+}
+
+void
+s3CursorEnable (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ if (pCurPriv->has_cursor)
+ {
+ if (pCurPriv->pCursor)
+ {
+ int x, y;
+
+ miPointerPosition (&x, &y);
+ s3LoadCursor (pScreen, x, y);
+ }
+ else
+ s3UnloadCursor (pScreen);
+ }
+}
+
+void
+s3CursorDisable (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ if (!pScreenPriv->enabled)
+ return;
+
+ if (pCurPriv->has_cursor)
+ {
+ if (pCurPriv->pCursor)
+ {
+ s3UnloadCursor (pScreen);
+ }
+ }
+}
+
+void
+s3CursorFini (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ pCurPriv->pCursor = NULL;
+}
diff --git a/hw/kdrive/trio/s3stub.c b/hw/kdrive/trio/s3stub.c
new file mode 100644
index 000000000..59773f725
--- /dev/null
+++ b/hw/kdrive/trio/s3stub.c
@@ -0,0 +1,59 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999 SuSE, Inc.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+/* $XFree86: $ */
+
+#include "s3.h"
+
+void
+InitCard (char *name)
+{
+ KdCardAttr attr;
+ CARD32 count;
+
+ count = 0;
+ while (LinuxFindPci (0x5333, 0x8904, count, &attr))
+ {
+ KdCardInfoAdd (&s3Funcs, &attr, 0);
+ count++;
+ }
+}
+
+void
+InitOutput (ScreenInfo *pScreenInfo, int argc, char **argv)
+{
+ KdInitOutput (pScreenInfo, argc, argv);
+}
+
+void
+InitInput (int argc, char **argv)
+{
+ KdInitInput (&Ps2MouseFuncs, &LinuxKeyboardFuncs);
+}
+
+void
+OsVendorInit (void)
+{
+ KdOsInit (&LinuxFuncs);
+}
diff --git a/hw/kdrive/ts300/Imakefile b/hw/kdrive/ts300/Imakefile
new file mode 100644
index 000000000..d0b214f85
--- /dev/null
+++ b/hw/kdrive/ts300/Imakefile
@@ -0,0 +1,15 @@
+XCOMM $XConsortium: Imakefile /main/10 1996/12/02 10:20:33 lehors $
+XCOMM $XFree86: xc/programs/Xserver/hw/nvfb/Imakefile,v 3.8 1996/12/23 06:30:19 dawes Exp $
+#include <Server.tmpl>
+
+SRCS = ts300.c
+
+OBJS = ts300.o
+
+INCLUDES = -I../trio -I../sis530 -I.. -I. -I$(XBUILDINCDIR) -I$(FONTINCSRC) \
+ -I../../../fb -I../../../mi -I../../../include -I../../../os \
+ -I$(EXTINCSRC) -I$(XINCLUDESRC)
+
+NormalLibraryObjectRule()
+NormalLibraryTarget(ts300,$(OBJS))
+DependTarget()
diff --git a/hw/kdrive/ts300/ts300.c b/hw/kdrive/ts300/ts300.c
new file mode 100644
index 000000000..6e3778db0
--- /dev/null
+++ b/hw/kdrive/ts300/ts300.c
@@ -0,0 +1,131 @@
+/*
+ * $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 "kdrive.h"
+
+extern KdCardFuncs sisFuncs;
+extern KdCardFuncs s3Funcs;
+
+/*
+ * Kludgy code to parse the ascii /proc/pci file as the TS300
+ * is running a 2.0 kernel
+ */
+BOOL
+HasPCI (char *name, KdCardAttr *attr)
+{
+ FILE *f;
+ char line[1024];
+ BOOL waiting;
+ BOOL found = FALSE;
+ char *mem;
+
+ f = fopen ("/proc/pci", "r");
+ if (!f)
+ return FALSE;
+ waiting = FALSE;
+ attr->naddr = 0;
+ while (fgets (line, sizeof (line), f))
+ {
+ if (waiting)
+ {
+
+ if (mem = strstr (line, "memory at "))
+ {
+ mem += strlen ("memory at ");
+ attr->address[attr->naddr++] = strtoul (mem, NULL, 0);
+ found = TRUE;
+ }
+ else if (mem = strstr (line, "I/O at "))
+ {
+ mem += strlen ("I/O at ");
+ attr->io = strtoul (mem, NULL, 0);
+ found = TRUE;
+ }
+ else if (strstr (line, "Bus") && strstr (line, "device") &&
+ strstr (line, "function"))
+ break;
+ }
+ else if (strstr (line, "VGA compatible controller"))
+ {
+ if (strstr (line, name))
+ waiting = TRUE;
+ }
+ }
+ fclose (f);
+ return found;
+}
+
+typedef struct _PCICard {
+ char *user;
+ char *name;
+ KdCardFuncs *funcs;
+} PCICard;
+
+PCICard PCICards[] = {
+ "sis", "Silicon Integrated Systems", &sisFuncs,
+ "s3", "S3 Inc.", &s3Funcs,
+};
+
+#define NUM_PCI_CARDS (sizeof (PCICards) / sizeof (PCICards[0]))
+
+void
+InitCard (char *name)
+{
+ KdCardInfo *card;
+ CARD32 fb;
+ int i;
+ KdCardAttr attr;
+
+ for (i = 0; i < NUM_PCI_CARDS; i++)
+ {
+ if (!name || !strcmp (name, PCICards[i].user))
+ {
+ if (HasPCI (PCICards[i].name, &attr))
+ {
+ KdCardInfoAdd (PCICards[i].funcs, &attr, 0);
+ return;
+ }
+ }
+ }
+}
+
+void
+InitOutput (ScreenInfo *pScreenInfo, int argc, char **argv)
+{
+ KdInitOutput (pScreenInfo, argc, argv);
+}
+
+void
+InitInput (int argc, char **argv)
+{
+ KdInitInput (&Ps2MouseFuncs, &LinuxKeyboardFuncs);
+}
+
+void
+OsVendorInit (void)
+{
+ KdOsInit (&LinuxFuncs);
+}
+