summaryrefslogtreecommitdiff
path: root/hw/kdrive/sis530
diff options
context:
space:
mode:
Diffstat (limited to 'hw/kdrive/sis530')
-rw-r--r--hw/kdrive/sis530/Imakefile15
-rw-r--r--hw/kdrive/sis530/sis.c953
-rw-r--r--hw/kdrive/sis530/sis.h1152
-rw-r--r--hw/kdrive/sis530/sisclock.c232
-rw-r--r--hw/kdrive/sis530/siscmap.c64
-rw-r--r--hw/kdrive/sis530/siscurs.c364
-rw-r--r--hw/kdrive/sis530/sisdraw.c1656
-rw-r--r--hw/kdrive/sis530/sisdraw.h183
-rw-r--r--hw/kdrive/sis530/sisio.c30
-rw-r--r--hw/kdrive/sis530/sisstub.c53
10 files changed, 4702 insertions, 0 deletions
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);
+}