diff options
Diffstat (limited to 'hw/kdrive')
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); +} + |