diff options
author | Dirk Hohndel <dirk.hohndel@intel.com> | 1999-11-19 13:54:06 +0000 |
---|---|---|
committer | Dirk Hohndel <dirk.hohndel@intel.com> | 1999-11-19 13:54:06 +0000 |
commit | f13b792a3a8d307a18cd6a41aa5a06622009e42f (patch) | |
tree | 5d7e7eb1dd3d69a9a408d0082c031c6121d625ea /hw/kdrive/savage |
3336. Fx up new MMIO macros (#3337, Matt Grossman).xf-3_9_16fxf-3_9_16exf-3_9_16dxf-3_9_16Z
3335. Clean up compiler warnings in lib/font/bitmap (#3411, Matt Grossman).
3334. TGA fixes, add sync on green (#3410, Matt Grossman).
3333. Fix NULL pointer dereference in libXaw (#3406, Christopher Sekiya).
3332. Add Rage128 support (#3405, Rik Faith, funded by ATI).
3331. Add MTRR support for NetBSD and OpenBSD. Add new NetBSD aperture
driver (#3404, Matthieu Herrb).
3330. Xterm patch #121 (#3402, Thomas Dickey).
3329. Rendition driver bugfixes and alpha related cleanups (#3400, Dejan
Ilic, Marc Langenbach, Egbert Eich).
3328. Add void input device (#3392, Frederic Lepied).
3327. Changed the Xon serial option to be able to select xon/xoff for
input, output or both. Add support for Graphire models. Change wacom
init phase to use new Xoff option (#3391, Frederic Lepied).
3326. Change the SwapAxes option to SwapXY in elographics/microtouch driver
to match an already existing option in the Dynapro driver. Add a Focus
class capability to the elographics driver (#3395, Patrick Lecoanet).
3325. Update mouse rate handling (#3388, Harald Koenig).
3324. Fix NULL pointer dereference in misprite.c (#3380, Edward Wang).
3323. Add FBDev and ShadowFB support to glint driver. Add new option
"NoWriteBitmap" (#3383, Michel Daenzer).
3322. Update SuperProbe to handle S3 Savage4, Savage200 and clean up
Trio3D/Savage3D detection (#3382,3384 Harald Koenig).
3321. Add new framebuffer code and tiny X DDX architecture (#3379, Keith
Packard).
3320. Add DGA2 documentation (#3378, Mark Vojkovich).
3319. Update XFree86 manpage wrt -bpp/-depth/-fbbpp (#3377, Andy Isaacson).
3318. Make SuperProbe check primary cards, only (#3374, Harald Koenig).
3317. Add SilkenMouse to *BSD (#3373, Matthieu Herrb).
3316. Allow SilkenMouse to work if not all drivers of an OS support SIGIO
(#3372, Keith Packard).
3315. Fix a few problems in TGA driver and add support for backing store
and SilkenMouse (#3371, Matt Grossman).
3314. Add smarter scheduler (#3370, Keith Packard).
3313. Xterm patch #120 (#3369, Thomas Dickey).
3312. Enable xf86SetKbdRate function on Solaris 8 (#3364, David Holland).
3311. Fix some bugs and add acceleration to Rendition server (#3360, Dejan
Ilic).
3310. Make raw DDC information available as properties in the root window
(#3357, Andrew Aitchison).
3309. Fix for xf86CreateRootWindow (#3355, Andrew Aitchison).
3308. Add manpage for the chips driver (#3353, David Bateman).
3307. Update contact info (#3352, Andrew van der Stock).
3306. Add kbd rate support for Linux (#3363, Harald Koenig).
3305. Update Portuguese XKB map (#3351, Joao Esteves, Francisco Colaco).
3304. Fix text clipping in 3dfx driver (#3349, Henrik Harmsen).
3303. Fix S3 ViRGE hw cursor (#3348, Harald Koenig).
3302. Fix clipping in 3dfx driver (#3342, Daryll Strauss).
3301. Enable SilkenMouse for 3dfx driver (#3341, Henrik Harmsen).
3300. Enable SIGIO support on LynxOS (#3339, Thomas Mueller).
3299. Get TRUE defined in sigio.c. Fix xterm compile problem on ISC (#3338,
Michael Rohleder).
3298. Correct DPMS suspend/standby modes for 3dfx driver (#3336, Henrik
Harmsen)
3297. Xterm patch #119 (#3335, Thomas Dickey).
Diffstat (limited to 'hw/kdrive/savage')
-rw-r--r-- | hw/kdrive/savage/Imakefile | 15 | ||||
-rw-r--r-- | hw/kdrive/savage/s3.c | 997 | ||||
-rw-r--r-- | hw/kdrive/savage/s3.h | 545 | ||||
-rw-r--r-- | hw/kdrive/savage/s3.nick | 41 | ||||
-rw-r--r-- | hw/kdrive/savage/s3clock.c | 86 | ||||
-rw-r--r-- | hw/kdrive/savage/s3cmap.c | 67 | ||||
-rw-r--r-- | hw/kdrive/savage/s3curs.c | 418 | ||||
-rw-r--r-- | hw/kdrive/savage/s3draw.c | 2334 | ||||
-rw-r--r-- | hw/kdrive/savage/s3draw.h | 372 | ||||
-rw-r--r-- | hw/kdrive/savage/s3gc.c | 388 | ||||
-rw-r--r-- | hw/kdrive/savage/s3reg.c | 1144 | ||||
-rw-r--r-- | hw/kdrive/savage/s3reg.h | 195 | ||||
-rw-r--r-- | hw/kdrive/savage/s3rtst.c | 141 | ||||
-rw-r--r-- | hw/kdrive/savage/s3stub.c | 60 |
14 files changed, 6803 insertions, 0 deletions
diff --git a/hw/kdrive/savage/Imakefile b/hw/kdrive/savage/Imakefile new file mode 100644 index 000000000..ba7c9cc84 --- /dev/null +++ b/hw/kdrive/savage/Imakefile @@ -0,0 +1,15 @@ +XCOMM $XConsortium: Imakefile /main/10 1996/12/02 10:20:33 lehors $ +XCOMM $XFree86: xc/programs/Xserver/hw/nvfb/Imakefile,v 3.8 1996/12/23 06:30:19 dawes Exp $ +#include <Server.tmpl> + +SRCS = s3.c s3clock.c s3cmap.c s3curs.c s3draw.c s3gc.c s3reg.c s3stub.c + +OBJS = s3.o s3clock.o s3cmap.o s3curs.o s3draw.o s3gc.o s3reg.o s3stub.o + +INCLUDES = -I.. -I. -I$(XBUILDINCDIR) -I$(FONTINCSRC) \ + -I../../../fb -I../../../mi -I../../../include -I../../../os \ + -I$(EXTINCSRC) -I$(XINCLUDESRC) + +NormalLibraryObjectRule() +NormalLibraryTarget(savage,$(OBJS)) +DependTarget() diff --git a/hw/kdrive/savage/s3.c b/hw/kdrive/savage/s3.c new file mode 100644 index 000000000..bf3e2896a --- /dev/null +++ b/hw/kdrive/savage/s3.c @@ -0,0 +1,997 @@ +/* + * $Id$ + * + * Copyright 1999 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ +/* $XFree86: $ */ + +#include "s3.h" + +#define REGISTERS_OFFSET (0x1000000) +#define PACKED_OFFSET (0x8100) +#define IOMAP_OFFSET (0x8000) + +/* + * Clock synthesis: + * + * f_out = f_ref * ((M + 2) / ((N + 2) * (1 << R))) + * + * Constraints: + * + * 1. 135MHz <= f_ref * ((M + 2) / (N + 2)) <= 270 MHz + * 2. N >= 1 + * + * Vertical refresh rate = clock / ((hsize + hblank) * (vsize + vblank)) + * Horizontal refresh rate = clock / (hsize + hblank) + */ + +#define DEFAULT_S3_TIMING 1 + +S3Timing s3Timings[] = { + /* FP BP BLANK */ + /* M N R blank bios5 */ + { 640, 480, 60, + 16, 48, 160, /* horizontal 31.321 KHz */ + 10, 33, 45, /* vertical 59.568 Hz */ + 26, 0, 3, /* pixel 25.057 MHz */ + }, + + { 800, 600, 85, + 32, 152, 248, /* horizontal 53.673 KHz */ + 1, 27, 31, /* vertical 85.060 Hz */ + 108, 5, 2, /* pixel 56.249 MHz */ + }, + { 800, 600, 75, + 16, 160, 256, /* horizontal 46.891 KHz */ + 1, 21, 25, /* vertical 75.025 Hz */ + 81, 4, 2, /* pixel 49.516 MHz */ + }, + { 800, 600, 72, + 56, 64, 240, /* horizontal 48.186 KHz */ + 37, 23, 66, /* vertical 72.351 Hz */ + 26, 0, 2, /* pixel 50.113 MHz */ + }, + { 800, 600, 60, + 48, 80, 256, + 1, 23, 28, + 0, 0, 0, + }, + { 1024, 768, 85, + 48, 208, 352, /* horizontal 68.676 KHz */ + 1, 36, 40, /* vertical 84.996 Hz */ + 64, 3, 1, /* pixel 94.499 MHz */ + }, + { 1024, 768, 75, + 16, 176, 288, /* horizontal 60.022 KHz */ + 1, 28, 32, /* vertical 75.028 Hz */ + 20, 0, 1, /* pixel 78.749 MHz */ + }, + { 1024, 768, 70, + 32, 136, 304, /* horizontal 56.604 KHz */ + 2, 30, 38, /* vertical 70.227 Hz */ + 124, 1, 3, /* pixel 75.170 MHz */ + }, + { 1024, 768, 66, + 24, 144, 304, /* horizontal 53.234 KHz */ + 3, 29, 38, /* vertical 66.047 Hz */ + 77, 6, 1, /* pixel 70.695 MHz */ + }, + + { 1152, 900, 85, + 48, 208, 384, /* horizontal 79.900 KHz */ + 1, 32, 38, /* vertical 85.181 Hz */ + 118, 5, 1, /* pixel 122.726 MHz */ + }, + { 1152, 900, 75, + 32, 208, 384, /* horizontal 70.495 Khz */ + 1, 32, 38, /* vertical 75.154 Hz */ + 119, 6, 1, /* pixel 108.280 MHz */ + }, + { 1152, 900, 70, + 32, 208, 384, /* horizontal 65.251 KHz */ + 2, 32, 38, /* vertical 69.564 Hz */ + 12, 0, 0, /* pixel 100.226 MHz */ + }, + { 1152, 900, 66, + 32, 208, 384, /* horizontal 61.817 KHz */ + 1, 32, 38, /* vertical 65.903 Hz */ + 124, 17, 0, /* pixel 94.951 MHz */ + }, + { 1280, 1024, 85, + 32, 248, 416, /* horizontal 90.561 KHz */ + 1, 40, 45, /* vertical 84.717 Hz */ + 116, 9, 0, /* pixel 153.593 MHz */ + }, + { 1280, 1024, 75, + 16, 248, 408, /* horizontal 80.255 KHz */ + 1, 38, 42, /* vertical 75.285 Hz */ + 111, 4, 1, /* pixel 134.828 MHz */ + }, + { 1280, 1024, 70, + 32, 248, 400, /* horizontal 74.573 KHz */ + 0, 36, 39, /* vertical 70.153 Hz */ + 68, 2, 1, /* pixel 125.283 MHz */ + }, + { 1280, 1024, 66, + 32, 248, 400, /* horizontal 70.007 KHz */ + 0, 36, 39, /* vertical 65.858 Hz */ + 113, 5, 1, /* pixel 117.612 MHz */ + }, + { 1280, 1024, 60, + 56, 240, 408, /* horizontal 70.007 KHz */ + 1, 38, 42, /* vertical 65.858 Hz */ + 113, 5, 1, /* pixel 117.612 MHz */ + }, + { 1600, 1200, 85, + 64, 304, 560, /* horizontal 106.059 KHz */ + 1, 46, 50, /* vertical 84.847 Hz */ + 126, 6, 0, /* pixel 229.088 MHz */ + }, + { 1600, 1200, 75, + 64, 304, 560, /* horizontal 93.748 KHz */ + 1, 46, 50, /* vertical 74.999 Hz */ + 97, 5, 0, /* pixel 202.497 MHz */ + }, + { 1600, 1200, 70, + 56, 304, 588, /* horizontal 87.524 KHz */ + 1, 46, 50, /* vertical 70.019 Hz */ + 105, 6, 0, /* pixel 191.503 MHz */ + }, + { 1600, 1200, 65, + 56, 308, 524, /* horizontal 80.050 KHz */ + 1, 38, 42, /* vertical 64.453 Hz */ + 93, 6, 0, /* pixel 170.026 MHz */ + }, +}; + +#define NUM_S3_TIMINGS (sizeof (s3Timings) / sizeof (s3Timings[0])) + +static void +_s3SetBlank (S3Ptr s3, S3Vga *s3vga, Bool blank) +{ + CARD8 clock_mode; + + s3SetImm(s3vga, s3_screen_off, blank ? 1 : 0); +} + +static void +_s3SetDepth (S3Ptr s3, S3Vga *s3vga) +{ + CARD8 save_3c2; + _s3SetBlank (s3, s3vga, TRUE); + VgaFlush(&s3vga->card); + VgaSetImm (&s3vga->card, s3_clock_load_imm, 1); + VgaSetImm(&s3vga->card, s3_clock_load_imm, 0); + _s3SetBlank (s3, s3vga, FALSE); +} + +Bool +s3CardInit (KdCardInfo *card) +{ + S3CardInfo *s3c; + S3Ptr s3; + S3Vga *s3vga; + int size; + CARD8 *registers; + CARD32 s3FrameBuffer; + CARD32 s3Registers; + CARD8 *temp_buffer; + CARD32 max_memory; + VGA32 save_linear_window_size; + VGA32 save_enable_linear; + VGA32 save_register_lock_2; + + s3c = (S3CardInfo *) xalloc (sizeof (S3CardInfo)); + if (!s3c) + { + goto bail0; + } + + memset (s3c, '\0', sizeof (S3CardInfo)); + + card->driver = s3c; + + if (card->attr.naddr > 1) + { + s3FrameBuffer = card->attr.address[1]; + s3Registers = card->attr.address[0]; + max_memory = 32 * 1024 * 1024; + } + else + { + s3FrameBuffer = card->attr.address[0]; + s3Registers = s3FrameBuffer + REGISTERS_OFFSET; + max_memory = 16 * 1024 * 1024; + } + +#ifdef DEBUG + fprintf (stderr, "S3 at 0x%x/0x%x\n", s3Registers, s3FrameBuffer); +#endif + registers = KdMapDevice (s3Registers, + sizeof (S3) + PACKED_OFFSET); + if (!registers) + { + ErrorF ("Can't map s3 device\n"); + goto bail2; + } + s3 = (S3Ptr) (registers + PACKED_OFFSET); + s3c->registers = registers; + s3c->s3 = s3; + + s3vga = &s3c->s3vga; + s3RegInit (s3vga, (VGAVOL8 *) (registers + IOMAP_OFFSET)); + + save_register_lock_2 = s3Get (s3vga, s3_register_lock_2); + s3SetImm (s3vga, s3_register_lock_2, 0xa0); + save_linear_window_size = s3Get (s3vga, s3_linear_window_size); + save_enable_linear = s3Get (s3vga, s3_enable_linear); + s3Set (s3vga, s3_linear_window_size, 3); + s3Set (s3vga, s3_enable_linear, 1); + VgaFlush (&s3vga->card); + VgaFinish (&s3vga->card); + + /* + * Can't trust S3 register value for frame buffer amount, must compute + */ + temp_buffer = KdMapDevice (s3FrameBuffer, max_memory); + + s3c->memory = KdFrameBufferSize (temp_buffer, max_memory); + + s3Set (s3vga, s3_linear_window_size, save_linear_window_size); + s3Set (s3vga, s3_enable_linear, save_enable_linear); + VgaFlush (&s3vga->card); + s3SetImm (s3vga, s3_register_lock_2, save_register_lock_2); + VgaFinish (&s3vga->card); +#ifdef DEBUG + fprintf (stderr, "Frame buffer 0x%x\n", s3c->memory); +#endif + KdUnmapDevice (temp_buffer, max_memory); + + if (!s3c->memory) + { + ErrorF ("Can't detect s3 frame buffer at 0x%x\n", s3FrameBuffer); + goto bail3; + } + + s3c->frameBuffer = KdMapDevice (s3FrameBuffer, s3c->memory); + if (!s3c->frameBuffer) + { + ErrorF ("Can't map s3 frame buffer\n"); + goto bail3; + } + + card->driver = s3c; + + return TRUE; +bail3: + KdUnmapDevice ((void *) s3, sizeof (S3)); +bail2: +bail1: + xfree (s3c); +bail0: + return FALSE; +} + +Bool +s3ScreenInit (KdScreenInfo *screen) +{ + KdCardInfo *card = screen->card; + S3CardInfo *s3c = (S3CardInfo *) card->driver; + S3ScreenInfo *s3s; + int screen_size; + int memory; + int requested_memory; + int v_total, h_total; + int byte_width; + int pixel_width; + int m, n, r; + int i; + S3Timing *t; + + s3s = (S3ScreenInfo *) xalloc (sizeof (S3ScreenInfo)); + if (!s3s) + return FALSE; + + memset (s3s, '\0', sizeof (S3ScreenInfo)); + + if (!screen->width || !screen->height) + { + screen->width = 800; + screen->height = 600; + screen->rate = 72; + } + if (!screen->depth) + screen->depth = 8; + + for (i = 0, t = s3Timings; i < NUM_S3_TIMINGS; i++, t++) + { + if (t->horizontal >= screen->width && + t->vertical >= screen->height && + (!screen->rate || t->rate <= screen->rate)) + break; + } + if (i == NUM_S3_TIMINGS) + t = &s3Timings[DEFAULT_S3_TIMING]; + screen->rate = t->rate; + screen->width = t->horizontal; + screen->height = t->vertical; + s3GetClock (S3ModeClock(t), &m, &n, &r, 511, 127, 4); +#ifdef DEBUG + fprintf (stderr, "computed %d,%d,%d (%d) provided %d,%d,%d (%d)\n", + m, n, r, S3_CLOCK(m,n,r), + t->dac_m, t->dac_n, t->dac_r, + S3_CLOCK(t->dac_m, t->dac_n, t->dac_r)); +#endif + /* + * Can only operate in pixel-doubled mode at 8 bits per pixel + */ + if (screen->depth > 16 && S3_CLOCK(m,n,r) > S3_MAX_CLOCK) + screen->depth = 16; + + for (;;) + { + if (screen->depth >= 24) + { + screen->depth = 24; + screen->bitsPerPixel = 32; + } + else if (screen->depth >= 16) + { + screen->depth = 16; + screen->bitsPerPixel = 16; + } + else if (screen->depth >= 15) + { + screen->depth = 15; + screen->bitsPerPixel = 16; + } + else + { + screen->depth = 8; + screen->bitsPerPixel = 8; + } + + /* Normalize width to supported values */ + + if (screen->width >= 1600) + screen->width = 1600; + else if (screen->width >= 1280) + screen->width = 1280; + else if (screen->width >= 1152) + screen->width = 1152; + else if (screen->width >= 1024) + screen->width = 1024; + else if (screen->width >= 800) + screen->width = 800; + else + screen->width = 640; + + byte_width = screen->width * (screen->bitsPerPixel >> 3); + pixel_width = screen->width; + screen->pixelStride = pixel_width; + screen->byteStride = byte_width; + + screen_size = byte_width * screen->height; + + if (screen_size <= s3c->memory) + break; + + /* + * Fix requested depth and geometry until it works + */ + if (screen->depth > 16) + screen->depth = 16; + else if (screen->depth > 8) + screen->depth = 8; + else if (screen->width > 1152) + { + screen->width = 1152; + screen->height = 900; + } + else if (screen->width > 1024) + { + screen->width = 1024; + screen->height = 768; + } + else if (screen->width > 800) + { + screen->width = 800; + screen->height = 600; + } + else if (screen->width > 640) + { + screen->width = 640; + screen->height = 480; + } + else + { + xfree (s3s); + return FALSE; + } + } + + memory = s3c->memory - screen_size; + + /* + * Stick frame buffer at start of memory + */ + screen->frameBuffer = s3c->frameBuffer; + + /* + * Stick cursor at end of memory + */ + if (memory >= 2048) + { + s3s->cursor_base = s3c->frameBuffer + (s3c->memory - 2048); + memory -= 2048; + } + else + s3s->cursor_base = 0; + + /* + * Use remaining memory for off-screen storage, but only use + * one piece (either right or bottom). + */ + if (memory >= byte_width * S3_TILE_SIZE) + { + s3s->offscreen = s3c->frameBuffer + screen_size; + s3s->offscreen_x = 0; + s3s->offscreen_y = screen_size / byte_width; + s3s->offscreen_width = pixel_width; + s3s->offscreen_height = memory / byte_width; + memory -= s3s->offscreen_height * byte_width; + } + else if (pixel_width - screen->width >= S3_TILE_SIZE) + { + s3s->offscreen = s3c->frameBuffer + screen->width; + s3s->offscreen_x = screen->width; + s3s->offscreen_y = 0; + s3s->offscreen_width = pixel_width - screen->width; + s3s->offscreen_height = screen->height; + } + else + s3s->offscreen = 0; + + switch (screen->depth) { + case 8: + screen->visuals = ((1 << StaticGray) | + (1 << GrayScale) | + (1 << StaticColor) | + (1 << PseudoColor) | + (1 << TrueColor) | + (1 << DirectColor)); + screen->blueMask = 0x00; + screen->greenMask = 0x00; + screen->redMask = 0x00; + break; + case 15: + screen->visuals = (1 << TrueColor); + screen->blueMask = 0x001f; + screen->greenMask = 0x03e0; + screen->redMask = 0x7c00; + break; + case 16: + screen->visuals = (1 << TrueColor); + screen->blueMask = 0x001f; + screen->greenMask = 0x07e0; + screen->redMask = 0xf800; + break; + case 24: + screen->visuals = (1 << TrueColor); + screen->blueMask = 0x0000ff; + screen->greenMask = 0x00ff00; + screen->redMask = 0xff0000; + break; + } + + screen->driver = s3s; + + return TRUE; +} + +void +s3Preserve (KdCardInfo *card) +{ + S3CardInfo *s3c = card->driver; + S3Ptr s3 = s3c->s3; + S3Vga *s3vga = &s3c->s3vga; + S3Save *save = &s3c->save; + CARD8 t1, t2; + CARD8 *cursor_base; + + s3Save (s3vga); + _s3SetBlank (s3, s3vga, TRUE); + /* + * Preserve the first part of the frame buffer which holds + * the text mode fonts and data + */ + s3Set (s3vga, s3_linear_window_size, 3); + s3Set (s3vga, s3_enable_linear, 1); + VgaFlush (&s3vga->card); + memcpy (save->text_save, s3c->frameBuffer, S3_TEXT_SAVE); + /* + * Preserve graphics engine state + */ + save->alt_mix = s3->alt_mix; + save->write_mask = s3->write_mask; + save->fg = s3->fg; + save->bg = s3->bg; + _s3SetBlank (s3, s3vga, FALSE); +} + +/* + * Enable the card for rendering. Manipulate the initial settings + * of the card here. + */ +void +s3Enable (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdCardInfo *card = pScreenPriv->card; + KdScreenInfo *screen = pScreenPriv->screen; + s3CardInfo (pScreenPriv); + s3ScreenInfo (pScreenPriv); + + S3Vga *s3vga = &s3c->s3vga; + int hactive, hblank, hfp, hbp; + int vactive, vblank, vfp, vbp; + int hsize; + + int h_total; + int h_display_end; + int h_blank_start; + int h_blank_end; + int h_sync_start; + int h_sync_end; + int h_screen_off; + int h_start_fifo_fetch; + + int primary_stream_l1; + + int v_total; + int v_retrace_start; + int v_retrace_end; + int v_display_end; + int v_blank_start; + int v_blank_end; + + int h_blank_start_adjust; + int h_blank_end_adjust; + int h_sync_extend; + int h_blank_extend; + int i; + CARD16 cursor_address; + S3Timing *t; + int m, n, r; + Bool clock_double; + + for (i = 0; i < NUM_S3_TIMINGS; i++) + { + t = &s3Timings[i]; + + if (t->horizontal == screen->width && + t->vertical == screen->height && + t->rate <= screen->rate) + break; + } + if (i == NUM_S3_TIMINGS) + t = &s3Timings[DEFAULT_S3_TIMING]; + + hfp = t->hfp; + hbp = t->hbp; + hblank = t->hblank; + hactive = t->horizontal; + + vfp = t->vfp; + vbp = t->vbp; + vblank = t->vblank; + vactive = t->vertical; + + m = s3Get (s3vga, s3_dclk_m); + n = s3Get (s3vga, s3_dclk_n); + r = s3Get (s3vga, s3_dclk_r); +#ifdef DEBUG + fprintf (stderr, "old clock %d, %d, %d\n", m, n, r); +#endif + clock_double = FALSE; + s3GetClock (S3ModeClock(t), &m, &n, &r, 511, 127, 4); + if (S3_CLOCK(m,n,r) > S3_MAX_CLOCK) + clock_double = TRUE; + s3Set (s3vga, s3_clock_select, 3); + s3Set (s3vga, s3_dclk_m, m); + s3Set (s3vga, s3_dclk_n, n); + s3Set (s3vga, s3_dclk_r, r); +#ifdef DEBUG + fprintf (stderr, "new clock %d, %d, %d\n", m, n, r); +#endif + + s3Set (s3vga, s3_select_graphics_mode, 1); + s3Set (s3vga, s3_enable_blinking, 0); + s3Set (s3vga, s3_enable_vga_16bit, 0); + s3Set (s3vga, s3_enhanced_memory_mapping, 1); + s3Set (s3vga, s3_enable_sff, 1); + s3Set (s3vga, s3_enable_2d_access, 1); + s3Set (s3vga, s3_byte_mode, 1); + s3Set (s3vga, s3_max_scan_line, 0); + s3Set (s3vga, s3_linear_window_size, 3); + s3Set (s3vga, s3_enable_linear, 1); + s3Set (s3vga, s3_enable_2d_3d, 1); + s3Set (s3vga, s3_refresh_control, 1); + s3Set (s3vga, s3_disable_pci_read_bursts, 0); + s3Set (s3vga, s3_pci_retry_enable, 1); + s3Set (s3vga, s3_enable_256, 1); +#if 1 + s3Set (s3vga, s3_border_select, 1); /* eliminate white border */ +#else + s3Set (s3vga, s3_border_select, 0); /* eliminate white border */ +#endif + s3Set (s3vga, s3_disable_v_retrace_int, 1); + s3Set (s3vga, s3_horz_sync_neg, 0); + s3Set (s3vga, s3_vert_sync_neg, 0); + + s3Set (s3vga, s3_dot_clock_8, 1); + s3Set (s3vga, s3_enable_write_plane, 0xf); + s3Set (s3vga, s3_extended_memory_access, 1); + s3Set (s3vga, s3_sequential_addressing_mode, 1); + s3Set (s3vga, s3_select_chain_4_mode, 1); +#if 1 + s3Set (s3vga, s3_linear_addressing_control, 1); +#else + s3Set (s3vga, s3_linear_addressing_control, 0); +#endif + s3Set (s3vga, s3_enable_8_bit_luts, 1); + + s3Set (s3vga, s3_dclk_invert, 0); + s3Set (s3vga, s3_enable_clock_double, 0); + + s3Set (s3vga, s3_cpu_timeout, 0x1f); + s3Set (s3vga, s3_fifo_fetch_timing, 1); + s3Set (s3vga, s3_fifo_drain_delay, 7); + + + s3Set (s3vga, s3_delay_h_enable, 0); + s3Set (s3vga, s3_sdclk_skew, 0); + + /* + * Compute character lengths for horizontal timing values + */ + h_blank_start_adjust = 0; + h_blank_end_adjust = 0; + switch (screen->bitsPerPixel) { + case 8: + hactive = screen->width / 8; + hblank /= 8; + hfp /= 8; + hbp /= 8; + h_screen_off = hactive; + s3Set (s3vga, s3_2d_graphics_engine_timeout, 0x1f); + s3Set (s3vga, s3_pixel_length, 0); + s3Set (s3vga, s3_color_mode, 0); + /* + * Set up for double-pixel mode, switch color modes, + * divide the dclk and delay h blank by 2 dclks + */ + if (clock_double) + { + s3Set (s3vga, s3_color_mode, 1); + s3Set (s3vga, s3_dclk_over_2, 1); + s3Set (s3vga, s3_enable_clock_double, 1); + s3Set (s3vga, s3_border_select, 0); +#if 0 + s3Set (s3vga, s3_delay_blank, 2); + s3Set (s3vga, s3_delay_h_enable, 2); + crtc->extended_bios_5 = 2; +#endif + h_blank_start_adjust = -1; + h_blank_end_adjust = 0; + } + break; + case 16: + hactive = screen->width / 8; + hblank /= 8; + hfp /= 8; + hbp /= 8; + h_screen_off = hactive * 2; + s3Set (s3vga, s3_pixel_length, 1); + s3Set (s3vga, s3_2d_graphics_engine_timeout, 0x14); + if (clock_double) + { + if (screen->depth == 15) + s3Set (s3vga, s3_color_mode, 3); + else + s3Set (s3vga, s3_color_mode, 5); + s3Set (s3vga, s3_dclk_over_2, 1); + s3Set (s3vga, s3_enable_clock_double, 1); + s3Set (s3vga, s3_border_select, 0); + } + else + { + if (screen->depth == 15) + s3Set (s3vga, s3_color_mode, 2); + else + s3Set (s3vga, s3_color_mode, 4); + s3Set (s3vga, s3_dclk_over_2, 0); + s3Set (s3vga, s3_enable_clock_double, 0); + s3Set (s3vga, s3_delay_blank, 0); + } + break; + case 32: + hactive = screen->width / 8; + hblank /= 8; + hfp /= 8; + hbp /= 8; + h_screen_off = hactive * 4; + s3Set (s3vga, s3_pixel_length, 3); + s3Set (s3vga, s3_color_mode, 0xd); + s3Set (s3vga, s3_2d_graphics_engine_timeout, 0x07); + break; + } + + /* + * X server starts frame buffer at top of memory + */ + s3Set (s3vga, s3_start_address, 0); + + /* + * Compute horizontal register values from timings + */ + h_total = hactive + hblank - 5; + h_display_end = hactive - 1; + + h_sync_start = hactive + hfp; + h_sync_end = hactive + hblank - hbp; + /* + * pad the blank values narrow a bit and use the border_select to + * eliminate the remaining border; don't know why, but it doesn't + * work in the documented fashion + */ + h_blank_start = hactive + 1 + h_blank_start_adjust; + h_blank_end = hactive + hblank - 2 + h_blank_end_adjust; + /* + * The manual says h_total - 5, but the + * bios does differently... + */ + if (screen->width >= 1600) + h_start_fifo_fetch = h_total - 24; + else if (screen->width >= 1280) + h_start_fifo_fetch = h_total - 19; + else if (screen->width >= 1024) + h_start_fifo_fetch = h_total - 14; + else if (screen->width >= 800) + h_start_fifo_fetch = h_total - 10; + else + h_start_fifo_fetch = h_total - 5; + + if (h_blank_end - h_blank_start >= 0x40) + h_blank_extend = 1; + else + h_blank_extend = 0; + + if (h_sync_end - h_sync_start >= 0x20) + h_sync_extend = 1; + else + h_sync_extend = 0; + + primary_stream_l1 = (screen->width * screen->bitsPerPixel / (8 * 8)) - 1; + +#ifdef DEBUG + fprintf (stderr, "h_total %d h_display_end %d\n", + h_total, h_display_end); + fprintf (stderr, "h_sync_start %d h_sync_end %d h_sync_extend %d\n", + h_sync_start, h_sync_end, h_sync_extend); + fprintf (stderr, "h_blank_start %d h_blank_end %d h_blank_extend %d\n", + h_blank_start, h_blank_end, h_blank_extend); +#endif + + s3Set (s3vga, s3_h_total, h_total); + s3Set (s3vga, s3_h_display_end, h_display_end); + s3Set (s3vga, s3_h_blank_start, h_blank_start); + s3Set (s3vga, s3_h_blank_end, h_blank_end); + s3Set (s3vga, s3_h_sync_start, h_sync_start); + s3Set (s3vga, s3_h_sync_end, h_sync_end); + s3Set (s3vga, s3_screen_offset, h_screen_off); + s3Set (s3vga, s3_h_start_fifo_fetch, h_start_fifo_fetch); + s3Set (s3vga, s3_h_sync_extend, h_sync_extend); + s3Set (s3vga, s3_h_blank_extend, h_blank_extend); + + s3Set (s3vga, s3_primary_stream_l1, primary_stream_l1); + + v_total = vactive + vblank - 2; + v_display_end = vactive - 1; + +#if 0 + v_blank_start = vactive - 1; + v_blank_end = v_blank_start + vblank - 1; +#else + v_blank_start = vactive - 1; + v_blank_end = v_blank_start + vblank - 1; +#endif + + v_retrace_start = vactive + vfp; + v_retrace_end = vactive + vblank - vbp; + + s3Set (s3vga, s3_v_total, v_total); + s3Set (s3vga, s3_v_retrace_start, v_retrace_start); + s3Set (s3vga, s3_v_retrace_end, v_retrace_end); + s3Set (s3vga, s3_v_display_end, v_display_end); + s3Set (s3vga, s3_v_blank_start, v_blank_start); + s3Set (s3vga, s3_v_blank_end, v_blank_end); + + if (vactive >= 1024) + s3Set (s3vga, s3_line_compare, 0x7ff); + else + s3Set (s3vga, s3_line_compare, 0x3ff); + + /* + * Set cursor + */ + if (!screen->softCursor) + { + cursor_address = (s3s->cursor_base - screen->frameBuffer) / 1024; + + s3Set (s3vga, s3_cursor_address, cursor_address); + s3Set (s3vga, s3_cursor_ms_x11, 0); + s3Set (s3vga, s3_cursor_enable, 1); + } + else + s3Set (s3vga, s3_cursor_enable, 0); + + /* + * Set accelerator + */ + switch (screen->width) { + case 640: s3Set (s3vga, s3_ge_screen_width, 1); break; + case 800: s3Set (s3vga, s3_ge_screen_width, 2); break; + case 1024: s3Set (s3vga, s3_ge_screen_width, 0); break; + case 1152: s3Set (s3vga, s3_ge_screen_width, 4); break; + case 1280: s3Set (s3vga, s3_ge_screen_width, 3); break; + case 1600: s3Set (s3vga, s3_ge_screen_width, 6); break; + } + +#if 0 + crtc->l_parm_0_7 = screen->width / 4; /* Undocumented. */ +#endif + + /* + * Set DPMS to normal + */ + s3Set (s3vga, s3_hsync_control, 0); + s3Set (s3vga, s3_vsync_control, 0); + + _s3SetDepth (s3c->s3, s3vga); +} + +void +s3Disable (ScreenPtr pScreen) +{ +} + +void +s3Restore (KdCardInfo *card) +{ + S3CardInfo *s3c = card->driver; + S3Ptr s3 = s3c->s3; + S3Vga *s3vga = &s3c->s3vga; + S3Save *save = &s3c->save; + CARD8 *cursor_base; + + /* graphics engine state */ + s3->alt_mix = save->alt_mix; + s3->write_mask = save->write_mask; + s3->fg = save->fg; + s3->bg = save->bg; + /* XXX should save and restore real values? */ + s3->scissors_tl = 0x00000000; + s3->scissors_br = 0x0fff0fff; + + _s3SetBlank (s3, s3vga, TRUE); + VgaRestore (&s3vga->card); + s3Set (s3vga, s3_linear_window_size, 3); + s3Set (s3vga, s3_enable_linear, 1); + VgaFlush (&s3vga->card); + memcpy (s3c->frameBuffer, save->text_save, S3_TEXT_SAVE); + s3Reset (s3vga); + _s3SetBlank (s3, s3vga, FALSE); +} + +void +_s3SetSync (S3CardInfo *s3c, int hsync, int vsync) +{ + /* this abuses the macros defined to access the crtc structure */ + S3Ptr s3 = s3c->s3; + S3Vga *s3vga = &s3c->s3vga; + + s3Set (s3vga, s3_hsync_control, hsync); + s3Set (s3vga, s3_vsync_control, vsync); + VgaFlush (&s3vga->card); +} + +Bool +s3DPMS (ScreenPtr pScreen, int mode) +{ + KdScreenPriv(pScreen); + s3CardInfo(pScreenPriv); + S3Vga *s3vga = &s3c->s3vga; + + switch (mode) { + case KD_DPMS_NORMAL: + _s3SetSync (s3c, 0, 0); + _s3SetBlank (s3c->s3, s3vga, FALSE); + break; + case KD_DPMS_STANDBY: + _s3SetBlank (s3c->s3, s3vga, TRUE); + _s3SetSync (s3c, 1, 0); + break; + case KD_DPMS_SUSPEND: + _s3SetBlank (s3c->s3, s3vga, TRUE); + _s3SetSync (s3c, 0, 1); + break; + case KD_DPMS_POWERDOWN: + _s3SetBlank (s3c->s3, s3vga, TRUE); + _s3SetSync (s3c, 1, 1); + break; + } + return TRUE; +} + +void +s3ScreenFini (KdScreenInfo *screen) +{ + S3ScreenInfo *s3s = (S3ScreenInfo *) screen->driver; + + xfree (s3s); + screen->driver = 0; +} + +void +s3CardFini (KdCardInfo *card) +{ + S3CardInfo *s3c = (S3CardInfo *) card->driver; + + KdUnmapDevice (s3c->frameBuffer, s3c->memory); + KdUnmapDevice (s3c->registers, sizeof (S3) + PACKED_OFFSET); + xfree (s3c); + card->driver = 0; +} + +KdCardFuncs s3Funcs = { + s3CardInit, + s3ScreenInit, + s3Preserve, + s3Enable, + s3DPMS, + s3Disable, + s3Restore, + s3ScreenFini, + s3CardFini, + s3CursorInit, + s3CursorEnable, + s3CursorDisable, + s3CursorFini, + s3RecolorCursor, + s3DrawInit, + s3DrawEnable, + s3DrawDisable, + s3DrawFini, + s3GetColors, + s3PutColors, +}; diff --git a/hw/kdrive/savage/s3.h b/hw/kdrive/savage/s3.h new file mode 100644 index 000000000..95a8edddd --- /dev/null +++ b/hw/kdrive/savage/s3.h @@ -0,0 +1,545 @@ +/* + * $Id$ + * + * Copyright 1999 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ +/* $XFree86: $ */ + +#ifndef _S3_H_ +#define _S3_H_ + +#include "kdrive.h" +#include "s3reg.h" + +#define PLATFORM 300 + +/* VESA Approved Register Definitions */ + +/* + * Linear Addressing 000 0000 - 0ff ffff (16m) + * Image data transfer 100 0000 - 100 7fff (32k) + * PCI config 100 8000 - 100 8043 + * Packed enhanced regs 100 8100 - 100 814a + * Streams regs 100 8180 - 100 81ff + * Current Y pos 100 82e8 + * CRT VGA 3b? regs 100 83b0 - 100 83bf + * CRT VGA 3c? regs 100 83c0 - 100 83cf + * CRT VGA 3d? regs 100 83d0 - 100 83df + * Subsystem status (42e8h) 100 8504 + * Advanced function (42e8h) 100 850c + * Enhanced regs 100 86e8 - 100 eeea + * Local peripheral bus 100 ff00 - 100 ff5c + * + * We don't care about the image transfer or PCI regs, so + * this structure starts at the packed enhanced regs + */ + +typedef volatile CARD32 VOL32; +typedef volatile CARD16 VOL16; +typedef volatile CARD8 VOL8; + +typedef volatile struct _s3 { + VOL32 alt_curxy; /* 8100 */ + VOL32 _pad0; /* 8104 */ + VOL32 alt_step; /* 8108 */ + VOL32 _pad1; /* 810c */ + VOL32 err_term; /* 8110 */ + VOL32 _pad2; /* 8114 */ + VOL32 cmd_gp_stat; /* 8118 */ + VOL32 short_stroke; /* 811c */ + VOL32 bg; /* 8120 */ + VOL32 fg; /* 8124 */ + VOL32 write_mask; /* 8128 */ + VOL32 read_mask; /* 812c */ + VOL32 color_cmp; /* 8130 */ + VOL32 alt_mix; /* 8134 */ + VOL32 scissors_tl; /* 8138 */ + VOL32 scissors_br; /* 813c */ + VOL16 pix_cntl; /* 8140 */ + VOL16 mult_misc2; /* 8142 */ + VOL32 mult_misc_read_sel; /* 8144 */ + VOL32 alt_pcnt; /* 8148 min_axis_pcnt, maj_axis_pcnt */ + VOL8 _pad3[0x19c]; /* 814c */ + VOL16 cur_y; /* 82e8 */ + VOL8 _pad4[0xc6]; /* 82ea */ + + VOL8 crt_vga_3b0; /* 83b0 */ + VOL8 crt_vga_3b1; /* 83b1 */ + VOL8 crt_vga_3b2; /* 83b2 */ + VOL8 crt_vga_3b3; /* 83b3 */ + VOL8 crt_vga_3b4; /* 83b4 */ + VOL8 crt_vga_3b5; /* 83b5 */ + VOL8 crt_vga_3b6; /* 83b6 */ + VOL8 crt_vga_3b7; /* 83b7 */ + VOL8 crt_vga_3b8; /* 83b8 */ + VOL8 crt_vga_3b9; /* 83b9 */ + VOL8 crt_vga_3ba; /* 83ba */ + VOL8 crt_vga_3bb; /* 83bb */ + VOL8 crt_vga_3bc; /* 83bc */ + VOL8 crt_vga_3bd; /* 83bd */ + VOL8 crt_vga_3be; /* 83be */ + VOL8 crt_vga_3bf; /* 83bf */ + + VOL8 crt_vga_3c0; /* 83c0 */ + VOL8 crt_vga_3c1; /* 83c1 */ + VOL8 crt_vga_3c2; /* 83c2 */ + VOL8 crt_vga_3c3; /* 83c3 */ + VOL8 crt_vga_3c4; /* 83c4 */ + VOL8 crt_vga_3c5; /* 83c5 */ + VOL8 crt_vga_dac_ad_mk; /* 83c6 */ + VOL8 crt_vga_dac_rd_ad; /* 83c7 */ + VOL8 crt_vga_dac_wt_ad; /* 83c8 */ + VOL8 crt_vga_dac_data; /* 83c9 */ + VOL8 crt_vga_3ca; /* 83ca */ + VOL8 crt_vga_3cb; /* 83cb */ + VOL8 crt_vga_3cc; /* 83cc */ + VOL8 crt_vga_3cd; /* 83cd */ + VOL8 crt_vga_3ce; /* 83ce */ + VOL8 crt_vga_3cf; /* 83cf */ + + VOL8 crt_vga_3d0; /* 83d0 */ + VOL8 crt_vga_3d1; /* 83d1 */ + VOL8 crt_vga_3d2; /* 83d2 */ + VOL8 crt_vga_3d3; /* 83d3 */ + VOL8 crt_vga_3d4; /* 83d4 */ + VOL8 crt_vga_3d5; /* 83d5 */ + VOL8 crt_vga_3d6; /* 83d6 */ + VOL8 crt_vga_3d7; /* 83d7 */ + VOL8 crt_vga_3d8; /* 83d8 */ + VOL8 crt_vga_3d9; /* 83d9 */ + VOL8 crt_vga_status_1; /* 83da */ + VOL8 crt_vga_3db; /* 83db */ + VOL8 crt_vga_3dc; /* 83dc */ + VOL8 crt_vga_3dd; /* 83dd */ + VOL8 crt_vga_3de; /* 83de */ + VOL8 crt_vga_3df; /* 83df */ + + VOL8 _pad5[0x124]; /* 83e0 */ + VOL16 subsys_status; /* 8504 */ + VOL8 _pad6[0x6]; /* 8506 */ + VOL16 adv_control; /* 850c */ + VOL8 _pad7[0x1da]; /* 850e */ + VOL16 cur_x; /* 86e8 */ + VOL8 _pad8[0x3fe]; /* 86ea */ + VOL16 desty_axstp; /* 8ae8 */ + VOL8 _pad9[0x3fe]; /* 8aea */ + VOL16 destx_diastp; /* 8ee8 */ + VOL8 _pad10[0x3fe]; /* 8eea */ + VOL16 enh_err_term; /* 92e8 */ + VOL8 _pad11[0x3fe]; /* 92ea */ + VOL16 maj_axis_pcnt; /* 96e8 */ + VOL8 _pad12[0x3fe]; /* 96ea */ + VOL16 enh_cmd_gp_stat; /* 9ae8 */ + VOL8 _pad13[0x3fe]; /* 9aea */ + VOL16 enh_short_stroke; /* 9ee8 */ + VOL8 _pad14[0x3fe]; /* 9eea */ + VOL16 enh_bg; /* a2e8 */ + VOL8 _pad15[0x3fe]; /* a2ea */ + VOL16 enh_fg; /* a6e8 */ + VOL8 _pad16[0x3fe]; /* a6ea */ + VOL16 enh_wrt_mask; /* aae8 */ + VOL8 _pad17[0x3fe]; /* aaea */ + VOL16 enh_rd_mask; /* aee8 */ + VOL8 _pad18[0x3fe]; /* aeea */ + VOL16 enh_color_cmp; /* b2e8 */ + VOL8 _pad19[0x3fe]; /* b2ea */ + VOL16 enh_bg_mix; /* b6e8 */ + VOL8 _pad20[0x3fe]; /* b6ea */ + VOL16 enh_fg_mix; /* bae8 */ + VOL8 _pad21[0x3fe]; /* baea */ + VOL16 enh_rd_reg_dt; /* bee8 */ + VOL8 _pad22[0x23fe]; /* beea */ + VOL32 pix_trans; /* e2e8 */ + + VOL8 _pad23[0x3a974]; /* e2ec */ + VOL32 alt_status_0; /* 48c60 */ +} S3, *S3Ptr; + +#define VGA_STATUS_1_DTM 0x01 +#define VGA_STATUS_1_VSY 0x08 + +#define DAC_MASK 0x03c6 +#define DAC_R_INDEX 0x03c7 +#define DAC_W_INDEX 0x03c8 +#define DAC_DATA 0x03c9 +#define DISP_STAT 0x02e8 +#define H_TOTAL 0x02e8 +#define H_DISP 0x06e8 +#define H_SYNC_STRT 0x0ae8 +#define H_SYNC_WID 0x0ee8 +#define V_TOTAL 0x12e8 +#define V_DISP 0x16e8 +#define V_SYNC_STRT 0x1ae8 +#define V_SYNC_WID 0x1ee8 +#define DISP_CNTL 0x22e8 +#define ADVFUNC_CNTL 0x4ae8 +#define SUBSYS_STAT 0x42e8 +#define SUBSYS_CNTL 0x42e8 +#define ROM_PAGE_SEL 0x46e8 +#define CUR_Y 0x82e8 +#define CUR_X 0x86e8 +#define DESTY_AXSTP 0x8ae8 +#define DESTX_DIASTP 0x8ee8 +#define ERR_TERM 0x92e8 +#define MAJ_AXIS_PCNT 0x96e8 +#define GP_STAT 0x9ae8 +#define CMD 0x9ae8 +#define SHORT_STROKE 0x9ee8 +#define BKGD_COLOR 0xa2e8 +#define FRGD_COLOR 0xa6e8 +#define WRT_MASK 0xaae8 +#define RD_MASK 0xaee8 +#define COLOR_CMP 0xb2e8 +#define BKGD_MIX 0xb6e8 +#define FRGD_MIX 0xbae8 +#define MULTIFUNC_CNTL 0xbee8 +#define MIN_AXIS_PCNT 0x0000 +#define SCISSORS_T 0x1000 +#define SCISSORS_L 0x2000 +#define SCISSORS_B 0x3000 +#define SCISSORS_R 0x4000 +#define MEM_CNTL 0x5000 +#define PATTERN_L 0x8000 +#define PATTERN_H 0x9000 +#define PIX_CNTL 0xa000 +#define PIX_TRANS 0xe2e8 + +/* Advanced Function Control Regsiter */ +#define CLKSEL 0x0004 +#define DISABPASSTHRU 0x0001 + +/* Graphics Processor Status Register */ + +#define GPNSLOT 13 + +#define GPBUSY_1 0x0080 +#define GPBUSY_2 0x0040 +#define GPBUSY_3 0x0020 +#define GPBUSY_4 0x0010 +#define GPBUSY_5 0x0008 +#define GPBUSY_6 0x0004 +#define GPBUSY_7 0x0002 +#define GPBUSY_8 0x0001 +#define GPBUSY_9 0x8000 +#define GPBUSY_10 0x4000 +#define GPBUSY_11 0x2000 +#define GPBUSY_12 0x1000 +#define GPBUSY_13 0x0800 + +#define GPEMPTY 0x0400 +#define GPBUSY 0x0200 +#define DATDRDY 0x0100 + +/* Command Register */ +#define CMD_NOP 0x0000 +#define CMD_LINE 0x2000 +#define CMD_RECT 0x4000 +#define CMD_RECTV1 0x6000 +#define CMD_RECTV2 0x8000 +#define CMD_LINEAF 0xa000 +#define CMD_BITBLT 0xc000 +#define CMD_PATBLT 0xe000 +#define CMD_OP_MSK 0xe000 +#define BYTSEQ 0x1000 +#define _32BITNOPAD 0x0600 +#define _32BIT 0x0400 +#define _16BIT 0x0200 +#define _8BIT 0x0000 +#define PCDATA 0x0100 +#define INC_Y 0x0080 +#define YMAJAXIS 0x0040 +#define INC_X 0x0020 +#define DRAW 0x0010 +#define LINETYPE 0x0008 +#define LASTPIX 0x0004 /* Draw last pixel in line */ +#define PLANAR 0x0002 +#define WRTDATA 0x0001 + +/* Background Mix Register */ +#define BSS_BKGDCOL 0x0000 +#define BSS_FRGDCOL 0x0020 +#define BSS_PCDATA 0x0040 +#define BSS_BITBLT 0x0060 + +/* Foreground Mix Register */ +#define FSS_BKGDCOL 0x0000 +#define FSS_FRGDCOL 0x0020 +#define FSS_PCDATA 0x0040 +#define FSS_BITBLT 0x0060 + +/* The Mixes */ +#define MIX_MASK 0x001f + +#define MIX_NOT_DST 0x0000 +#define MIX_0 0x0001 +#define MIX_1 0x0002 +#define MIX_DST 0x0003 +#define MIX_NOT_SRC 0x0004 +#define MIX_XOR 0x0005 +#define MIX_XNOR 0x0006 +#define MIX_SRC 0x0007 +#define MIX_NAND 0x0008 +#define MIX_NOT_SRC_OR_DST 0x0009 +#define MIX_SRC_OR_NOT_DST 0x000a +#define MIX_OR 0x000b +#define MIX_AND 0x000c +#define MIX_SRC_AND_NOT_DST 0x000d +#define MIX_NOT_SRC_AND_DST 0x000e +#define MIX_NOR 0x000f + +#define MIX_MIN 0x0010 +#define MIX_DST_MINUS_SRC 0x0011 +#define MIX_SRC_MINUS_DST 0x0012 +#define MIX_PLUS 0x0013 +#define MIX_MAX 0x0014 +#define MIX_HALF__DST_MINUS_SRC 0x0015 +#define MIX_HALF__SRC_MINUS_DST 0x0016 +#define MIX_AVERAGE 0x0017 +#define MIX_DST_MINUS_SRC_SAT 0x0018 +#define MIX_SRC_MINUS_DST_SAT 0x001a +#define MIX_HALF__DST_MINUS_SRC_SAT 0x001c +#define MIX_HALF__SRC_MINUS_DST_SAT 0x001e +#define MIX_AVERAGE_SAT 0x001f + +/* Pixel Control Register */ +#define MIXSEL_FRGDMIX 0x0000 +#define MIXSEL_PATT 0x0040 +#define MIXSEL_EXPPC 0x0080 +#define MIXSEL_EXPBLT 0x00c0 +#define COLCMPOP_F 0x0000 +#define COLCMPOP_T 0x0008 +#define COLCMPOP_GE 0x0010 +#define COLCMPOP_LT 0x0018 +#define COLCMPOP_NE 0x0020 +#define COLCMPOP_EQ 0x0028 +#define COLCMPOP_LE 0x0030 +#define COLCMPOP_GT 0x0038 +#define PLANEMODE 0x0004 + + +#define S3_SAVAGE4_SLOTS 0x0001ffff +#define S3_SAVAGE4_2DI 0x00800000 + +#define _s3WaitLoop(mask,value){ \ + int __loop = 100000; \ + while (((s3)->alt_status_0 & (mask)) != (value)) \ + if (--__loop == 0) { \ + ErrorF ("savage wait loop failed 0x%x\n", s3->alt_status_0); \ + break; \ + } \ +} + +#define _s3WaitSlot(s3) _s3WaitLoop(0x1, 0x0) +#define _s3WaitEmpty(s3) _s3WaitLoop(S3_SAVAGE4_SLOTS, 0) +#define _s3WaitIdleEmpty(s3) _s3WaitLoop(S3_SAVAGE4_SLOTS|S3_SAVAGE4_2DI, \ + S3_SAVAGE4_2DI) +#define _s3WaitIdle(s3) _s3WaitLoop(S3_SAVAGE4_2DI, S3_SAVAGE4_2DI) + +typedef struct _s3Cursor { + int width, height; + int xhot, yhot; + Bool has_cursor; + CursorPtr pCursor; + Pixel source, mask; +} S3Cursor; + +typedef struct _s3PatternCache { + int id; + int x, y; +} S3PatternCache; + +typedef struct _s3Patterns { + S3PatternCache *cache; + int ncache; + int last_used; + int last_id; +} S3Patterns; + +#define S3_CLOCK_REF 14318 /* KHz */ + +#define S3_CLOCK(m,n,r) (S3_CLOCK_REF * ((m) + 2) / (((n) + 2) * (1 << (r)))) + +#if PLATFORM == 200 +#define S3_MAX_CLOCK 80000 /* KHz */ +#endif +#if PLATFORM == 300 +#define S3_MAX_CLOCK 135000 /* KHz */ +#endif + +typedef struct _s3Timing { + /* label */ + int horizontal; + int vertical; + int rate; + /* horizontal timing */ + int hfp; /* front porch */ + int hbp; /* back porch */ + int hblank; /* blanking */ + /* vertical timing */ + int vfp; /* front porch */ + int vbp; /* back porch */ + int vblank; /* blanking */ + /* clock values */ + int dac_m; + int dac_n; + int dac_r; +} S3Timing; + +#define S3_TEXT_SAVE (64*1024) + +typedef struct _s3Save { + CARD8 cursor_fg; + CARD8 cursor_bg; + CARD8 lock1; + CARD8 lock2; + CARD8 locksrtc; + CARD8 clock_mode; + CARD32 alt_mix; + CARD32 write_mask; + CARD32 fg; + CARD32 bg; + CARD8 text_save[S3_TEXT_SAVE]; +} S3Save; + +typedef struct _s3CardInfo { + S3Ptr s3; /* pointer to register structure */ + int memory; /* amount of memory */ + CARD8 *frameBuffer; /* pointer to frame buffer */ + CARD8 *registers; /* pointer to register map */ + S3Vga s3vga; + S3Save save; +} S3CardInfo; + +typedef struct _s3ScreenInfo { + CARD8 *cursor_base; /* pointer to cursor area */ + CARD8 *offscreen; /* pointer to offscreen area */ + int offscreen_y; /* top y coordinate of offscreen area */ + int offscreen_x; /* top x coordinate of offscreen area */ + int offscreen_width; /* width of offscreen area */ + int offscreen_height; /* height of offscreen area */ + S3Cursor cursor; + S3Patterns patterns; +} S3ScreenInfo; + +#define getS3CardInfo(kd) ((S3CardInfo *) ((kd)->card->driver)) +#define s3CardInfo(kd) S3CardInfo *s3c = getS3CardInfo(kd) + +#define getS3ScreenInfo(kd) ((S3ScreenInfo *) ((kd)->screen->driver)) +#define s3ScreenInfo(kd) S3ScreenInfo *s3s = getS3ScreenInfo(kd) + +Bool s3CardInit (KdCardInfo *); +Bool s3ScreenInit (KdScreenInfo *); +void s3Enable (ScreenPtr pScreen); +void s3Disable (ScreenPtr pScreen); +void s3Fini (ScreenPtr pScreen); + +Bool s3CursorInit (ScreenPtr pScreen); +void s3CursorEnable (ScreenPtr pScreen); +void s3CursorDisable (ScreenPtr pScreen); +void s3CursorFini (ScreenPtr pScreen); +void s3RecolorCursor (ScreenPtr pScreen, int ndef, xColorItem *pdefs); + +Bool s3DrawInit (ScreenPtr pScreen); +void s3DrawEnable (ScreenPtr pScreen); +void s3DrawDisable (ScreenPtr pScreen); +void s3DrawFini (ScreenPtr pScreen); + +void s3GetColors (ScreenPtr pScreen, int ndef, xColorItem *pdefs); +void s3PutColors (ScreenPtr pScreen, int ndef, xColorItem *pdefs); + +void S3InitCard (KdCardAttr *attr); + +void s3GetClock (int target, int *Mp, int *Np, int *Rp, int maxM, int maxN, int maxR); + +#define S3ModeClock(t) (((t->horizontal + t->hblank) * \ + (t->vertical + t->vblank) * \ + t->rate) / 1000) + +extern KdCardFuncs s3Funcs; + +/* + * Wait for the begining of the retrace interval + */ + +#define S3_RETRACE_LOOP_CHECK if (++_loop_count > 300000) {\ + DRAW_DEBUG ((DEBUG_FAILURE, "S3 wait loop failed at %s:%d", \ + __FILE__, __LINE__)); \ + break; \ +} + +#define DRAW_DEBUG(a) + +#define _s3WaitVRetrace(s3) { \ + VOL8 *_status = &s3->crt_vga_status_1; \ + int _loop_count; \ + DRAW_DEBUG ((DEBUG_CRTC, "_s3WaitVRetrace 0x%x", *_status)); \ + _loop_count = 0; \ + while ((*_status & VGA_STATUS_1_VSY) != 0) S3_RETRACE_LOOP_CHECK; \ + _loop_count = 0; \ + while ((*_status & VGA_STATUS_1_VSY) == 0) S3_RETRACE_LOOP_CHECK; \ +} +/* + * Wait for the begining of the retrace interval + */ +#define _s3WaitVRetraceEnd(s3) { \ + VOL8 *_status = &s3->crt_vga_status_1; \ + int _loop_count; \ + DRAW_DEBUG ((DEBUG_CRTC, "_s3WaitVRetraceEnd 0x%x", *_status)); \ + _loop_count = 0; \ + while ((*_status & VGA_STATUS_1_VSY) == 0) S3_RETRACE_LOOP_CHECK; \ + _loop_count = 0; \ + while ((*_status & VGA_STATUS_1_VSY) != 0) S3_RETRACE_LOOP_CHECK; \ +} + +#define S3_CURSOR_WIDTH 64 +#define S3_CURSOR_HEIGHT 64 +#define S3_CURSOR_SIZE ((S3_CURSOR_WIDTH * S3_CURSOR_HEIGHT + 7) / 8) + +#define S3_TILE_SIZE 8 + +/* + * Ok, so the S3 is broken -- it expects bitmaps to come MSB bit order, + * but it's willing to take them in LSB byte order. These macros + * flip bits around without flipping bytes. Instead of using a table + * and burning memory bandwidth, do them in place with the CPU. + */ + +/* The MIPS compiler automatically places these constants in registers */ +#define S3InvertBits32(v) { \ + v = ((v & 0x55555555) << 1) | ((v >> 1) & 0x55555555); \ + v = ((v & 0x33333333) << 2) | ((v >> 2) & 0x33333333); \ + v = ((v & 0x0f0f0f0f) << 4) | ((v >> 4) & 0x0f0f0f0f); \ +} + +#define S3InvertBits16(v) { \ + v = ((v & 0x5555) << 1) | ((v >> 1) & 0x5555); \ + v = ((v & 0x3333) << 2) | ((v >> 2) & 0x3333); \ + v = ((v & 0x0f0f) << 4) | ((v >> 4) & 0x0f0f); \ +} + +#define S3InvertBits8(v) { \ + v = ((v & 0x55) << 1) | ((v >> 1) & 0x55); \ + v = ((v & 0x33) << 2) | ((v >> 2) & 0x33); \ + v = ((v & 0x0f) << 4) | ((v >> 4) & 0x0f); \ +} + +#endif /* _S3_H_ */ diff --git a/hw/kdrive/savage/s3.nick b/hw/kdrive/savage/s3.nick new file mode 100644 index 000000000..500b03d7b --- /dev/null +++ b/hw/kdrive/savage/s3.nick @@ -0,0 +1,41 @@ +/* $XFree86: $ */ + +global f_ref = 14318000; + +function s3_clock (m, n, r) +{ + return f_ref * (m + 2) / ((n + 2) * (2 ^ r)); +} + +function s3_near (f1, f2) +{ + return abs (f1 - f2) < f1 / 10; +} + +function s3_clocks (f) +{ + auto m, n, r, ft; + auto dist, min_dist; + auto min_m, min_n, min_r; + + min_dist = f / 5; + for (r = 0; r <= 3; r++) + for (n = 0; n <= 31; n++) + for (m = 0; m <= 127; m++) + { + ft = s3_clock (m, n, r); + if (s3_near (ft, f)) + printf ("m %d n %d r %d = %d\n", + m, n, r, ft); + dist = abs (f - ft); + if (dist < min_dist) + { + min_dist = dist; + min_m = m; + min_n = n; + min_r = r; + } + } + printf ("m %d n %d r %d f %d dist %d\n", + min_m, min_n, min_r, s3_clock(min_m, min_n, min_r), min_dist); +} diff --git a/hw/kdrive/savage/s3clock.c b/hw/kdrive/savage/s3clock.c new file mode 100644 index 000000000..457f5c57e --- /dev/null +++ b/hw/kdrive/savage/s3clock.c @@ -0,0 +1,86 @@ +/* + * $Id$ + * + * Copyright 1999 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ +/* $XFree86: $ */ + +#include "s3.h" + +/* + * Clock synthesis: + * + * f_out = f_ref * ((M + 2) / ((N + 2) * (1 << R))) + * + * Constraints: + * + * 1. 135MHz <= f_ref * ((M + 2) / (N + 2)) <= 270 MHz + * 2. N >= 1 + * + * Vertical refresh rate = clock / ((hsize + hblank) * (vsize + vblank)) + * Horizontal refresh rate = clock / (hsize + hblank) + */ + +/* all in kHz */ +#define MIN_VCO 135000.0 +#define MAX_VCO 270000.0 + +void +s3GetClock (int target, int *Mp, int *Np, int *Rp, int maxM, int maxN, int maxR) +{ + int M, N, R, bestM, bestN; + int f_vco, f_out; + int err, abserr, besterr; + + /* + * Compute correct R value to keep VCO in range + */ + for (R = 0; R <= maxR; R++) + { + f_vco = target * (1 << R); + if (MIN_VCO <= f_vco && f_vco < MAX_VCO) + break; + } + + /* M = f_out / f_ref * ((N + 2) * (1 << R)); */ + besterr = target; + for (N = 0; N <= maxN; N++) + { + M = (target * (N + 2) * (1 << R) + (S3_CLOCK_REF/2)) / S3_CLOCK_REF - 2; + if (0 <= M && M <= maxM) + { + f_out = S3_CLOCK(M,N,R); + err = target - f_out; + if (err < 0) + err = -err; + if (err < besterr) + { + besterr = err; + bestM = M; + bestN = N; + } + } + } + *Mp = bestM; + *Np = bestN; + *Rp = R; +} diff --git a/hw/kdrive/savage/s3cmap.c b/hw/kdrive/savage/s3cmap.c new file mode 100644 index 000000000..1c10dfa16 --- /dev/null +++ b/hw/kdrive/savage/s3cmap.c @@ -0,0 +1,67 @@ +/* + * $Id$ + * + * Copyright 1999 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ +/* $XFree86: $ */ + +#include "s3.h" + +void +s3GetColors (ScreenPtr pScreen, int ndef, xColorItem *pdefs) +{ + KdScreenPriv(pScreen); + s3CardInfo(pScreenPriv); + S3Ptr s3 = s3c->s3; + VOL8 *dac_rd_ad = &s3->crt_vga_dac_rd_ad; + VOL8 *dac_data = &s3->crt_vga_dac_data; + + while (ndef--) + { + *dac_rd_ad = pdefs->pixel; + pdefs->red = *dac_data << 8; + pdefs->green = *dac_data << 8; + pdefs->blue = *dac_data << 8; + pdefs++; + } +} + +void +s3PutColors (ScreenPtr pScreen, int ndef, xColorItem *pdefs) +{ + KdScreenPriv(pScreen); + s3CardInfo(pScreenPriv); + S3Ptr s3 = s3c->s3; + VOL8 *dac_wt_ad = &s3->crt_vga_dac_wt_ad; + VOL8 *dac_data = &s3->crt_vga_dac_data; + + _s3WaitVRetrace (s3); + while (ndef--) + { + *dac_wt_ad = pdefs->pixel; + *dac_data = pdefs->red >> 8; + *dac_data = pdefs->green >> 8; + *dac_data = pdefs->blue >> 8; + pdefs++; + } +} + diff --git a/hw/kdrive/savage/s3curs.c b/hw/kdrive/savage/s3curs.c new file mode 100644 index 000000000..0fd1397ab --- /dev/null +++ b/hw/kdrive/savage/s3curs.c @@ -0,0 +1,418 @@ +/* + * $Id$ + * + * Copyright 1999 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ +/* $XFree86: $ */ + +#include "s3.h" +#include "cursorstr.h" + +#define SetupCursor(s) KdScreenPriv(s); \ + s3CardInfo(pScreenPriv); \ + s3ScreenInfo(pScreenPriv); \ + S3Ptr s3 = s3c->s3; \ + S3Vga *s3vga = &s3c->s3vga; \ + S3Cursor *pCurPriv = &s3s->cursor + +static void +_s3MoveCursor (ScreenPtr pScreen, int x, int y) +{ + SetupCursor(pScreen); + CARD8 xlow, xhigh, ylow, yhigh; + CARD8 xoff, yoff; + + DRAW_DEBUG ((DEBUG_CURSOR, "s3MoveCursor %d %d", x, y)); + + x -= pCurPriv->xhot; + xoff = 0; + if (x < 0) + { + xoff = -x; + x = 0; + } + y -= pCurPriv->yhot; + yoff = 0; + if (y < 0) + { + yoff = -y; + y = 0; + } + xlow = (CARD8) x; + xhigh = (CARD8) (x >> 8); + ylow = (CARD8) y; + yhigh = (CARD8) (y >> 8); + + + /* This is the recommended order to move the cursor */ + + s3SetImm (s3vga, s3_cursor_xhigh, xhigh); + s3SetImm (s3vga, s3_cursor_xlow, xlow); + s3SetImm (s3vga, s3_cursor_ylow, ylow); + s3SetImm (s3vga, s3_cursor_xoff, xoff); + s3SetImm (s3vga, s3_cursor_yoff, yoff); + s3SetImm (s3vga, s3_cursor_yhigh, yhigh); + + DRAW_DEBUG ((DEBUG_CURSOR, "s3MoveCursor done")); +} + +static void +s3MoveCursor (ScreenPtr pScreen, int x, int y) +{ + SetupCursor (pScreen); + + if (!pCurPriv->has_cursor) + return; + + if (!pScreenPriv->enabled) + return; + + _s3MoveCursor (pScreen, x, y); +} + +static void +s3AllocCursorColors (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + CursorPtr pCursor = pCurPriv->pCursor; + xColorItem sourceColor, maskColor; + + /* + * Set these to an invalid pixel value so that + * when the store colors comes through, the cursor + * won't get recolored + */ + pCurPriv->source = ~0; + pCurPriv->mask = ~0; + /* + * XXX S3 bug workaround; s3 chip doesn't use RGB values from + * the cursor color registers as documented, rather it uses + * them to index the DAC. This is in the errata though. + */ + sourceColor.red = pCursor->foreRed; + sourceColor.green = pCursor->foreGreen; + sourceColor.blue = pCursor->foreBlue; + FakeAllocColor(pScreenPriv->pInstalledmap, &sourceColor); + maskColor.red = pCursor->backRed; + maskColor.green = pCursor->backGreen; + maskColor.blue = pCursor->backBlue; + FakeAllocColor(pScreenPriv->pInstalledmap, &maskColor); + FakeFreeColor(pScreenPriv->pInstalledmap, sourceColor.pixel); + FakeFreeColor(pScreenPriv->pInstalledmap, maskColor.pixel); + + pCurPriv->source = sourceColor.pixel; + pCurPriv->mask = maskColor.pixel; + switch (pScreenPriv->screen->bitsPerPixel) { + case 4: + pCurPriv->source |= pCurPriv->source << 4; + pCurPriv->mask |= pCurPriv->mask << 4; + case 8: + pCurPriv->source |= pCurPriv->source << 8; + pCurPriv->mask |= pCurPriv->mask << 8; + case 16: + pCurPriv->source |= pCurPriv->source << 16; + pCurPriv->mask |= pCurPriv->mask << 16; + } +} + +static void +_s3SetCursorColors (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + /* set foreground */ + /* Reset cursor color stack pointers */ + (void) s3GetImm (s3vga, s3_cursor_enable); + s3SetImm (s3vga, s3_cursor_fg, pCurPriv->source); + s3SetImm (s3vga, s3_cursor_fg, pCurPriv->source >> 8); + s3SetImm (s3vga, s3_cursor_fg, pCurPriv->source >> 16); + + /* set background */ + /* Reset cursor color stack pointers */ + (void) s3GetImm (s3vga, s3_cursor_enable); + s3SetImm (s3vga, s3_cursor_bg, pCurPriv->mask); + s3SetImm (s3vga, s3_cursor_bg, pCurPriv->mask >> 8); + s3SetImm (s3vga, s3_cursor_bg, pCurPriv->mask >> 16); +} + +void +s3RecolorCursor (ScreenPtr pScreen, int ndef, xColorItem *pdef) +{ + SetupCursor (pScreen); + CursorPtr pCursor = pCurPriv->pCursor; + xColorItem sourceColor, maskColor; + + if (!pCurPriv->has_cursor || !pCursor) + return; + + if (!pScreenPriv->enabled) + return; + + if (pdef) + { + while (ndef) + { + if (pdef->pixel == pCurPriv->source || + pdef->pixel == pCurPriv->mask) + break; + ndef--; + } + if (!ndef) + return; + } + s3AllocCursorColors (pScreen); + _s3SetCursorColors (pScreen); +} + +static void +s3LoadCursor (ScreenPtr pScreen, int x, int y) +{ + SetupCursor(pScreen); + CursorPtr pCursor = pCurPriv->pCursor; + CursorBitsPtr bits = pCursor->bits; + int w, h; + unsigned char r[2], g[2], b[2]; + unsigned short *ram, *msk, *mskLine, *src, *srcLine; + unsigned short and, xor; + int i, j; + int cursor_address; + int wsrc; + unsigned char ramdac_control_; + + /* + * Allocate new colors + */ + s3AllocCursorColors (pScreen); + + pCurPriv->pCursor = pCursor; + pCurPriv->xhot = pCursor->bits->xhot; + pCurPriv->yhot = pCursor->bits->yhot; + + /* + * Stick new image into cursor memory + */ + ram = (unsigned short *) s3s->cursor_base; + mskLine = (unsigned short *) bits->mask; + srcLine = (unsigned short *) bits->source; + + h = bits->height; + if (h > S3_CURSOR_HEIGHT) + h = S3_CURSOR_HEIGHT; + + wsrc = BitmapBytePad(bits->width) / 2; /* words per line */ + + for (i = 0; i < S3_CURSOR_HEIGHT; i++) { + msk = mskLine; + src = srcLine; + mskLine += wsrc; + srcLine += wsrc; + for (j = 0; j < S3_CURSOR_WIDTH / 16; j++) { + + unsigned short m, s; + + if (i < h && j < wsrc) + { + m = *msk++; + s = *src++; + xor = m & s; + and = ~m; + } + else + { + and = 0xffff; + xor = 0x0000; + } + + S3InvertBits16(and); + *ram++ = and; + S3InvertBits16(xor); + *ram++ = xor; + } + } + + _s3WaitIdle (s3); + + /* Set new color */ + _s3SetCursorColors (pScreen); + + /* Enable the cursor */ + s3SetImm (s3vga, s3_cursor_enable, 1); + + /* Wait for VRetrace to make sure the position is read */ + _s3WaitVRetrace (s3); + + /* Move to new position */ + _s3MoveCursor (pScreen, x, y); +} + +static void +s3UnloadCursor (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + /* Disable cursor */ + s3SetImm (s3vga, s3_cursor_enable, 0); +} + +static Bool +s3RealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) +{ + SetupCursor(pScreen); + + if (!pScreenPriv->enabled) + return TRUE; + + /* miRecolorCursor does this */ + if (pCurPriv->pCursor == pCursor) + { + if (pCursor) + { + int x, y; + + miPointerPosition (&x, &y); + s3LoadCursor (pScreen, x, y); + } + } + return TRUE; +} + +static Bool +s3UnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) +{ + return TRUE; +} + +static void +s3SetCursor (ScreenPtr pScreen, CursorPtr pCursor, int x, int y) +{ + SetupCursor(pScreen); + + pCurPriv->pCursor = pCursor; + + if (!pScreenPriv->enabled) + return; + + if (pCursor) + s3LoadCursor (pScreen, x, y); + else + s3UnloadCursor (pScreen); +} + +miPointerSpriteFuncRec s3PointerSpriteFuncs = { + s3RealizeCursor, + s3UnrealizeCursor, + s3SetCursor, + s3MoveCursor, +}; + +static void +s3QueryBestSize (int class, + unsigned short *pwidth, unsigned short *pheight, + ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + switch (class) + { + case CursorShape: + if (*pwidth > pCurPriv->width) + *pwidth = pCurPriv->width; + if (*pheight > pCurPriv->height) + *pheight = pCurPriv->height; + if (*pwidth > pScreen->width) + *pwidth = pScreen->width; + if (*pheight > pScreen->height) + *pheight = pScreen->height; + break; + default: + fbQueryBestSize (class, pwidth, pheight, pScreen); + break; + } +} + +Bool +s3CursorInit (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + if (!s3s->cursor_base) + { + DRAW_DEBUG ((DEBUG_CURSOR,"Not enough screen memory for cursor %d", s3d->memory)); + pCurPriv->has_cursor = FALSE; + return FALSE; + } + + pCurPriv->width = S3_CURSOR_WIDTH; + pCurPriv->height= S3_CURSOR_HEIGHT; + pScreen->QueryBestSize = s3QueryBestSize; + miPointerInitialize (pScreen, + &s3PointerSpriteFuncs, + &kdPointerScreenFuncs, + FALSE); + pCurPriv->has_cursor = TRUE; + pCurPriv->pCursor = NULL; + return TRUE; +} + +void +s3CursorEnable (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + DRAW_DEBUG ((DEBUG_INIT, "s3CursorEnable")); + if (pCurPriv->has_cursor) + { + if (pCurPriv->pCursor) + { + int x, y; + + miPointerPosition (&x, &y); + s3LoadCursor (pScreen, x, y); + } + else + s3UnloadCursor (pScreen); + } +} + +void +s3CursorDisable (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + if (!pScreenPriv->enabled) + return; + + if (pCurPriv->has_cursor) + { + if (pCurPriv->pCursor) + { + s3UnloadCursor (pScreen); + } + } +} + +void +s3CursorFini (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + pCurPriv->pCursor = NULL; +} diff --git a/hw/kdrive/savage/s3draw.c b/hw/kdrive/savage/s3draw.c new file mode 100644 index 000000000..c57bc2eb5 --- /dev/null +++ b/hw/kdrive/savage/s3draw.c @@ -0,0 +1,2334 @@ +/* + * $Id$ + * + * Copyright 1999 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ +/* $XFree86: $ */ + +#include "s3.h" +#include "s3draw.h" + +#include "Xmd.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "mistruct.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "fb.h" +#include "migc.h" +#include "miline.h" + +/* + * Map X rops to S3 rops + */ + +short s3alu[16] = { + MIX_0, + MIX_AND, + MIX_SRC_AND_NOT_DST, + MIX_SRC, + MIX_NOT_SRC_AND_DST, + MIX_DST, + MIX_XOR, + MIX_OR, + MIX_NOR, + MIX_XNOR, + MIX_NOT_DST, + MIX_SRC_OR_NOT_DST, + MIX_NOT_SRC, + MIX_NOT_SRC_OR_DST, + MIX_NAND, + MIX_1 +}; + +/* + * Handle pixel transfers + */ + +#define BURST +#ifdef BURST +#define PixTransDeclare VOL32 *pix_trans_base = (VOL32 *) (s3c->registers),\ + *pix_trans = pix_trans_base; +#define PixTransStart(n) if (pix_trans + (n) > pix_trans_base + 8192) pix_trans = pix_trans_base; +#define PixTransStore(t) *pix_trans++ = (t) +#else +#define PixTransDeclare VOL32 *pix_trans = &s3->pix_trans; +#define PixTransStart(n) +#define PixTransStore(t) *pix_trans = (t) +#endif + +int s3GCPrivateIndex; +int s3WindowPrivateIndex; +int s3Generation; + +/* + s3DoBitBlt + ============= + Bit Blit for all window to window blits. +*/ + +#define sourceInvarient(alu) (((alu) & 3) == (((alu) >> 2) & 3)) + +void +s3CopyNtoN (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + SetupS3(pDstDrawable->pScreen); + int srcX, srcY, dstX, dstY; + int w, h; + int flags; + + if (sourceInvarient (pGC->alu)) + { + s3FillBoxSolid (pDstDrawable, nbox, pbox, 0, pGC->alu, pGC->planemask); + return; + } + + _s3SetBlt(s3,pGC->alu,pGC->planemask); + DRAW_DEBUG ((DEBUG_RENDER, "s3CopyNtoN alu %d planemask 0x%x", + pGC->alu, pGC->planemask)); + while (nbox--) + { + w = pbox->x2 - pbox->x1; + h = pbox->y2 - pbox->y1; + flags = 0; + if (reverse) + { + dstX = pbox->x2 - 1; + } + else + { + dstX = pbox->x1; + flags |= INC_X; + } + srcX = dstX + dx; + + if (upsidedown) + { + dstY = pbox->y2 - 1; + } + else + { + dstY = pbox->y1; + flags |= INC_Y; + } + srcY = dstY + dy; + + _s3Blt (s3, srcX, srcY, dstX, dstY, w, h, flags); + pbox++; + } + _s3WaitIdleEmpty(s3); +} + +RegionPtr +s3CopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, + int srcx, int srcy, int width, int height, int dstx, int dsty) +{ + KdScreenPriv(pDstDrawable->pScreen); + + if (pSrcDrawable->type == DRAWABLE_WINDOW && + pDstDrawable->type == DRAWABLE_WINDOW) + { + return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, + dstx, dsty, s3CopyNtoN, 0, 0); + } + return fbCopyArea (pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, dstx, dsty); +} + +typedef struct _s31toNargs { + unsigned long copyPlaneFG, copyPlaneBG; +} s31toNargs; + +void +_s3Stipple (S3CardInfo *s3c, + FbStip *psrcBase, + FbStride widthSrc, + int srcx, + int srcy, + int dstx, + int dsty, + int width, + int height) +{ + S3Ptr s3 = s3c->s3; + FbStip *psrcLine, *psrc; + FbStride widthRest; + FbStip bits, tmp, lastTmp; + int leftShift, rightShift; + int nl, nlMiddle; + int r; + PixTransDeclare; + + /* Compute blt address and parameters */ + psrc = psrcBase + srcy * widthSrc + (srcx >> 5); + nlMiddle = (width + 31) >> 5; + leftShift = srcx & 0x1f; + rightShift = 32 - leftShift; + widthRest = widthSrc - nlMiddle; + + _s3PlaneBlt(s3,dstx,dsty,width,height); + + if (leftShift == 0) + { + while (height--) + { + nl = nlMiddle; + PixTransStart(nl); + while (nl--) + { + tmp = *psrc++; + S3InvertBits32(tmp); + PixTransStore (tmp); + } + psrc += widthRest; + } + } + else + { + widthRest--; + while (height--) + { + bits = *psrc++; + nl = nlMiddle; + PixTransStart(nl); + while (nl--) + { + tmp = FbStipLeft(bits, leftShift); + bits = *psrc++; + tmp |= FbStipRight(bits, rightShift); + S3InvertBits32(tmp); + PixTransStore (tmp); + } + psrc += widthRest; + } + } +} + +void +s3Copy1toN (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + SetupS3(pDstDrawable->pScreen); + + s31toNargs *args = closure; + int dstx, dsty; + FbStip *psrcBase; + FbStride widthSrc; + int srcBpp; + + if (sourceInvarient (pGC->alu)) + { + s3FillBoxSolid (pDstDrawable, nbox, pbox, + pGC->bgPixel, pGC->alu, pGC->planemask); + return; + } + + fbGetStipDrawable (pSrcDrawable, psrcBase, widthSrc, srcBpp); + + _s3SetOpaquePlaneBlt(s3,pGC->alu,pGC->planemask,args->copyPlaneFG, + args->copyPlaneBG); + + while (nbox--) + { + dstx = pbox->x1; + dsty = pbox->y1; + + _s3Stipple (s3c, + psrcBase, widthSrc, + dstx + dx, dsty + dy, + dstx, dsty, + pbox->x2 - dstx, pbox->y2 - dsty); + pbox++; + } + _s3WaitIdleEmpty (s3); +} + +RegionPtr +s3CopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, + int srcx, int srcy, int width, int height, + int dstx, int dsty, unsigned long bitPlane) +{ + KdScreenPriv (pDstDrawable->pScreen); + RegionPtr ret; + s31toNargs args; + + if (pDstDrawable->type == DRAWABLE_WINDOW && + pSrcDrawable->depth == 1) + { + args.copyPlaneFG = pGC->fgPixel; + args.copyPlaneBG = pGC->bgPixel; + return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, + dstx, dsty, s3Copy1toN, bitPlane, &args); + } + return fbCopyPlane(pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, + dstx, dsty, bitPlane); +} + +void +s3FillBoxSolid (DrawablePtr pDrawable, int nBox, BoxPtr pBox, + unsigned long pixel, int alu, unsigned long planemask) +{ + SetupS3(pDrawable->pScreen); + register int r; + + _s3SetSolidFill(s3,pixel,alu,planemask); + + while (nBox--) { + _s3SolidRect(s3,pBox->x1,pBox->y1,pBox->x2-pBox->x1,pBox->y2-pBox->y1); + pBox++; + } + _s3WaitIdleEmpty(s3); +} + +void +_s3SetPattern (ScreenPtr pScreen, + int alu, unsigned long planemask, s3PatternPtr pPattern) +{ + SetupS3(pScreen); + S3PatternCache *cache; + + _s3LoadPattern (pScreen, pPattern); + cache = pPattern->cache; + + switch (pPattern->fillStyle) { + case FillTiled: + _s3SetTile(s3,alu,planemask); + break; + case FillStippled: + _s3SetStipple(s3,alu,planemask,pPattern->fore); + break; + case FillOpaqueStippled: + _s3SetOpaqueStipple(s3,alu,planemask,pPattern->fore,pPattern->back); + break; + } +} + +void +s3FillBoxPattern (DrawablePtr pDrawable, int nBox, BoxPtr pBox, + int alu, unsigned long planemask, s3PatternPtr pPattern) +{ + SetupS3(pDrawable->pScreen); + S3PatternCache *cache; + int patx, paty; + + _s3SetPattern (pDrawable->pScreen, alu, planemask, pPattern); + cache = pPattern->cache; + while (nBox--) + { + _s3PatRect(s3,cache->x, cache->y, + pBox->x1, pBox->y1, + pBox->x2-pBox->x1, pBox->y2-pBox->y1); + pBox++; + } + _s3WaitIdleEmpty(s3); +} + +void +s3FillBoxLargeStipple (DrawablePtr pDrawable, GCPtr pGC, + int nBox, BoxPtr pBox) +{ + SetupS3(pDrawable->pScreen); + DrawablePtr pStipple = &pGC->stipple->drawable; + int xRot = pGC->patOrg.x + pDrawable->x; + int yRot = pGC->patOrg.y + pDrawable->y; + FbStip *stip; + FbStride stipStride; + int stipBpp; + int stipWidth, stipHeight; + int dstX, dstY, width, height; + + stipWidth = pStipple->width; + stipHeight = pStipple->height; + fbGetStipDrawable (pStipple, stip, stipStride, stipBpp); + + if (pGC->fillStyle == FillOpaqueStippled) + { + _s3SetOpaquePlaneBlt(s3,pGC->alu,pGC->planemask, + pGC->fgPixel, pGC->bgPixel); + + } + else + { + _s3SetTransparentPlaneBlt(s3,pGC->alu,pGC->planemask, pGC->fgPixel); + } + + while (nBox--) + { + int stipX, stipY, sx; + int widthTmp; + int h, w; + int x, y; + + dstX = pBox->x1; + dstY = pBox->y1; + width = pBox->x2 - pBox->x1; + height = pBox->y2 - pBox->y1; + pBox++; + modulus (dstY - yRot, stipHeight, stipY); + modulus (dstX - xRot, stipWidth, stipX); + y = dstY; + while (height) + { + h = stipHeight - stipY; + if (h > height) + h = height; + height -= h; + widthTmp = width; + x = dstX; + sx = stipX; + while (widthTmp) + { + w = (stipWidth - sx); + if (w > widthTmp) + w = widthTmp; + widthTmp -= w; + _s3Stipple (s3c, + stip, + stipStride, + sx, stipY, + x, y, + w, h); + x += w; + sx = 0; + } + y += h; + stipY = 0; + } + } + _s3WaitIdleEmpty (s3); +} + +#define NUM_STACK_RECTS 1024 + +void +s3PolyFillRect (DrawablePtr pDrawable, GCPtr pGC, + int nrectFill, xRectangle *prectInit) +{ + s3GCPrivate(pGC); + xRectangle *prect; + RegionPtr prgnClip; + register BoxPtr pbox; + register BoxPtr pboxClipped; + BoxPtr pboxClippedBase; + BoxPtr pextent; + BoxRec stackRects[NUM_STACK_RECTS]; + FbGCPrivPtr fbPriv = fbGetGCPrivate (pGC); + int numRects; + int n; + int xorg, yorg; + int x, y; + + prgnClip = fbGetCompositeClip(pGC); + xorg = pDrawable->x; + yorg = pDrawable->y; + + if (xorg || yorg) + { + prect = prectInit; + n = nrectFill; + while(n--) + { + prect->x += xorg; + prect->y += yorg; + prect++; + } + } + + prect = prectInit; + + numRects = REGION_NUM_RECTS(prgnClip) * nrectFill; + if (numRects > NUM_STACK_RECTS) + { + pboxClippedBase = (BoxPtr)ALLOCATE_LOCAL(numRects * sizeof(BoxRec)); + if (!pboxClippedBase) + return; + } + else + pboxClippedBase = stackRects; + + pboxClipped = pboxClippedBase; + + if (REGION_NUM_RECTS(prgnClip) == 1) + { + int x1, y1, x2, y2, bx2, by2; + + pextent = REGION_RECTS(prgnClip); + x1 = pextent->x1; + y1 = pextent->y1; + x2 = pextent->x2; + y2 = pextent->y2; + while (nrectFill--) + { + if ((pboxClipped->x1 = prect->x) < x1) + pboxClipped->x1 = x1; + + if ((pboxClipped->y1 = prect->y) < y1) + pboxClipped->y1 = y1; + + bx2 = (int) prect->x + (int) prect->width; + if (bx2 > x2) + bx2 = x2; + pboxClipped->x2 = bx2; + + by2 = (int) prect->y + (int) prect->height; + if (by2 > y2) + by2 = y2; + pboxClipped->y2 = by2; + + prect++; + if ((pboxClipped->x1 < pboxClipped->x2) && + (pboxClipped->y1 < pboxClipped->y2)) + { + pboxClipped++; + } + } + } + else + { + int x1, y1, x2, y2, bx2, by2; + + pextent = REGION_EXTENTS(pGC->pScreen, prgnClip); + x1 = pextent->x1; + y1 = pextent->y1; + x2 = pextent->x2; + y2 = pextent->y2; + while (nrectFill--) + { + BoxRec box; + + if ((box.x1 = prect->x) < x1) + box.x1 = x1; + + if ((box.y1 = prect->y) < y1) + box.y1 = y1; + + bx2 = (int) prect->x + (int) prect->width; + if (bx2 > x2) + bx2 = x2; + box.x2 = bx2; + + by2 = (int) prect->y + (int) prect->height; + if (by2 > y2) + by2 = y2; + box.y2 = by2; + + prect++; + + if ((box.x1 >= box.x2) || (box.y1 >= box.y2)) + continue; + + n = REGION_NUM_RECTS (prgnClip); + pbox = REGION_RECTS(prgnClip); + + /* clip the rectangle to each box in the clip region + this is logically equivalent to calling Intersect() + */ + while(n--) + { + pboxClipped->x1 = max(box.x1, pbox->x1); + pboxClipped->y1 = max(box.y1, pbox->y1); + pboxClipped->x2 = min(box.x2, pbox->x2); + pboxClipped->y2 = min(box.y2, pbox->y2); + pbox++; + + /* see if clipping left anything */ + if(pboxClipped->x1 < pboxClipped->x2 && + pboxClipped->y1 < pboxClipped->y2) + { + pboxClipped++; + } + } + } + } + if (pboxClipped != pboxClippedBase) + { + if (pGC->fillStyle == FillSolid) + s3FillBoxSolid(pDrawable, + pboxClipped-pboxClippedBase, pboxClippedBase, + pGC->fgPixel, pGC->alu, pGC->planemask); + else if (s3Priv->pPattern) + s3FillBoxPattern (pDrawable, + pboxClipped-pboxClippedBase, pboxClippedBase, + pGC->alu, pGC->planemask, + s3Priv->pPattern); + else + s3FillBoxLargeStipple (pDrawable, pGC, + pboxClipped-pboxClippedBase, + pboxClippedBase); + } + if (pboxClippedBase != stackRects) + DEALLOCATE_LOCAL(pboxClippedBase); +} + +void +_s3FillSpanLargeStipple (DrawablePtr pDrawable, GCPtr pGC, + int n, DDXPointPtr ppt, int *pwidth) +{ + SetupS3 (pDrawable->pScreen); + DrawablePtr pStipple = &pGC->stipple->drawable; + int xRot = pGC->patOrg.x + pDrawable->x; + int yRot = pGC->patOrg.y + pDrawable->y; + FbStip *stip; + FbStride stipStride; + int stipBpp; + int stipWidth, stipHeight; + int dstX, dstY, width, height; + + stipWidth = pStipple->width; + stipHeight = pStipple->height; + fbGetStipDrawable (pStipple, stip, stipStride, stipBpp); + if (pGC->fillStyle == FillOpaqueStippled) + { + _s3SetOpaquePlaneBlt(s3,pGC->alu,pGC->planemask, + pGC->fgPixel, pGC->bgPixel); + + } + else + { + _s3SetTransparentPlaneBlt(s3,pGC->alu,pGC->planemask, pGC->fgPixel); + } + while (n--) + { + int stipX, stipY, sx; + int w; + int x, y; + + dstX = ppt->x; + dstY = ppt->y; + ppt++; + width = *pwidth++; + modulus (dstY - yRot, stipHeight, stipY); + modulus (dstX - xRot, stipWidth, stipX); + y = dstY; + x = dstX; + sx = stipX; + while (width) + { + w = (stipWidth - sx); + if (w > width) + w = width; + width -= w; + _s3Stipple (s3c, + stip, + stipStride, + sx, stipY, + x, y, + w, 1); + x += w; + sx = 0; + } + } +} + +void +s3FillSpans (DrawablePtr pDrawable, GCPtr pGC, int n, + DDXPointPtr ppt, int *pwidth, int fSorted) +{ + s3GCPrivate(pGC); + SetupS3(pDrawable->pScreen); + int x, y; + int width; + /* next three parameters are post-clip */ + int nTmp; + int *pwidthFree;/* copies of the pointers to free */ + DDXPointPtr pptFree; + FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC); + BoxPtr extents; + S3PatternCache *cache; + + nTmp = n * miFindMaxBand(fbGetCompositeClip(pGC)); + pwidthFree = (int *)ALLOCATE_LOCAL(nTmp * sizeof(int)); + pptFree = (DDXPointRec *)ALLOCATE_LOCAL(nTmp * sizeof(DDXPointRec)); + if(!pptFree || !pwidthFree) + { + if (pptFree) DEALLOCATE_LOCAL(pptFree); + if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree); + return; + } + n = miClipSpans(fbGetCompositeClip(pGC), + ppt, pwidth, n, + pptFree, pwidthFree, fSorted); + pwidth = pwidthFree; + ppt = pptFree; + if (pGC->fillStyle == FillSolid) + { + _s3SetSolidFill(s3,pGC->fgPixel,pGC->alu,pGC->planemask); + while (n--) + { + x = ppt->x; + y = ppt->y; + ppt++; + width = *pwidth++; + if (width) + { + _s3SolidRect(s3,x,y,width,1); + } + } + } + else if (s3Priv->pPattern) + { + _s3SetPattern (pDrawable->pScreen, pGC->alu, pGC->planemask, + s3Priv->pPattern); + cache = s3Priv->pPattern->cache; + while (n--) + { + x = ppt->x; + y = ppt->y; + ppt++; + width = *pwidth++; + if (width) + { + _s3PatRect(s3, cache->x, cache->y, x, y, width, 1); + } + } + } + else + { + _s3FillSpanLargeStipple (pDrawable, pGC, n, ppt, pwidth); + } + _s3WaitIdleEmpty (s3); + DEALLOCATE_LOCAL(pptFree); + DEALLOCATE_LOCAL(pwidthFree); +} + +#include "mifillarc.h" + +#define FILLSPAN(s3,y,__x1,__x2) {\ + DRAW_DEBUG ((DEBUG_ARCS, "FILLSPAN %d: %d->%d", y, __x1, __x2)); \ + if ((__x2) >= (__x1)) {\ + _s3SolidRect(s3,(__x1),(y),(__x2)-(__x1)+1,1); \ + } \ +} + +#define FILLSLICESPANS(flip,__y) \ + if (!flip) \ + { \ + FILLSPAN(s3,__y,xl,xr) \ + } \ + else \ + { \ + xc = xorg - x; \ + FILLSPAN(s3, __y, xc, xr) \ + xc += slw - 1; \ + FILLSPAN(s3, __y, xl, xc) \ + } + +static void +_s3FillEllipse (DrawablePtr pDraw, S3Ptr s3, xArc *arc) +{ + int x, y, e; + int yk, xk, ym, xm, dx, dy, xorg, yorg; + int y_top, y_bot; + miFillArcRec info; + register int xpos; + int slw; + + miFillArcSetup(arc, &info); + MIFILLARCSETUP(); + y_top = pDraw->y + yorg - y; + y_bot = pDraw->y + yorg + y + dy; + xorg += pDraw->x; + while (y) + { + y_top++; + y_bot--; + MIFILLARCSTEP(slw); + if (!slw) + continue; + xpos = xorg - x; + _s3SolidRect (s3,xpos,y_top,slw,1); + if (miFillArcLower(slw)) + _s3SolidRect (s3,xpos,y_bot,slw,1); + } +} + + +static void +_s3FillArcSlice (DrawablePtr pDraw, GCPtr pGC, S3Ptr s3, xArc *arc) +{ + int yk, xk, ym, xm, dx, dy, xorg, yorg, slw; + register int x, y, e; + miFillArcRec info; + miArcSliceRec slice; + int xl, xr, xc; + int y_top, y_bot; + + DRAW_DEBUG ((DEBUG_ARCS, "slice %dx%d+%d+%d %d->%d", + arc->width, arc->height, arc->x, arc->y, + arc->angle1, arc->angle2)); + miFillArcSetup(arc, &info); + miFillArcSliceSetup(arc, &slice, pGC); + DRAW_DEBUG ((DEBUG_ARCS, "edge1.x %d edge2.x %d", + slice.edge1.x, slice.edge2.x)); + MIFILLARCSETUP(); + DRAW_DEBUG ((DEBUG_ARCS, "xorg %d yorg %d", + xorg, yorg)); + xorg += pDraw->x; + yorg += pDraw->y; + y_top = yorg - y; + y_bot = yorg + y + dy; + slice.edge1.x += pDraw->x; + slice.edge2.x += pDraw->x; + DRAW_DEBUG ((DEBUG_ARCS, "xorg %d y_top %d y_bot %d", + xorg, y_top, y_bot)); + while (y > 0) + { + y_top++; + y_bot--; + MIFILLARCSTEP(slw); + MIARCSLICESTEP(slice.edge1); + MIARCSLICESTEP(slice.edge2); + if (miFillSliceUpper(slice)) + { + MIARCSLICEUPPER(xl, xr, slice, slw); + FILLSLICESPANS(slice.flip_top, y_top); + } + if (miFillSliceLower(slice)) + { + MIARCSLICELOWER(xl, xr, slice, slw); + FILLSLICESPANS(slice.flip_bot, y_bot); + } + } +} + +void +s3PolyFillArcSolid (DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs) +{ + SetupS3(pDraw->pScreen); + xArc *arc; + int i; + int x, y; + BoxRec box; + RegionPtr pClip = fbGetCompositeClip(pGC); + BOOL set; + + set = FALSE; + for (; --narcs >= 0; parcs++) + { + if (miFillArcEmpty(parcs)) + continue; + if (miCanFillArc(parcs)) + { + box.x1 = parcs->x + pDraw->x; + box.y1 = parcs->y + pDraw->y; + box.x2 = box.x1 + (int)parcs->width + 1; + box.y2 = box.y1 + (int)parcs->height + 1; + switch (RECT_IN_REGION(pDraw->pScreen, pClip, &box)) + { + case rgnIN: + if (!set) + { + _s3SetSolidFill (s3, pGC->fgPixel, pGC->alu, pGC->planemask); + set = TRUE; + } + if ((parcs->angle2 >= FULLCIRCLE) || + (parcs->angle2 <= -FULLCIRCLE)) + { + DRAW_DEBUG ((DEBUG_ARCS, "Full circle ellipse %dx%d", + parcs->width, parcs->height)); + _s3FillEllipse (pDraw, s3, parcs); + } + else + { + DRAW_DEBUG ((DEBUG_ARCS, "Partial ellipse %dx%d", + parcs->width, parcs->height)); + _s3FillArcSlice (pDraw, pGC, s3, parcs); + } + /* fall through ... */ + case rgnOUT: + continue; + case rgnPART: + break; + } + } + if (set) + { + _s3WaitIdleEmpty(s3); + set = FALSE; + } + miPolyFillArc(pDraw, pGC, 1, parcs); + } + if (set) + { + _s3WaitIdleEmpty(s3); + set = FALSE; + } +} + +void +s3FillPoly1Rect (DrawablePtr pDrawable, GCPtr pGC, int shape, + int mode, int countInit, DDXPointPtr ptsIn) +{ + SetupS3(pDrawable->pScreen); + FbGCPrivPtr fbPriv; + int nwidth; + int maxy; + int count; + register int vertex1, vertex2; + int c; + BoxPtr extents; + int y, sy; + int *vertex1p, *vertex2p; + int *endp; + int x1, x2, sx; + int dx1, dx2; + int dy1, dy2; + int e1, e2; + int step1, step2; + int sign1, sign2; + int h; + int l, r; + int nmiddle; + + if (mode == CoordModePrevious) + { + miFillPolygon (pDrawable, pGC, shape, mode, countInit, ptsIn); + return; + } + + fbPriv = fbGetGCPrivate(pGC); + sy = pDrawable->y; + sx = pDrawable->x; + extents = &fbGetCompositeClip(pGC)->extents; + + y = 32767; + maxy = 0; + vertex2p = (int *) ptsIn; + endp = vertex2p + countInit; + if (shape == Convex) + { + count = countInit; + while (count--) + { + c = *vertex2p; + /* + * Check for negative or over S3 limits + */ + if (c & 0xe000e000) + { + miFillPolygon (pDrawable, pGC, shape, mode, countInit, ptsIn); + return; + } + c = intToY(c); + DRAW_DEBUG ((DEBUG_POLYGON, "Y coordinate %d", c)); + if (c < y) + { + y = c; + vertex1p = vertex2p; + } + vertex2p++; + if (c > maxy) + maxy = c; + } + } + else + { + int yFlip = 0; + dx1 = 1; + x2 = -1; + x1 = -1; + count = countInit; + while (count--) + { + c = *vertex2p; + /* + * Check for negative or over S3 limits + */ + if (c & 0xe000e000) + { + miFillPolygon (pDrawable, pGC, shape, mode, countInit, ptsIn); + return; + } + c = intToY(c); + DRAW_DEBUG ((DEBUG_POLYGON, "Y coordinate %d", c)); + if (c < y) + { + y = c; + vertex1p = vertex2p; + } + vertex2p++; + if (c > maxy) + maxy = c; + if (c == x1) + continue; + if (dx1 > 0) + { + if (x2 < 0) + x2 = c; + else + dx2 = dx1 = (c - x1) >> 31; + } + else + if ((c - x1) >> 31 != dx1) + { + dx1 = ~dx1; + yFlip++; + } + x1 = c; + } + x1 = (x2 - c) >> 31; + if (x1 != dx1) + yFlip++; + if (x1 != dx2) + yFlip++; + if (yFlip != 2) + { + miFillPolygon (pDrawable, pGC, shape, mode, countInit, ptsIn); + return; + } + } + if (y == maxy) + return; + + _s3SetSolidFill(s3,pGC->fgPixel,pGC->alu,pGC->planemask); + _s3SetClip(s3,extents); + + vertex2p = vertex1p; + vertex2 = vertex1 = *vertex2p++; + if (vertex2p == endp) + vertex2p = (int *) ptsIn; +#define Setup(c,x,vertex,dx,dy,e,sign,step) {\ + x = intToX(vertex); \ + if (dy = intToY(c) - y) { \ + dx = intToX(c) - x; \ + step = 0; \ + if (dx >= 0) \ + { \ + e = 0; \ + sign = 1; \ + if (dx >= dy) {\ + step = dx / dy; \ + dx = dx % dy; \ + } \ + } \ + else \ + { \ + e = 1 - dy; \ + sign = -1; \ + dx = -dx; \ + if (dx >= dy) { \ + step = - (dx / dy); \ + dx = dx % dy; \ + } \ + } \ + } \ + x += sx; \ + vertex = c; \ +} + +#define Step(x,dx,dy,e,sign,step) {\ + x += step; \ + if ((e += dx) > 0) \ + { \ + x += sign; \ + e -= dy; \ + } \ +} + sy += y; + DRAW_DEBUG ((DEBUG_POLYGON, "Starting polygon at %d", sy)); + for (;;) + { + DRAW_DEBUG ((DEBUG_POLYGON, "vertex1 0x%x vertex2 0x%x y %d vy1 %d vy2 %d", + vertex1, vertex2, + y, intToY(vertex1), intToY (vertex2))); + if (y == intToY(vertex1)) + { + DRAW_DEBUG ((DEBUG_POLYGON, "Find next -- vertext")); + do + { + if (vertex1p == (int *) ptsIn) + vertex1p = endp; + c = *--vertex1p; + Setup (c,x1,vertex1,dx1,dy1,e1,sign1,step1); + DRAW_DEBUG ((DEBUG_POLYGON, "-- vertex 0x%x y %d", + vertex1, intToY(vertex1))); + } while (y >= intToY(vertex1)); + h = dy1; + } + else + { + Step(x1,dx1,dy1,e1,sign1,step1) + h = intToY(vertex1) - y; + } + if (y == intToY(vertex2)) + { + DRAW_DEBUG ((DEBUG_POLYGON, "Find next ++ vertext")); + do + { + c = *vertex2p++; + if (vertex2p == endp) + vertex2p = (int *) ptsIn; + Setup (c,x2,vertex2,dx2,dy2,e2,sign2,step2) + DRAW_DEBUG ((DEBUG_POLYGON, "++ vertex 0x%x y %d", + vertex1, intToY(vertex1))); + } while (y >= intToY(vertex2)); + if (dy2 < h) + h = dy2; + } + else + { + Step(x2,dx2,dy2,e2,sign2,step2) + if ((c = (intToY(vertex2) - y)) < h) + h = c; + } + DRAW_DEBUG ((DEBUG_POLYGON, "This band %d", h)); + /* fill spans for this segment */ + for (;;) + { + nmiddle = x2 - x1; + DRAW_DEBUG ((DEBUG_POLYGON, "This span %d->%d", x1, x2)); + if (nmiddle) + { + l = x1; + if (nmiddle < 0) + { + nmiddle = -nmiddle; + l = x2; + } + _s3SolidRect(s3,l,sy,nmiddle,1); + } + y++; + sy++; + if (!--h) + break; + Step(x1,dx1,dy1,e1,sign1,step1) + Step(x2,dx2,dy2,e2,sign2,step2) + } + if (y == maxy) + break; + } + _s3ResetClip (s3, pDrawable->pScreen); + _s3WaitIdleEmpty(s3); +} + +void +s3PolyGlyphBltClipped (DrawablePtr pDrawable, + GCPtr pGC, + int x, int y, + unsigned int nglyph, + CharInfoPtr *ppciInit, + pointer pglyphBase) +{ + SetupS3(pDrawable->pScreen); + int h; + int w; + int xBack, yBack; + int hBack, wBack; + int lw; + FontPtr pfont = pGC->font; + CharInfoPtr pci; + unsigned long *bits; + BoxPtr extents; + BoxRec bbox; + CARD32 b; + CharInfoPtr *ppci; + FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC); + RegionPtr pClip = fbGetCompositeClip(pGC); + BoxPtr pBox; + int nbox; + int x1, y1, x2, y2; + unsigned char alu; + Bool locked; + PixTransDeclare; + + x += pDrawable->x; + y += pDrawable->y; + + if (pglyphBase == (pointer) 1) + { + xBack = x; + yBack = y - FONTASCENT(pGC->font); + wBack = 0; + hBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); + if (hBack) + { + h = nglyph; + ppci = ppciInit; + while (h--) + wBack += (*ppci++)->metrics.characterWidth; + } + if (wBack < 0) + { + xBack = xBack + wBack; + wBack = -wBack; + } + if (hBack < 0) + { + yBack = yBack + hBack; + hBack = -hBack; + } + alu = GXcopy; + } + else + { + wBack = 0; + alu = pGC->alu; + } + + if (wBack) + { + _s3SetSolidFill (s3, pGC->bgPixel, GXcopy, pGC->planemask); + for (nbox = REGION_NUM_RECTS (pClip), + pBox = REGION_RECTS (pClip); + nbox--; + pBox++) + { + x1 = xBack; + x2 = xBack + wBack; + y1 = yBack; + y2 = yBack + hBack; + if (x1 < pBox->x1) x1 = pBox->x1; + if (x2 > pBox->x2) x2 = pBox->x2; + if (y1 < pBox->y1) y1 = pBox->y1; + if (y2 > pBox->y2) y2 = pBox->y2; + if (x1 < x2 && y1 < y2) + { + _s3SolidRect (s3, x1, y1, x2 - x1, y2 - y1); + } + } + } + _s3SetTransparentPlaneBlt (s3, alu, pGC->planemask, pGC->fgPixel); + ppci = ppciInit; + locked = TRUE; + while (nglyph--) + { + pci = *ppci++; + h = pci->metrics.ascent + pci->metrics.descent; + w = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; + x1 = x + pci->metrics.leftSideBearing; + y1 = y - pci->metrics.ascent; + bbox.x1 = x1; + bbox.y1 = y1; + bbox.x2 = x1 + w; + bbox.y2 = y1 + h; + switch (RECT_IN_REGION(pGC->pScreen, pClip, &bbox)) + { + case rgnIN: + lw = h * ((w + 31) >> 5); + if (lw) + { + if (!locked) + { + _s3SetTransparentPlaneBlt (s3, alu, pGC->planemask, pGC->fgPixel); + locked = TRUE; + } + _s3PlaneBlt(s3, + x + pci->metrics.leftSideBearing, + y - pci->metrics.ascent, + w, h); + bits = (unsigned long *) pci->bits; + PixTransStart (lw); + while (lw--) + { + b = *bits++; + S3InvertBits32 (b); + PixTransStore(b); + } + } + break; + case rgnPART: + if (locked) + { + _s3WaitIdleEmpty(s3); + locked = FALSE; + } + fbPutXYImage (pDrawable, + pClip, + fbPriv->fg, + fbPriv->bg, + fbPriv->pm, + alu, + FALSE, + x1, y1, + w, h, + (FbStip *) pci->bits, + (w + 31) >> 5, + 0); + break; + case rgnOUT: + break; + } + x += pci->metrics.characterWidth; + } + _s3WaitIdleEmpty(s3); +} + +/* + * Blt glyphs using S3 image transfer register, this does both + * poly glyph blt and image glyph blt (when pglyphBase == 1) + */ + +void +s3PolyGlyphBlt (DrawablePtr pDrawable, + GCPtr pGC, + int x, int y, + unsigned int nglyph, + CharInfoPtr *ppciInit, + pointer pglyphBase) +{ + SetupS3(pDrawable->pScreen); + int h; + int w; + int xBack, yBack; + int hBack, wBack; + int lw; + FontPtr pfont = pGC->font; + CharInfoPtr pci; + unsigned long *bits; + BoxPtr extents; + BoxRec bbox; + CARD32 b; + CharInfoPtr *ppci; + unsigned char alu; + PixTransDeclare; + + x += pDrawable->x; + y += pDrawable->y; + + /* compute an approximate (but covering) bounding box */ + ppci = ppciInit; + w = 0; + h = nglyph; + while (h--) + w += (*ppci++)->metrics.characterWidth; + if (w < 0) + { + bbox.x1 = x + w; + bbox.x2 = x; + } + else + { + bbox.x1 = x; + bbox.x2 = x + w; + } + w = FONTMINBOUNDS(pfont,leftSideBearing); + if (w < 0) + bbox.x1 += w; + w = FONTMAXBOUNDS(pfont, rightSideBearing) - FONTMINBOUNDS(pfont, characterWidth); + if (w > 0) + bbox.x2 += w; + bbox.y1 = y - FONTMAXBOUNDS(pfont,ascent); + bbox.y2 = y + FONTMAXBOUNDS(pfont,descent); + + DRAW_DEBUG ((DEBUG_TEXT, "PolyGlyphBlt %d box is %d %d", nglyph, + bbox.x1, bbox.x2)); + switch (RECT_IN_REGION(pGC->pScreen, fbGetCompositeClip(pGC), &bbox)) + { + case rgnIN: + break; + case rgnPART: + s3PolyGlyphBltClipped(pDrawable, pGC, x - pDrawable->x, + y - pDrawable->y, + nglyph, ppciInit, pglyphBase); + case rgnOUT: + return; + } + + if (pglyphBase == (pointer) 1) + { + xBack = x; + yBack = y - FONTASCENT(pGC->font); + wBack = 0; + hBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); + if (hBack) + { + h = nglyph; + ppci = ppciInit; + while (h--) + wBack += (*ppci++)->metrics.characterWidth; + } + if (wBack < 0) + { + xBack = xBack + wBack; + wBack = -wBack; + } + if (hBack < 0) + { + yBack = yBack + hBack; + hBack = -hBack; + } + alu = GXcopy; + } + else + { + wBack = 0; + alu = pGC->alu; + } + + if (wBack) + { + _s3SetSolidFill (s3, pGC->bgPixel, GXcopy, pGC->planemask); + _s3SolidRect (s3, xBack, yBack, wBack, hBack); + } + _s3SetTransparentPlaneBlt (s3, alu, pGC->planemask, pGC->fgPixel); + ppci = ppciInit; + while (nglyph--) + { + pci = *ppci++; + h = pci->metrics.ascent + pci->metrics.descent; + w = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; + lw = h * ((w + 31) >> 5); + if (lw) + { + _s3PlaneBlt(s3, + x + pci->metrics.leftSideBearing, + y - pci->metrics.ascent, + w, h); + bits = (unsigned long *) pci->bits; + PixTransStart(lw); + while (lw--) + { + b = *bits++; + S3InvertBits32 (b); + PixTransStore(b); + } + } + x += pci->metrics.characterWidth; + } + _s3WaitIdleEmpty(s3); +} + +void +s3ImageGlyphBlt (DrawablePtr pDrawable, + GCPtr pGC, + int x, int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase) +{ + s3PolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, (pointer) 1); +} + +/* + * Blt TE fonts using S3 image transfer. Differs from + * above in that it doesn't need to fill a solid rect for + * the background and it can draw multiple characters at a time + */ + +void +s3ImageTEGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase) +{ + SetupS3(pDrawable->pScreen); + int x, y; + int h, lw, lwTmp; + int w; + FontPtr pfont = pGC->font; + unsigned long *char1, *char2, *char3, *char4; + int widthGlyphs, widthGlyph; + BoxRec bbox; + CARD32 tmp; + PixTransDeclare; + + widthGlyph = FONTMAXBOUNDS(pfont,characterWidth); + if (!widthGlyph) + return; + + h = FONTASCENT(pfont) + FONTDESCENT(pfont); + if (!h) + return; + + DRAW_DEBUG ((DEBUG_TEXT, "ImageTEGlyphBlt chars are %d %d", + widthGlyph, h)); + + x = xInit + FONTMAXBOUNDS(pfont,leftSideBearing) + pDrawable->x; + y = yInit - FONTASCENT(pfont) + pDrawable->y; + + bbox.x1 = x; + bbox.x2 = x + (widthGlyph * nglyph); + bbox.y1 = y; + bbox.y2 = y + h; + + switch (RECT_IN_REGION(pGC->pScreen, fbGetCompositeClip(pGC), &bbox)) + { + case rgnPART: + if (pglyphBase == (pointer) 1) + pglyphBase = 0; + else + pglyphBase = (pointer) 1; + s3PolyGlyphBltClipped(pDrawable, pGC, + xInit, + yInit, + nglyph, ppci, + pglyphBase); + case rgnOUT: + return; + } + + if (pglyphBase == (pointer) 1) + { + _s3SetTransparentPlaneBlt (s3, pGC->alu, pGC->planemask, pGC->fgPixel); + } + else + { + _s3SetOpaquePlaneBlt (s3, GXcopy, pGC->planemask, pGC->fgPixel, pGC->bgPixel); + } + +#define LoopIt(count, w, loadup, fetch) \ + while (nglyph >= count) \ + { \ + nglyph -= count; \ + _s3PlaneBlt (s3, x, y, w, h); \ + x += w; \ + loadup \ + lwTmp = h; \ + PixTransStart(h); \ + while (lwTmp--) { \ + tmp = fetch; \ + S3InvertBits32(tmp); \ + PixTransStore(tmp); \ + } \ + } + + if (widthGlyph <= 8) + { + widthGlyphs = widthGlyph << 2; + LoopIt(4, widthGlyphs, + char1 = (unsigned long *) (*ppci++)->bits; + char2 = (unsigned long *) (*ppci++)->bits; + char3 = (unsigned long *) (*ppci++)->bits; + char4 = (unsigned long *) (*ppci++)->bits;, + (*char1++ | ((*char2++ | ((*char3++ | (*char4++ + << widthGlyph)) + << widthGlyph)) + << widthGlyph))) + } + else if (widthGlyph <= 10) + { + widthGlyphs = (widthGlyph << 1) + widthGlyph; + LoopIt(3, widthGlyphs, + char1 = (unsigned long *) (*ppci++)->bits; + char2 = (unsigned long *) (*ppci++)->bits; + char3 = (unsigned long *) (*ppci++)->bits;, + (*char1++ | ((*char2++ | (*char3++ << widthGlyph)) << widthGlyph))) + } + else if (widthGlyph <= 16) + { + widthGlyphs = widthGlyph << 1; + LoopIt(2, widthGlyphs, + char1 = (unsigned long *) (*ppci++)->bits; + char2 = (unsigned long *) (*ppci++)->bits;, + (*char1++ | (*char2++ << widthGlyph))) + } + lw = h * ((widthGlyph + 31) >> 5); + while (nglyph--) + { + _s3PlaneBlt (s3, x, y, widthGlyph, h); + x += widthGlyph; + char1 = (unsigned long *) (*ppci++)->bits; + lwTmp = lw; + PixTransStart(lw); + while (lwTmp--) + { + tmp = *char1++; + S3InvertBits32(tmp); + PixTransStore(tmp); + } + } + _s3WaitIdleEmpty (s3); +} + +void +s3PolyTEGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, + int x, int y, + unsigned int nglyph, CharInfoPtr *ppci, + pointer pglyphBase) +{ + s3ImageTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, (pointer) 1); +} + +#define _s3ClipLine(s3,cmd,e1,e2,e,len) {\ + DRAW_DEBUG ((DEBUG_RENDER, "clip line 0x%x 0x%x 0x%x 0x%x 0x%x", cmd,e1,e2,e,len)); \ + _s3CmdWait(s3); \ + _s3SetPcnt (s3, (len), 0); \ + _s3SetStep (s3, e2, e1); \ + _s3SetErr (s3, e); \ + _s3SetCmd (s3, CMD_LINE | (cmd) | DRAW | WRTDATA); \ +} + +void +_s3Segment (DrawablePtr pDrawable, + GCPtr pGC, + int x1, + int y1, + int x2, + int y2, + Bool drawLast) +{ + SetupS3(pDrawable->pScreen); + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + RegionPtr pClip = fbGetCompositeClip(pGC); + BoxPtr pBox; + int nBox; + int adx; /* abs values of dx and dy */ + int ady; + int signdx; /* sign of dx and dy */ + int signdy; + int e, e1, e2; /* bresenham error and increments */ + int len; /* length of segment */ + int axis; /* major axis */ + int octant; + int cmd; + unsigned int bias = miGetZeroLineBias(pDrawable->pScreen); + unsigned int oc1; /* outcode of point 1 */ + unsigned int oc2; /* outcode of point 2 */ + + nBox = REGION_NUM_RECTS (pClip); + pBox = REGION_RECTS (pClip); + CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, + 1, 1, octant); + + cmd = LASTPIX; + + if (signdx > 0) + cmd |= INC_X; + if (signdy > 0) + cmd |= INC_Y; + + if (adx > ady) + { + axis = X_AXIS; + e1 = ady << 1; + e2 = e1 - (adx << 1); + e = e1 - adx; + len = adx; + } + else + { + cmd |= YMAJAXIS; + axis = Y_AXIS; + e1 = adx << 1; + e2 = e1 - (ady << 1); + e = e1 - ady; + SetYMajorOctant(octant); + len = ady; + } + + FIXUP_ERROR (e, octant, bias); + + /* we have bresenham parameters and two points. + all we have to do now is clip and draw. + */ + + if (drawLast) + len++; + while(nBox--) + { + oc1 = 0; + oc2 = 0; + OUTCODES(oc1, x1, y1, pBox); + OUTCODES(oc2, x2, y2, pBox); + if ((oc1 | oc2) == 0) + { + _s3SetCur (s3, x1, y1); + _s3ClipLine (s3, cmd, e1, e2, e, len); + break; + } + else if (oc1 & oc2) + { + pBox++; + } + else + { + int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2; + int clip1 = 0, clip2 = 0; + int clipdx, clipdy; + int err; + + if (miZeroClipLine(pBox->x1, pBox->y1, pBox->x2-1, + pBox->y2-1, + &new_x1, &new_y1, &new_x2, &new_y2, + adx, ady, &clip1, &clip2, + octant, bias, oc1, oc2) == -1) + { + pBox++; + continue; + } + + if (axis == X_AXIS) + len = abs(new_x2 - new_x1); + else + len = abs(new_y2 - new_y1); + if (clip2 != 0 || drawLast) + len++; + if (len) + { + /* unwind bresenham error term to first point */ + err = e; + if (clip1) + { + clipdx = abs(new_x1 - x1); + clipdy = abs(new_y1 - y1); + if (axis == X_AXIS) + err += (e2 - e1) * clipdy + e1 * clipdx; + else + err += (e2 - e1) * clipdx + e1 * clipdy; + } + _s3SetCur (s3, new_x1, new_y1); + _s3ClipLine (s3, cmd, e1, e2, err, len); + } + pBox++; + } + } /* while (nBox--) */ +} + +void +s3Polylines (DrawablePtr pDrawable, GCPtr pGC, + int mode, int npt, DDXPointPtr ppt) +{ + SetupS3(pDrawable->pScreen); + int x, y, nx, ny; + int ox = pDrawable->x, oy = pDrawable->y; + + if (!npt) + return; + + _s3SetSolidFill (s3, pGC->fgPixel, pGC->alu, pGC->planemask); + x = ppt->x + ox; + y = ppt->y + oy; + while (--npt) + { + ++ppt; + if (mode == CoordModePrevious) + { + nx = x + ppt->x; + ny = y + ppt->y; + } + else + { + nx = ppt->x + ox; + ny = ppt->y + oy; + } + _s3Segment (pDrawable, pGC, x, y, nx, ny, + npt == 1 && pGC->capStyle != CapNotLast); + x = nx; + y = ny; + } + _s3WaitIdleEmpty(s3); +} + +void +s3PolySegment (DrawablePtr pDrawable, GCPtr pGC, + int nsegInit, xSegment *pSegInit) +{ + SetupS3(pDrawable->pScreen); + int x, y; + int ox = pDrawable->x, oy = pDrawable->y; + RegionPtr pClip = fbGetCompositeClip (pGC); + BoxPtr pBox; + int nbox; + int nseg; + xSegment *pSeg; + int dx, dy; + int maj, min, len, inc; + int t; + CARD32 cmd; + CARD32 init_cmd; + Bool drawLast; + + drawLast = pGC->capStyle != CapNotLast; + _s3SetSolidFill (s3, pGC->fgPixel, pGC->alu, pGC->planemask); + + for (nseg = nsegInit, pSeg = pSegInit; nseg--; pSeg++) + { + _s3Segment (pDrawable, pGC, pSeg->x1 + ox, pSeg->y1 + oy, + pSeg->x2 + ox, pSeg->y2 + oy, drawLast); + + } + _s3WaitIdleEmpty(s3); +} + +/* + * Check to see if a pattern can be painted with the S3 + */ + +#define _s3CheckPatternSize(s) ((s) <= S3_TILE_SIZE && ((s) & ((s) - 1)) == 0) +#define s3CheckPattern(w,h) (_s3CheckPatternSize(w) && _s3CheckPatternSize(h)) + +Bool +s3AllocPattern (ScreenPtr pScreen, + PixmapPtr pPixmap, + int xorg, int yorg, + int fillStyle, Pixel fg, Pixel bg, + s3PatternPtr *ppPattern) +{ + KdScreenPriv(pScreen); + s3ScreenInfo(pScreenPriv); + s3PatternPtr pPattern; + + if (s3s->patterns.cache && fillStyle != FillSolid && + s3CheckPattern (pPixmap->drawable.width, pPixmap->drawable.height)) + { + if (!(pPattern = *ppPattern)) + { + pPattern = (s3PatternPtr) xalloc (sizeof (s3PatternRec)); + if (!pPattern) + return FALSE; + *ppPattern = pPattern; + } + + pPattern->cache = 0; + pPattern->id = 0; + pPattern->pPixmap = pPixmap; + pPattern->fillStyle = fillStyle; + pPattern->xrot = (-xorg) & (S3_TILE_SIZE-1); + pPattern->yrot = (-yorg) & (S3_TILE_SIZE-1); + pPattern->fore = fg; + pPattern->back = bg; + return TRUE; + } + else + { + if (*ppPattern) + { + xfree (*ppPattern); + *ppPattern = 0; + } + return FALSE; + } +} + +void +s3CheckGCFill (GCPtr pGC) +{ + s3PrivGCPtr s3Priv = s3GetGCPrivate (pGC); + PixmapPtr pPixmap; + + switch (pGC->fillStyle) { + case FillSolid: + pPixmap = 0; + break; + case FillOpaqueStippled: + case FillStippled: + pPixmap = pGC->stipple; + break; + case FillTiled: + pPixmap = pGC->tile.pixmap; + break; + } + s3AllocPattern (pGC->pScreen, + pPixmap, + pGC->patOrg.x + pGC->lastWinOrg.x, + pGC->patOrg.y + pGC->lastWinOrg.y, + pGC->fillStyle, pGC->fgPixel, pGC->bgPixel, + &s3Priv->pPattern); +} + +void +s3MoveGCFill (GCPtr pGC) +{ + s3PrivGCPtr s3Priv = s3GetGCPrivate (pGC); + int xorg, yorg; + s3PatternPtr pPattern; + + if (pPattern = s3Priv->pPattern) + { + /* + * Reset origin + */ + xorg = pGC->patOrg.x + pGC->lastWinOrg.x; + yorg = pGC->patOrg.y + pGC->lastWinOrg.y; + pPattern->xrot = (-xorg) & (S3_TILE_SIZE - 1); + pPattern->yrot = (-yorg) & (S3_TILE_SIZE - 1); + /* + * Invalidate cache entry + */ + pPattern->id = 0; + pPattern->cache = 0; + } +} + +/* + * S3 Patterns. These are always full-depth images, stored in off-screen + * memory. + */ + +Pixel +s3FetchPatternPixel (s3PatternPtr pPattern, int x, int y) +{ + CARD8 *src; + CARD16 *src16; + CARD32 *src32; + PixmapPtr pPixmap = pPattern->pPixmap; + + x = (x + pPattern->xrot) % pPixmap->drawable.width; + y = (y + pPattern->yrot) % pPixmap->drawable.height; + src = (CARD8 *) pPixmap->devPrivate.ptr + y * pPixmap->devKind; + switch (pPixmap->drawable.bitsPerPixel) { + case 1: + return (src[x>>3] >> (x & 7)) & 1 ? 0xffffffff : 0x00; + case 4: + if (x & 1) + return src[x>>1] >> 4; + else + return src[x>>1] & 0xf; + case 8: + return src[x]; + case 16: + src16 = (CARD16 *) src; + return src16[x]; + case 32: + src32 = (CARD32 *) src; + return src32[x]; + } +} + +/* + * Place pattern image on screen; done with S3 locked + */ +void +_s3PutPattern (ScreenPtr pScreen, s3PatternPtr pPattern) +{ + SetupS3(pScreen); + int x, y; + CARD8 *dstLine, *dst8; + CARD16 *dst16; + CARD32 *dst32; + S3PatternCache *cache = pPattern->cache; + + DRAW_DEBUG ((DEBUG_PATTERN, "_s3PutPattern 0x%x id %d to %d %d", + pPattern, pPattern->id, cache->x, cache->y)); + + dstLine = (pScreenPriv->screen->frameBuffer + + cache->y * pScreenPriv->screen->byteStride + + cache->x * pScreenPriv->bytesPerPixel); + + for (y = 0; y < S3_TILE_SIZE; y++) + { + switch (pScreenPriv->screen->bitsPerPixel) { + case 8: + dst8 = dstLine; + for (x = 0; x < S3_TILE_SIZE; x++) + *dst8++ = s3FetchPatternPixel (pPattern, x, y); + DRAW_DEBUG ((DEBUG_PATTERN, "%c%c%c%c%c%c%c%c", + dstLine[0] ? 'X' : ' ', + dstLine[1] ? 'X' : ' ', + dstLine[2] ? 'X' : ' ', + dstLine[3] ? 'X' : ' ', + dstLine[4] ? 'X' : ' ', + dstLine[5] ? 'X' : ' ', + dstLine[6] ? 'X' : ' ', + dstLine[7] ? 'X' : ' ')); + break; + case 16: + dst16 = (CARD16 *) dstLine; + for (x = 0; x < S3_TILE_SIZE; x++) + *dst16++ = s3FetchPatternPixel (pPattern, x, y); + break; + case 32: + dst32 = (CARD32 *) dstLine; + for (x = 0; x < S3_TILE_SIZE; x++) + *dst32++ = s3FetchPatternPixel (pPattern, x, y); + break; + } + dstLine += pScreenPriv->screen->byteStride; + } +} + +/* + * Load a stipple to off-screen memory; done with S3 locked + */ +void +_s3LoadPattern (ScreenPtr pScreen, s3PatternPtr pPattern) +{ + SetupS3(pScreen); + s3ScreenInfo(pScreenPriv); + S3PatternCache *cache; + + DRAW_DEBUG((DEBUG_PATTERN, + "s3LoadPattern 0x%x id %d cache 0x%x cacheid %d", + pPattern, pPattern->id, pPattern->cache, + pPattern->cache ? pPattern->cache->id : -1)); + /* + * Check to see if its still loaded + */ + cache = pPattern->cache; + if (cache && cache->id == pPattern->id) + return; + /* + * Lame replacement strategy; assume we'll have plenty of room. + */ + cache = &s3s->patterns.cache[s3s->patterns.last_used]; + if (++s3s->patterns.last_used == s3s->patterns.ncache) + s3s->patterns.last_used = 0; + cache->id = ++s3s->patterns.last_id; + pPattern->id = cache->id; + pPattern->cache = cache; + _s3PutPattern (pScreen, pPattern); +} + +void +s3DestroyGC (GCPtr pGC) +{ + s3PrivGCPtr s3Priv = s3GetGCPrivate (pGC); + + if (s3Priv->pPattern) + xfree (s3Priv->pPattern); + miDestroyGC (pGC); +} + +GCFuncs s3GCFuncs = { + s3ValidateGC, + miChangeGC, + miCopyGC, + s3DestroyGC, + miChangeClip, + miDestroyClip, + miCopyClip +}; + +int +s3CreateGC (GCPtr pGC) +{ + s3PrivGCPtr s3Priv; + + if (!fbCreateGC (pGC)) + return FALSE; + + if (pGC->depth != 1) + pGC->funcs = &s3GCFuncs; + + s3Priv = s3GetGCPrivate(pGC); + s3Priv->type = DRAWABLE_PIXMAP; + s3Priv->pPattern = 0; + + return TRUE; +} + +Bool +s3CreateWindow (WindowPtr pWin) +{ + if (!KdCreateWindow (pWin)) + return FALSE; + pWin->devPrivates[s3WindowPrivateIndex].ptr = 0; + return TRUE; +} + +Bool +s3DestroyWindow (WindowPtr pWin) +{ + s3PatternPtr pPattern; + if (pPattern = s3GetWindowPrivate(pWin)) + xfree (pPattern); + return fbDestroyWindow (pWin); +} + +Bool +s3ChangeWindowAttributes (WindowPtr pWin, Mask mask) +{ + Bool ret; + s3PatternPtr pPattern; + PixmapPtr pPixmap; + int fillStyle; + + ret = fbChangeWindowAttributes (pWin, mask); + if (mask & CWBackPixmap) + { + if (pWin->backgroundState == BackgroundPixmap) + { + pPixmap = pWin->background.pixmap; + fillStyle = FillTiled; + } + else + { + pPixmap = 0; + fillStyle = FillSolid; + } + pPattern = s3GetWindowPrivate(pWin); + s3AllocPattern (pWin->drawable.pScreen, pPixmap, + pWin->drawable.x, pWin->drawable.y, + fillStyle, 0, 0, &pPattern); + DRAW_DEBUG ((DEBUG_PAINT_WINDOW, "Background pattern 0x%x pixmap 0x%x style %d", + pPattern, pPixmap, fillStyle)); + s3SetWindowPrivate (pWin, pPattern); + } + return ret; +} + +void +s3PaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) +{ + KdScreenPriv(pWin->drawable.pScreen); + s3PatternPtr pPattern; + + DRAW_DEBUG ((DEBUG_PAINT_WINDOW, "s3PaintWindow 0x%x extents %d %d %d %d n %d", + pWin->drawable.id, + pRegion->extents.x1, pRegion->extents.y1, + pRegion->extents.x2, pRegion->extents.y2, + REGION_NUM_RECTS(pRegion))); + if (!REGION_NUM_RECTS(pRegion)) + return; + switch (what) { + case PW_BACKGROUND: + switch (pWin->backgroundState) { + case None: + return; + case ParentRelative: + do { + pWin = pWin->parent; + } while (pWin->backgroundState == ParentRelative); + (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion, + what); + return; + case BackgroundPixmap: + pPattern = s3GetWindowPrivate(pWin); + if (pPattern) + { + s3FillBoxPattern ((DrawablePtr)pWin, + (int)REGION_NUM_RECTS(pRegion), + REGION_RECTS(pRegion), + GXcopy, ~0, pPattern); + return; + } + break; + case BackgroundPixel: + s3FillBoxSolid((DrawablePtr)pWin, + (int)REGION_NUM_RECTS(pRegion), + REGION_RECTS(pRegion), + pWin->background.pixel, GXcopy, ~0); + return; + } + break; + case PW_BORDER: + if (pWin->borderIsPixel) + { + s3FillBoxSolid((DrawablePtr)pWin, + (int)REGION_NUM_RECTS(pRegion), + REGION_RECTS(pRegion), + pWin->border.pixel, GXcopy, ~0); + return; + } + break; + } + fbPaintWindow (pWin, pRegion, what); +} + +void +s3CopyWindowProc (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + SetupS3(pDstDrawable->pScreen); + int srcX, srcY, dstX, dstY; + int w, h; + int flags; + + _s3SetBlt(s3,GXcopy,~0); + while (nbox--) + { + w = pbox->x2 - pbox->x1; + h = pbox->y2 - pbox->y1; + flags = 0; + if (reverse) + { + dstX = pbox->x2 - 1; + } + else + { + dstX = pbox->x1; + flags |= INC_X; + } + srcX = dstX + dx; + + if (upsidedown) + { + dstY = pbox->y2 - 1; + } + else + { + dstY = pbox->y1; + flags |= INC_Y; + } + srcY = dstY + dy; + + _s3Blt (s3, srcX, srcY, dstX, dstY, w, h, flags); + pbox++; + } + _s3WaitIdleEmpty(s3); +} + +void +s3CopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + KdScreenPriv(pScreen); + RegionRec rgnDst; + int dx, dy; + WindowPtr pwinRoot; + + pwinRoot = WindowTable[pWin->drawable.pScreen->myNum]; + + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy); + + REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0); + + REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc); + + fbCopyRegion ((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot, + 0, + &rgnDst, dx, dy, s3CopyWindowProc, 0, 0); + + REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); +} + +Bool +s3DrawInit (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + s3ScreenInfo(pScreenPriv); + int ncache_w, ncache_h, ncache; + int px, py; + S3PatternCache *cache; + + switch (pScreenPriv->screen->bitsPerPixel) { + case 8: + case 16: + case 32: + break; + default: + return FALSE; + } + if (serverGeneration != s3Generation) + { + s3GCPrivateIndex = AllocateGCPrivateIndex (); + s3WindowPrivateIndex = AllocateWindowPrivateIndex (); + s3Generation = serverGeneration; + } + if (!AllocateWindowPrivate(pScreen, s3WindowPrivateIndex, 0)) + return FALSE; + if (!AllocateGCPrivate(pScreen, s3GCPrivateIndex, sizeof (s3PrivGCRec))) + return FALSE; + /* + * Replace various fb screen functions + */ + pScreen->CreateGC = s3CreateGC; + pScreen->CreateWindow = s3CreateWindow; + pScreen->ChangeWindowAttributes = s3ChangeWindowAttributes; + pScreen->DestroyWindow = s3DestroyWindow; + pScreen->PaintWindowBackground = s3PaintWindow; + pScreen->PaintWindowBorder = s3PaintWindow; + pScreen->CopyWindow = s3CopyWindow; + + /* + * Initialize patterns + */ + ncache_w = s3s->offscreen_width / S3_TILE_SIZE; + ncache_h = s3s->offscreen_height / S3_TILE_SIZE; + ncache = ncache_w * ncache_h; + DRAW_DEBUG ((DEBUG_S3INIT, "ncache_w %d ncache_h %d ncache %d", + ncache_w, ncache_h, ncache)); + s3s->patterns.cache = (S3PatternCache *) xalloc (ncache * sizeof (S3PatternCache)); + if (s3s->patterns.cache) + { + DRAW_DEBUG ((DEBUG_S3INIT, "Have pattern cache")); + s3s->patterns.ncache = ncache; + s3s->patterns.last_used = 0; + s3s->patterns.last_id = 0; + cache = s3s->patterns.cache; + for (py = 0; py < ncache_h; py++) + for (px = 0; px < ncache_w; px++) + { + cache->id = 0; + cache->x = s3s->offscreen_x + px * S3_TILE_SIZE; + cache->y = s3s->offscreen_y + py * S3_TILE_SIZE; + cache++; + } + } + return TRUE; +} + +void +s3DrawEnable (ScreenPtr pScreen) +{ + SetupS3(pScreen); + s3ScreenInfo(pScreenPriv); + int c; + + /* + * Flush pattern cache + */ + for (c = 0; c < s3s->patterns.ncache; c++) + s3s->patterns.cache[c].id = 0; + + _s3WaitIdleEmpty(s3); + _s3SetScissorsTl(s3, 0, 0); + _s3SetScissorsBr(s3, pScreenPriv->screen->width - 1, pScreenPriv->screen->height - 1); + _s3SetSolidFill(s3, pScreen->blackPixel, GXcopy, ~0); + _s3SolidRect (s3, 0, 0, pScreenPriv->screen->width, pScreenPriv->screen->height); + _s3WaitIdleEmpty (s3); +} + +void +s3DrawDisable (ScreenPtr pScreen) +{ +} + +void +s3DrawFini (ScreenPtr pScreen) +{ + SetupS3(pScreen); + s3ScreenInfo(pScreenPriv); + + if (s3s->patterns.cache) + { + xfree (s3s->patterns.cache); + s3s->patterns.cache = 0; + s3s->patterns.ncache = 0; + } +} diff --git a/hw/kdrive/savage/s3draw.h b/hw/kdrive/savage/s3draw.h new file mode 100644 index 000000000..14dd1688e --- /dev/null +++ b/hw/kdrive/savage/s3draw.h @@ -0,0 +1,372 @@ +/* + * $Id$ + * + * Copyright 1999 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ +/* $XFree86: $ */ + +#ifndef _S3DRAW_H_ +#define _S3DRAW_H_ + +extern int s3GCPrivateIndex; +extern int s3WindowPrivateIndex; + +typedef struct _s3Pattern { + S3PatternCache *cache; + int id; + PixmapPtr pPixmap; + int fillStyle; + int xrot, yrot; + unsigned int fore, back; +} s3PatternRec, *s3PatternPtr; + +typedef struct _s3PrivGC { + int type; /* type of drawable validated against */ + s3PatternPtr pPattern; /* pattern */ +} s3PrivGCRec, *s3PrivGCPtr; + +#define s3GetGCPrivate(g) ((s3PrivGCPtr) \ + (g)->devPrivates[s3GCPrivateIndex].ptr) + +#define s3GCPrivate(g) s3PrivGCPtr s3Priv = s3GetGCPrivate(g) + +#define s3GetWindowPrivate(w) ((s3PatternPtr) \ + (w)->devPrivates[s3WindowPrivateIndex].ptr) + +#define s3SetWindowPrivate(w,p) (\ + (w)->devPrivates[s3WindowPrivateIndex].ptr = (pointer) p) + + +void _s3LoadPattern (ScreenPtr pScreen, s3PatternPtr pPattern); + +#define SetupS3(s) KdScreenPriv(s); \ + s3CardInfo(pScreenPriv); \ + S3Ptr s3 = s3c->s3 + +#define WIDEN(x) ((unsigned long) (x)) +#define MERGE(a,b) ((WIDEN(a) << 16) | WIDEN(b)) + +#define _s3SetFg(s3,_fg) { \ + DRAW_DEBUG ((DEBUG_REGISTERS, " fg <- 0x%x", _fg));\ + s3->fg = (_fg); \ +} + +#define _s3SetBg(s3,_bg) { \ + DRAW_DEBUG ((DEBUG_REGISTERS, " bg <- 0x%x", _bg));\ + s3->bg = (_bg); \ +} + +#define _s3SetWriteMask(s3,_mask) {\ + DRAW_DEBUG((DEBUG_REGISTERS," write_mask <- 0x%x", _mask)); \ + s3->write_mask = (_mask); \ +} + +#define _s3SetReadMask(s3,_mask) {\ + DRAW_DEBUG((DEBUG_REGISTERS," read_mask <- 0x%x", _mask)); \ + s3->read_mask = (_mask); \ +} + +#define _s3SetPixelControl(s3,_ctl) { \ + DRAW_DEBUG((DEBUG_REGISTERS, " pix_cntl <- 0x%x", PIX_CNTL | (_ctl))); \ + s3->pix_cntl = PIX_CNTL | (_ctl); \ +} + +#define _s3SetFgMix(s3,_mix) { \ + DRAW_DEBUG((DEBUG_REGISTERS, " fg_mix <- 0x%x", _mix)); \ + s3->enh_fg_mix = (_mix); \ +} + +#define _s3SetBgMix(s3,_mix) { \ + DRAW_DEBUG((DEBUG_REGISTERS, " bg_mix <- 0x%x", _mix)); \ + s3->enh_bg_mix = (_mix); \ +} + +#define _s3SetMix(s3,fg_mix,bg_mix) { \ + DRAW_DEBUG((DEBUG_REGISTERS, " alt_mix <- 0x%x", MERGE(fg_mix,bg_mix))); \ + s3->alt_mix = MERGE(fg_mix,bg_mix); \ +} + +#define _s3SetCur(s3,_x,_y) { \ + DRAW_DEBUG ((DEBUG_REGISTERS, " alt_curxy <- 0x%x", MERGE(_x,_y))); \ + s3->alt_curxy = MERGE(_x,_y); \ +} + +#define _s3SetStep(s3,_x,_y) { \ + DRAW_DEBUG ((DEBUG_REGISTERS, " alt_step <- 0x%x", MERGE(_x,_y))); \ + s3->alt_step = MERGE(_x,_y); \ +} + +#define _s3SetErr(s3,_e) { \ + DRAW_DEBUG ((DEBUG_REGISTERS, " err_term <- 0x%x", _e)); \ + s3->err_term = (_e); \ +} + +#define _s3SetPcnt(s3,_x,_y) { \ + DRAW_DEBUG ((DEBUG_REGISTERS, " alt_pcnt <- 0x%x", MERGE(_x,_y))); \ + s3->alt_pcnt = MERGE(_x,_y); \ +} + +#define _s3SetScissorsTl(s3,t,l) {\ + DRAW_DEBUG ((DEBUG_REGISTERS, " scissors_tl <- 0x%x", MERGE(t,l))); \ + s3->scissors_tl = MERGE(t,l); \ +} + +#define _s3SetScissorsBr(s3,b,r) {\ + DRAW_DEBUG ((DEBUG_REGISTERS, " scissors_br <- 0x%x", MERGE(b,r))); \ + s3->scissors_br = MERGE(b,r); \ +} + +#define _s3CmdWait(s3) + +#define _s3SetCmd(s3,_cmd) { \ + DRAW_DEBUG((DEBUG_REGISTERS, " cmd <- 0x%x", _cmd)); \ + _s3CmdWait(s3); \ + s3->cmd_gp_stat = (_cmd); \ + { CARD32 __junk__; __junk__ = s3->cmd_gp_stat; } \ +} + +#define _s3SetSolidFill(s3,pix,alu,mask) { \ + DRAW_DEBUG((DEBUG_SET,"set fill 0x%x %d 0x%x",pix,alu,mask)); \ + _s3SetFg (s3, pix); \ + _s3SetWriteMask(s3,mask); \ + _s3SetMix (s3, FSS_FRGDCOL | s3alu[alu], BSS_BKGDCOL | MIX_SRC); \ + _s3SetPixelControl (s3, MIXSEL_FRGDMIX); \ + DRAW_DEBUG((DEBUG_SET," done")); \ +} + +#define _s3SolidRect(s3,x,y,w,h) {\ + DRAW_DEBUG((DEBUG_RENDER,"solid rect %d,%d %dx%d",x,y,w,h)); \ + _s3CmdWait(s3); \ + _s3SetCur(s3, x, y); \ + _s3SetPcnt (s3, (w)-1, (h)-1); \ + _s3SetCmd (s3, CMD_RECT|INC_X|INC_Y|DRAW|WRTDATA); \ + DRAW_DEBUG((DEBUG_RENDER," done")); \ +} + +#define _s3SolidLine(s3,maj,min,len,cmd) { \ + DRAW_DEBUG ((DEBUG_RENDER, "solid line 0x%x 0x%x 0x%x", maj, min, cmd)); \ + _s3CmdWait(s3); \ + _s3SetPcnt(s3, (len), 0); \ + _s3SetStep(s3, 2*((min) - (maj)), 2*(min)); \ + _s3SetErr(s3, 2*(min) - (maj)); \ + _s3SetCmd (s3, CMD_LINE | (cmd) | DRAW | WRTDATA); \ +} + +#define _s3SetTile(s3,alu,mask) { \ + DRAW_DEBUG ((DEBUG_SET,"set tile %d 0x%x", alu, mask)); \ + _s3SetWriteMask(s3, mask); \ + _s3SetMix(s3, FSS_BITBLT | s3alu[alu], BSS_BITBLT|s3alu[alu]); \ + _s3SetPixelControl (s3, MIXSEL_FRGDMIX); \ + DRAW_DEBUG((DEBUG_SET," done")); \ +} + +/* + * For some reason, MIX_DST doesn't work in this mode; use MIX_OR with + * an explicit 0 pixel value + */ +#define _s3SetStipple(s3,alu,mask,_fg) {\ + DRAW_DEBUG ((DEBUG_SET,"set stipple 0x%x %d 0x%x", _fg, alu, mask)); \ + _s3SetFg (s3, _fg); \ + _s3SetBg (s3, 0); \ + _s3SetWriteMask(s3,mask); \ + _s3SetMix (s3, FSS_FRGDCOL | s3alu[alu], BSS_BKGDCOL|MIX_OR); \ + _s3SetPixelControl (s3, MIXSEL_EXPBLT); \ + DRAW_DEBUG((DEBUG_SET," done")); \ +} + +#define _s3SetOpaqueStipple(s3,alu,mask,_fg,_bg) {\ + DRAW_DEBUG ((DEBUG_SET,"set opaque stipple 0x%x 0x%x %d 0x%x", _fg, _bg, alu, mask)); \ + _s3SetFg (s3, _fg); \ + _s3SetBg (s3, _bg); \ + _s3SetWriteMask(s3,mask); \ + _s3SetMix (s3, FSS_FRGDCOL | s3alu[alu], BSS_BKGDCOL|s3alu[alu]); \ + _s3SetPixelControl (s3, MIXSEL_EXPBLT); \ + DRAW_DEBUG((DEBUG_SET," done")); \ +} + +#define _s3PatRect(s3,px,py,x,y,w,h) {\ + DRAW_DEBUG ((DEBUG_RENDER, "pat rect %d,%d %dx%d", x,y,w,h)); \ + _s3CmdWait(s3); \ + _s3SetCur (s3, px, py); \ + _s3SetStep (s3, x, y); \ + _s3SetPcnt (s3, (w)-1, (h)-1); \ + _s3SetCmd (s3, CMD_PATBLT|INC_X|INC_Y|DRAW|PLANAR|WRTDATA); \ + DRAW_DEBUG((DEBUG_RENDER," done")); \ +} + +#define _s3SetBlt(s3,alu,mask) { \ + DRAW_DEBUG ((DEBUG_SET,"set blt %d 0x%x", alu, mask)); \ + _s3SetPixelControl (s3, MIXSEL_FRGDMIX); \ + _s3SetMix(s3, FSS_BITBLT | s3alu[alu], BSS_BITBLT | s3alu[alu]); \ + _s3SetWriteMask(s3, mask); \ + DRAW_DEBUG((DEBUG_SET," done")); \ +} + +#define _s3Blt(s3,_sx,_sy,_dx,_dy,_w,_h,_dir) { \ + DRAW_DEBUG ((DEBUG_RENDER, "blt %d,%d -> %d,%d %dx%d 0x%x", \ + _sx,_sy,_dx,_dy,_w,_h,_dir)); \ + _s3CmdWait(s3); \ + _s3SetCur(s3,_sx,_sy); \ + _s3SetStep(s3,_dx,_dy); \ + _s3SetPcnt(s3,(_w)-1,(_h)-1); \ + _s3SetCmd (s3, CMD_BITBLT | (_dir) | DRAW | WRTDATA); \ + DRAW_DEBUG((DEBUG_RENDER," done")); \ +} + +#define _s3SetOpaquePlaneBlt(s3,alu,mask,_fg,_bg) {\ + DRAW_DEBUG ((DEBUG_SET,"set opaque plane blt 0x%x 0x%x %d 0x%x", \ + _fg, _bg, alu, mask)); \ + _s3SetFg(s3,_fg); \ + _s3SetBg(s3,_bg); \ + _s3SetWriteMask(s3,mask); \ + _s3SetMix(s3,FSS_FRGDCOL|s3alu[alu], BSS_BKGDCOL|s3alu[alu]); \ + _s3SetPixelControl(s3,MIXSEL_EXPPC); \ + DRAW_DEBUG((DEBUG_SET," done")); \ +} + +#define _s3SetTransparentPlaneBlt(s3,alu,mask,_fg) {\ + DRAW_DEBUG ((DEBUG_SET,"set transparent plane blt 0x%x %d 0x%x", \ + _fg, alu, mask)); \ + _s3SetFg(s3,_fg); \ + _s3SetWriteMask(s3,mask); \ + _s3SetMix(s3,FSS_FRGDCOL|s3alu[alu], BSS_BKGDCOL|MIX_DST); \ + _s3SetPixelControl(s3,MIXSEL_EXPPC); \ + DRAW_DEBUG((DEBUG_SET," done")); \ +} + +/* Across the plane blt */ +#define _s3PlaneBlt(s3,x,y,w,h) {\ + DRAW_DEBUG ((DEBUG_RENDER, "plane blt %d,%d %dx%d", x,y,w,h)); \ + _s3CmdWait(s3); \ + _s3SetCur(s3, x, y); \ + _s3SetPcnt (s3, (w)-1, (h)-1); \ + _s3SetCmd (s3, \ + CMD_RECT| /* Fill rectangle */ \ + BYTSEQ| /* LSB byte order */ \ + _32BIT| /* 32 bit data on 32 bit boundaries */ \ + PCDATA| /* Data from CPU */ \ + INC_X|INC_Y| /* X and Y both increasing */ \ + DRAW| /* Draw, not move */ \ + PLANAR| /* multi pixel */ \ + WRTDATA); \ + DRAW_DEBUG((DEBUG_RENDER," done")); \ +} + +#define _s3SetClip(s3,pbox) {\ + DRAW_DEBUG ((DEBUG_SET, "set clip %dx%d -> %dx%d ", \ + pbox->x1, pbox->y1, pbox->x2, pbox->y2)); \ + _s3WaitEmpty(s3); \ + _s3SetScissorsTl(s3,(pbox)->x1, (pbox)->y1); \ + _s3SetScissorsBr(s3,(pbox)->x2 - 1, (pbox)->y2 - 1); \ + DRAW_DEBUG((DEBUG_SET," done")); \ +} + +#define _s3ResetClip(s3,pScreen) { \ + DRAW_DEBUG ((DEBUG_SET, "reset clip")); \ + _s3WaitEmpty(s3); \ + _s3SetScissorsTl(s3,0,0); \ + _s3SetScissorsBr(s3,pScreen->width - 1, pScreen->height - 1); \ + DRAW_DEBUG((DEBUG_SET," done")); \ +} + +RegionPtr +s3CopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, + int srcx, int srcy, int width, int height, int dstx, int dsty); + +RegionPtr +s3CopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, + int srcx, int srcy, int width, int height, + int dstx, int dsty, unsigned long bitPlane); + +void +s3FillBoxSolid (DrawablePtr pDrawable, int nBox, BoxPtr pBox, + unsigned long pixel, int alu, unsigned long planemask); + +void +s3FillBoxPattern (DrawablePtr pDrawable, int nBox, BoxPtr pBox, + int alu, unsigned long planemask, s3PatternPtr pPattern); + +void +s3PolyFillRect (DrawablePtr pDrawable, GCPtr pGC, + int nrectFill, xRectangle *prectInit); + +void +s3FillSpans (DrawablePtr pDrawable, GCPtr pGC, int n, + DDXPointPtr ppt, int *pwidth, int fSorted); + +void +s3PolyFillArcSolid (DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs); + +void +s3FillPoly1Rect (DrawablePtr pDrawable, GCPtr pGC, int shape, + int mode, int count, DDXPointPtr ptsIn); + +void +s3PolyGlyphBlt (DrawablePtr pDrawable, + GCPtr pGC, + int xInit, int y, + unsigned int nglyphInit, + CharInfoPtr *ppciInit, + pointer pglyphBase); + +void +s3ImageGlyphBlt (DrawablePtr pDrawable, + GCPtr pGC, + int x, int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase); + +void +s3ImageTEGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, + int xInit, int y, + unsigned int nglyphInit, + CharInfoPtr *ppciInit, + pointer pglyphBase); + +void +s3PolyTEGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, + int x, int y, + unsigned int nglyph, CharInfoPtr *ppci, + pointer pglyphBase); + +void +s3Polylines (DrawablePtr pDrawable, GCPtr pGC, + int mode, int nptInit, DDXPointPtr pptInit); + +void +s3PolySegment (DrawablePtr pDrawable, GCPtr pGC, + int nsegInit, xSegment *pSegInit); + +void +s3FillBoxSolid (DrawablePtr pDrawable, int nBox, BoxPtr pBox, + unsigned long pixel, int alu, unsigned long planemask); + +void s3ValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable); + +void +s3CheckGCFill (GCPtr pGC); + +void +s3MoveGCFill (GCPtr pGC); + +#endif diff --git a/hw/kdrive/savage/s3gc.c b/hw/kdrive/savage/s3gc.c new file mode 100644 index 000000000..245dfc483 --- /dev/null +++ b/hw/kdrive/savage/s3gc.c @@ -0,0 +1,388 @@ +/* + * $Id$ + * + * Copyright 1999 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ +/* $XFree86: $ */ + +#include "s3.h" +#include "s3draw.h" + +#include "Xmd.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "mistruct.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "migc.h" + +/* + * Common op groups. Common assumptions: + * + * lineWidth 0 + * lineStyle LineSolid + * fillStyle FillSolid + * rop GXcopy + * font <= 32 pixels wide + */ + +/* TE font, >= 4 pixels wide, one clip rectangle */ +static GCOps s3TEOps1Rect = { + s3FillSpans, + fbSetSpans, + fbPutImage, + s3CopyArea, + s3CopyPlane, + fbPolyPoint, + s3Polylines, + s3PolySegment, + miPolyRectangle, + fbPolyArc, + s3FillPoly1Rect, + s3PolyFillRect, + s3PolyFillArcSolid, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + s3ImageTEGlyphBlt, + s3PolyTEGlyphBlt, + fbPushPixels, +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +extern GCOps fbGCOps; + +/* Non TE font, one clip rectangle */ +static GCOps s3NonTEOps1Rect = { + s3FillSpans, + fbSetSpans, + fbPutImage, + s3CopyArea, + s3CopyPlane, + fbPolyPoint, + s3Polylines, + s3PolySegment, + miPolyRectangle, + fbPolyArc, + s3FillPoly1Rect, + s3PolyFillRect, + s3PolyFillArcSolid, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + s3ImageGlyphBlt, + s3PolyGlyphBlt, + fbPushPixels +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +/* TE font, != 1 clip rect (including 0) */ +static GCOps s3TEOps = { + s3FillSpans, + fbSetSpans, + fbPutImage, + s3CopyArea, + s3CopyPlane, + fbPolyPoint, + s3Polylines, + s3PolySegment, + miPolyRectangle, + fbPolyArc, + miFillPolygon, + s3PolyFillRect, + s3PolyFillArcSolid, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + s3ImageTEGlyphBlt, + s3PolyTEGlyphBlt, + fbPushPixels +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +/* Non TE font, != 1 clip rect (including 0) */ +static GCOps s3NonTEOps = { + s3FillSpans, + fbSetSpans, + fbPutImage, + s3CopyArea, + s3CopyPlane, + fbPolyPoint, + s3Polylines, + s3PolySegment, + miPolyRectangle, + fbPolyArc, + miFillPolygon, + s3PolyFillRect, + s3PolyFillArcSolid, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + s3ImageGlyphBlt, + s3PolyGlyphBlt, + fbPushPixels +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +static GCOps * +s3MatchCommon (DrawablePtr pDraw, GCPtr pGC, FbGCPrivPtr fbPriv) +{ + KdScreenPriv (pDraw->pScreen); + + if (!REGION_NOTEMPTY(pDraw->pScreen,fbGetCompositeClip(pGC))) + { + DRAW_DEBUG ((DEBUG_CLIP, "Empty composite clip, clipping all ops")); + return &kdNoopOps; + } + + if (pDraw->type != DRAWABLE_WINDOW) + return (GCOps *) &fbGCOps; + + if (pGC->lineWidth != 0) + return 0; + if (pGC->lineStyle != LineSolid) + return 0; + if (pGC->fillStyle != FillSolid) + return 0; + if (fbPriv->and != 0) + return 0; + if (pGC->font) + { + if (TERMINALFONT(pGC->font)) + { + if (fbPriv->oneRect) + return &s3TEOps1Rect; + else + return &s3TEOps; + } + else + { + if (fbPriv->oneRect) + return &s3NonTEOps1Rect; + else + return &s3NonTEOps; + } + } + return 0; +} + +void +s3ValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable) +{ + int new_type; /* drawable type has changed */ + int new_onerect; /* onerect value has changed */ + int new_origin; + + /* flags for changing the proc vector */ + FbGCPrivPtr fbPriv; + s3PrivGCPtr s3Priv; + int oneRect; + + fbPriv = fbGetGCPrivate(pGC); + s3Priv = s3GetGCPrivate(pGC); + + new_type = FALSE; + new_onerect = FALSE; + new_origin = FALSE; + + /* + * If the type of drawable has changed, fix up accelerated functions + */ + if (s3Priv->type != pDrawable->type) + { + new_type = TRUE; + s3Priv->type = pDrawable->type; + } + + /* + * Check tile/stipple origin + */ + if (pGC->lastWinOrg.x != pDrawable->x || pGC->lastWinOrg.y != pDrawable->y) + new_origin = TRUE; + + /* + * Call down to FB to set clip list and rrop values + */ + oneRect = fbPriv->oneRect; + + fbValidateGC (pGC, changes, pDrawable); + + if (oneRect != fbPriv->oneRect) + new_onerect = TRUE; + + /* + * Check accelerated pattern if necessary + */ + if (changes & (GCFillStyle|GCStipple|GCTile)) + s3CheckGCFill (pGC); + else if (s3Priv->pPattern && + (new_origin || changes & (GCTileStipXOrigin|GCTileStipYOrigin))) + s3MoveGCFill (pGC); + + /* + * Try to match common vector + */ + + if (new_type || new_onerect || + (changes & (GCLineWidth|GCLineStyle|GCFillStyle| + GCFont|GCForeground|GCFunction|GCPlaneMask))) + { + GCOps *newops; + + if (newops = s3MatchCommon (pDrawable, pGC, fbPriv)) + { + if (pGC->ops->devPrivate.val) + miDestroyGCOps (pGC->ops); + pGC->ops = newops; + return; + } + } + + /* + * No common vector matched, create private ops vector and + * fill it in + */ + if (!pGC->ops->devPrivate.val) + { + /* + * Switch from noop vector by first switching to fb + * vector and fixing it up + */ + if (pGC->ops == &kdNoopOps) + { + pGC->ops = (GCOps *) &fbGCOps; + new_type = TRUE; + } + pGC->ops = miCreateGCOps (pGC->ops); + pGC->ops->devPrivate.val = 1; + } + + /* + * Fills + */ + if (new_type || (changes & (GCFillStyle|GCTile|GCStipple))) + { + pGC->ops->FillSpans = fbFillSpans; + pGC->ops->PolyFillRect = fbPolyFillRect; + if (s3Priv->type == DRAWABLE_WINDOW && + (pGC->fillStyle != FillTiled || s3Priv->pPattern)) + { + pGC->ops->FillSpans = s3FillSpans; + pGC->ops->PolyFillRect = s3PolyFillRect; + } + } + + /* + * Blt + */ + if (new_type) + { + pGC->ops->CopyArea = fbCopyArea; + pGC->ops->CopyPlane = fbCopyPlane; + if (s3Priv->type == DRAWABLE_WINDOW) + { + pGC->ops->CopyArea = s3CopyArea; + pGC->ops->CopyPlane = s3CopyPlane; + } + } + + /* + * Lines + */ + if (new_type || (changes & (GCLineStyle|GCLineWidth|GCFillStyle))) + { + pGC->ops->Polylines = fbPolyLine; + pGC->ops->PolySegment = fbPolySegment; + if (pGC->lineStyle == LineSolid && + pGC->lineWidth == 0 && + pGC->fillStyle == FillSolid && + s3Priv->type == DRAWABLE_WINDOW) + { + pGC->ops->Polylines = s3Polylines; + pGC->ops->PolySegment = s3PolySegment; + } + } + + /* + * Polygons + */ + if (new_type || new_onerect || (changes & (GCFillStyle))) + { + pGC->ops->FillPolygon = miFillPolygon; + if (s3Priv->type == DRAWABLE_WINDOW && + fbPriv->oneRect && + pGC->fillStyle == FillSolid) + { + pGC->ops->FillPolygon = s3FillPoly1Rect; + } + } + + /* + * Filled arcs + */ + if (new_type || (changes & GCFillStyle)) + { + pGC->ops->PolyFillArc = fbPolyFillArc; + if (s3Priv->type == DRAWABLE_WINDOW && + pGC->fillStyle == FillSolid) + { + pGC->ops->PolyFillArc = s3PolyFillArcSolid; + } + } + + /* + * Text + */ + if (new_type || (changes & (GCFont|GCFillStyle))) + { + pGC->ops->PolyGlyphBlt = fbPolyGlyphBlt; + pGC->ops->ImageGlyphBlt = fbImageGlyphBlt; + if (s3Priv->type == DRAWABLE_WINDOW && pGC->font) + { + if (pGC->fillStyle == FillSolid) + { + if (TERMINALFONT(pGC->font)) + pGC->ops->PolyGlyphBlt = s3PolyTEGlyphBlt; + else + pGC->ops->PolyGlyphBlt = s3PolyGlyphBlt; + } + if (TERMINALFONT(pGC->font)) + pGC->ops->ImageGlyphBlt = s3ImageTEGlyphBlt; + else + pGC->ops->ImageGlyphBlt = s3ImageGlyphBlt; + } + } +} diff --git a/hw/kdrive/savage/s3reg.c b/hw/kdrive/savage/s3reg.c new file mode 100644 index 000000000..38ca2e804 --- /dev/null +++ b/hw/kdrive/savage/s3reg.c @@ -0,0 +1,1144 @@ +/* + * $Id$ + * + * Copyright 1999 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ +/* $XFree86: $ */ + +#include "s3reg.h" + +#define CR00 S3_CR+0x00 +#define CR01 S3_CR+0x01 +#define CR02 S3_CR+0x02 +#define CR03 S3_CR+0x03 +#define CR04 S3_CR+0x04 +#define CR05 S3_CR+0x05 +#define CR06 S3_CR+0x06 +#define CR07 S3_CR+0x07 +#define CR08 S3_CR+0x08 +#define CR09 S3_CR+0x09 +#define CR0A S3_CR+0x0A +#define CR0B S3_CR+0x0B +#define CR0C S3_CR+0x0C +#define CR0D S3_CR+0x0D +#define CR0E S3_CR+0x0E +#define CR0F S3_CR+0x0F +#define CR10 S3_CR+0x10 +#define CR11 S3_CR+0x11 +#define CR12 S3_CR+0x12 +#define CR13 S3_CR+0x13 +#define CR14 S3_CR+0x14 +#define CR15 S3_CR+0x15 +#define CR16 S3_CR+0x16 +#define CR17 S3_CR+0x17 +#define CR18 S3_CR+0x18 +#define CR19 S3_CR+0x19 +#define CR1A S3_CR+0x1A +#define CR1B S3_CR+0x1B +#define CR1C S3_CR+0x1C +#define CR1D S3_CR+0x1D +#define CR1E S3_CR+0x1E +#define CR1F S3_CR+0x1F +#define CR20 S3_CR+0x20 +#define CR21 S3_CR+0x21 +#define CR22 S3_CR+0x22 +#define CR23 S3_CR+0x23 +#define CR24 S3_CR+0x24 +#define CR25 S3_CR+0x25 +#define CR26 S3_CR+0x26 +#define CR27 S3_CR+0x27 +#define CR28 S3_CR+0x28 +#define CR29 S3_CR+0x29 +#define CR2A S3_CR+0x2A +#define CR2B S3_CR+0x2B +#define CR2C S3_CR+0x2C +#define CR2D S3_CR+0x2D +#define CR2E S3_CR+0x2E +#define CR2F S3_CR+0x2F +#define CR30 S3_CR+0x30 +#define CR31 S3_CR+0x31 +#define CR32 S3_CR+0x32 +#define CR33 S3_CR+0x33 +#define CR34 S3_CR+0x34 +#define CR35 S3_CR+0x35 +#define CR36 S3_CR+0x36 +#define CR37 S3_CR+0x37 +#define CR38 S3_CR+0x38 +#define CR39 S3_CR+0x39 +#define CR3A S3_CR+0x3A +#define CR3B S3_CR+0x3B +#define CR3C S3_CR+0x3C +#define CR3D S3_CR+0x3D +#define CR3E S3_CR+0x3E +#define CR3F S3_CR+0x3F +#define CR40 S3_CR+0x40 +#define CR41 S3_CR+0x41 +#define CR42 S3_CR+0x42 +#define CR43 S3_CR+0x43 +#define CR44 S3_CR+0x44 +#define CR45 S3_CR+0x45 +#define CR46 S3_CR+0x46 +#define CR47 S3_CR+0x47 +#define CR48 S3_CR+0x48 +#define CR49 S3_CR+0x49 +#define CR4A S3_CR+0x4A +#define CR4B S3_CR+0x4B +#define CR4C S3_CR+0x4C +#define CR4D S3_CR+0x4D +#define CR4E S3_CR+0x4E +#define CR4F S3_CR+0x4F +#define CR50 S3_CR+0x50 +#define CR51 S3_CR+0x51 +#define CR52 S3_CR+0x52 +#define CR53 S3_CR+0x53 +#define CR54 S3_CR+0x54 +#define CR55 S3_CR+0x55 +#define CR56 S3_CR+0x56 +#define CR57 S3_CR+0x57 +#define CR58 S3_CR+0x58 +#define CR59 S3_CR+0x59 +#define CR5A S3_CR+0x5A +#define CR5B S3_CR+0x5B +#define CR5C S3_CR+0x5C +#define CR5D S3_CR+0x5D +#define CR5E S3_CR+0x5E +#define CR5F S3_CR+0x5F +#define CR60 S3_CR+0x60 +#define CR61 S3_CR+0x61 +#define CR62 S3_CR+0x62 +#define CR63 S3_CR+0x63 +#define CR64 S3_CR+0x64 +#define CR65 S3_CR+0x65 +#define CR66 S3_CR+0x66 +#define CR67 S3_CR+0x67 +#define CR68 S3_CR+0x68 +#define CR69 S3_CR+0x69 +#define CR6A S3_CR+0x6A +#define CR6B S3_CR+0x6B +#define CR6C S3_CR+0x6C +#define CR6D S3_CR+0x6D +#define CR6E S3_CR+0x6E +#define CR6F S3_CR+0x6F +#define CR70 S3_CR+0x70 +#define CR71 S3_CR+0x71 +#define CR72 S3_CR+0x72 +#define CR73 S3_CR+0x73 +#define CR74 S3_CR+0x74 +#define CR75 S3_CR+0x75 +#define CR76 S3_CR+0x76 +#define CR77 S3_CR+0x77 +#define CR78 S3_CR+0x78 +#define CR79 S3_CR+0x79 +#define CR7A S3_CR+0x7A +#define CR7B S3_CR+0x7B +#define CR7C S3_CR+0x7C +#define CR7D S3_CR+0x7D +#define CR7E S3_CR+0x7E +#define CR7F S3_CR+0x7F +#define CR80 S3_CR+0x80 +#define CR81 S3_CR+0x81 +#define CR82 S3_CR+0x82 +#define CR83 S3_CR+0x83 +#define CR84 S3_CR+0x84 +#define CR85 S3_CR+0x85 +#define CR86 S3_CR+0x86 +#define CR87 S3_CR+0x87 +#define CR88 S3_CR+0x88 +#define CR89 S3_CR+0x89 +#define CR8A S3_CR+0x8A +#define CR8B S3_CR+0x8B +#define CR8C S3_CR+0x8C +#define CR8D S3_CR+0x8D +#define CR8E S3_CR+0x8E +#define CR8F S3_CR+0x8F +#define CR90 S3_CR+0x90 +#define CR91 S3_CR+0x91 +#define CR92 S3_CR+0x92 +#define CR93 S3_CR+0x93 +#define CR94 S3_CR+0x94 +#define CR95 S3_CR+0x95 +#define CR96 S3_CR+0x96 +#define CR97 S3_CR+0x97 +#define CR98 S3_CR+0x98 +#define CR99 S3_CR+0x99 +#define CR9A S3_CR+0x9A +#define CR9B S3_CR+0x9B +#define CR9C S3_CR+0x9C +#define CR9D S3_CR+0x9D +#define CR9E S3_CR+0x9E +#define CR9F S3_CR+0x9F +#define CRA0 S3_CR+0xA0 +#define CRA1 S3_CR+0xA1 +#define CRA2 S3_CR+0xA2 +#define CRA3 S3_CR+0xA3 +#define CRA4 S3_CR+0xA4 +#define CRA5 S3_CR+0xA5 +#define CRA6 S3_CR+0xA6 +#define CRA7 S3_CR+0xA7 +#define CRA8 S3_CR+0xA8 +#define CRA9 S3_CR+0xA9 +#define CRAA S3_CR+0xAA +#define CRAB S3_CR+0xAB +#define CRAC S3_CR+0xAC +#define CRAD S3_CR+0xAD +#define CRAE S3_CR+0xAE +#define CRAF S3_CR+0xAF +#define CRB0 S3_CR+0xB0 +#define CRB1 S3_CR+0xB1 +#define CRB2 S3_CR+0xB2 +#define CRB3 S3_CR+0xB3 +#define CRB4 S3_CR+0xB4 +#define CRB5 S3_CR+0xB5 +#define CRB6 S3_CR+0xB6 +#define CRB7 S3_CR+0xB7 +#define CRB8 S3_CR+0xB8 +#define CRB9 S3_CR+0xB9 +#define CRBA S3_CR+0xBA +#define CRBB S3_CR+0xBB +#define CRBC S3_CR+0xBC +#define CRBD S3_CR+0xBD +#define CRBE S3_CR+0xBE +#define CRBF S3_CR+0xBF + +#define CR_FIRST CR00 + +VgaReg s3_h_total[] = { + CR00, 0, 8, + CR5D, 0, 1, + CR5F, 0, 2, + VGA_REG_END +}; + +VgaReg s3_h_display_end[] = { + CR01, 0, 8, + CR5D, 1, 1, + CR5F, 2, 2, + VGA_REG_END +}; + +VgaReg s3_h_blank_start[] = { + CR02, 0, 8, + CR5D, 2, 1, + CR5F, 4, 2, + VGA_REG_END +}; + +VgaReg s3_h_blank_end[] = { + CR03, 0, 5, + CR05, 7, 1, + VGA_REG_END +}; + +VgaReg s3_display_skew[] = { + CR03, 5, 2, + VGA_REG_END +}; + +VgaReg s3_h_sync_start[] = { + CR04, 0, 8, + CR5D, 4, 1, + CR5F, 6, 2, + VGA_REG_END +}; + +VgaReg s3_h_sync_end[] = { + CR05, 0, 5, + VGA_REG_END +}; + +VgaReg s3_h_skew[] = { + CR05, 5, 2, + VGA_REG_END +}; + +VgaReg s3_v_total[] = { + CR06, 0, 8, + CR07, 0, 1, + CR07, 5, 1, + CR5E, 0, 1, + VGA_REG_END +}; + +VgaReg s3_preset_row_scan[] = { + CR08, 0, 8, + VGA_REG_END +}; + +VgaReg s3_max_scan_line[] = { + CR09, 0, 5, + VGA_REG_END +}; + +VgaReg s3_start_address[] = { + CR0D, 0, 8, + CR0C, 0, 8, + CR69, 0, 7, + VGA_REG_END +}; + +VgaReg s3_v_retrace_start[] = { + CR10, 0, 8, + CR07, 2, 1, + CR07, 7, 1, + CR5E, 4, 1, + VGA_REG_END +}; + +VgaReg s3_v_retrace_end[] = { + CR11, 0, 4, + VGA_REG_END +}; + +VgaReg s3_clear_v_retrace_int[] = { + CR11, 4, 1, + VGA_REG_END +}; + +VgaReg s3_disable_v_retrace_int[] = { + CR11, 5, 1, + VGA_REG_END +}; + +VgaReg s3_lock_crtc[] = { + CR11, 7, 1, + VGA_REG_END +}; + +VgaReg s3_v_display_end[] = { + CR12, 0, 8, + CR07, 1, 1, + CR07, 6, 1, + CR5E, 1, 1, + VGA_REG_END +}; + +VgaReg s3_screen_offset[] = { + CR13, 0, 8, + CR51, 4, 2, + VGA_REG_END +}; + +VgaReg s3_count_by_4_mode[] = { + CR14, 5, 1, + VGA_REG_END +}; + +VgaReg s3_doubleword_mode[] = { + CR14, 6, 1, + VGA_REG_END +}; + +VgaReg s3_v_blank_start[] = { + CR15, 0, 8, + CR07, 3, 1, + CR09, 5, 1, + CR5E, 2, 1, + VGA_REG_END +}; + +VgaReg s3_v_blank_end[] = { + CR16, 0, 8, + VGA_REG_END +}; + +VgaReg s3_v_total_double[] = { + CR17, 2, 1, + VGA_REG_END +}; + +VgaReg s3_word_mode[] = { + CR17, 3, 1, + VGA_REG_END +}; + +VgaReg s3_byte_mode[] = { + CR17, 6, 1, + VGA_REG_END +}; + +VgaReg s3_line_compare[] = { + CR18, 0, 8, + CR07, 4, 1, + CR09, 6, 1, + CR5E, 6, 1, + VGA_REG_END +}; + +VgaReg s3_device_id[] = { + CR2E, 0, 8, + CR2D, 0, 8, + VGA_REG_END +}; + +VgaReg s3_revision[] = { + CR2F, 0, 8, + VGA_REG_END +}; + +VgaReg s3_enable_vga_16bit[] = { + CR31, 2, 1, + VGA_REG_END +}; + +VgaReg s3_enhanced_memory_mapping[] = { + CR31, 3, 1, + VGA_REG_END +}; + +VgaReg s3_lock_dac_writes[] = { + CR33, 4, 1, + VGA_REG_END +}; + +VgaReg s3_border_select[] = { + CR33, 5, 1, + VGA_REG_END +}; + +VgaReg s3_enable_sff[] = { + CR34, 4, 1, + VGA_REG_END +}; + +VgaReg s3_lock_vert[] = { + CR35, 4, 1, + VGA_REG_END +}; + +VgaReg s3_lock_horz[] = { + CR35, 5, 1, + VGA_REG_END +}; + +VgaReg s3_io_disable[] = { + CR36, 4, 1, + VGA_REG_END +}; + +VgaReg s3_mem_size[] = { + CR36, 5, 3, + VGA_REG_END +}; + +VgaReg s3_register_lock_1 [] = { + CR38, 0, 8, /* load with 0x48 */ + VGA_REG_END +}; + +VgaReg s3_register_lock_2 [] = { + CR39, 0, 8, /* load with 0xa0 */ + VGA_REG_END +}; + +VgaReg s3_refresh_control[] = { + CR3A, 0, 2, + VGA_REG_END +}; + +VgaReg s3_enable_256[] = { + CR3A, 4, 1, + VGA_REG_END +}; + +VgaReg s3_disable_pci_read_bursts[] = { + CR3A, 7, 1, + VGA_REG_END +}; + +VgaReg s3_h_start_fifo_fetch[] = { + CR3B, 0, 8, + CR5D, 6, 1, + CR5B, 2, 2, + VGA_REG_END +}; + +VgaReg s3_enable_2d_access[] = { + CR40, 0, 1, + VGA_REG_END +}; + +VgaReg s3_interlace[] = { + CR42, 5, 1, + VGA_REG_END +}; + +VgaReg s3_old_screen_off_8[] = { + CR43, 2, 1, + VGA_REG_END +}; + +VgaReg s3_h_counter_double_mode[] = { + CR43, 7, 1, + VGA_REG_END +}; + +VgaReg s3_cursor_enable[] = { + CR45, 0, 1, + VGA_REG_END +}; + +VgaReg s3_cursor_right[] = { + CR45, 4, 1, + VGA_REG_END +}; + +VgaReg s3_cursor_xhigh[] = { + CR46, 0, 3, + VGA_REG_END +}; + +VgaReg s3_cursor_xlow[] = { + CR47, 0, 8, + VGA_REG_END +}; + +VgaReg s3_cursor_yhigh[] = { + CR48, 0, 3, + VGA_REG_END +}; + +VgaReg s3_cursor_ylow[] = { + CR49, 0, 8, + VGA_REG_END +}; + +VgaReg s3_cursor_fg[] = { + CR4A, 0, 8, + VGA_REG_END +}; + +VgaReg s3_cursor_bg[] = { + CR4B, 0, 8, + VGA_REG_END +}; + +VgaReg s3_cursor_address[] = { + CR4D, 0, 8, + CR4C, 0, 8, + VGA_REG_END +}; + +VgaReg s3_cursor_xoff[] = { + CR4E, 0, 6, + VGA_REG_END +}; + +VgaReg s3_cursor_yoff[] = { + CR4F, 0, 6, + VGA_REG_END +}; + +VgaReg s3_ge_screen_width[] = { + CR50, 6, 2, + CR50, 0, 1, + VGA_REG_END +}; + +VgaReg s3_pixel_length[] = { + CR50, 4, 2, + VGA_REG_END +}; + +VgaReg s3_big_endian_linear[] = { + CR53, 1, 2, + VGA_REG_END +}; + +VgaReg s3_mmio_select[] = { + CR53, 3, 2, + VGA_REG_END +}; + +VgaReg s3_mmio_window[] = { + CR53, 5, 1, + VGA_REG_END +}; + +VgaReg s3_swap_nibbles[] = { + CR53, 6, 1, + VGA_REG_END +}; + +VgaReg s3_cursor_ms_x11[] = { + CR55, 4, 1, + VGA_REG_END +}; + +VgaReg s3_linear_window_size[] = { + CR58, 0, 2, + VGA_REG_END +}; + +VgaReg s3_enable_linear[] = { + CR58, 4, 1, + VGA_REG_END +}; + +VgaReg s3_h_blank_extend[] = { + CR5D, 3, 1, + VGA_REG_END +}; + +VgaReg s3_h_sync_extend[] = { + CR5D, 5, 1, + VGA_REG_END +}; + +VgaReg s3_sdclk_skew[] = { + CR60, 0, 4, + VGA_REG_END +}; + +VgaReg s3_delay_blank[] = { + CR65, 3, 2, + VGA_REG_END +}; + +VgaReg s3_delay_h_enable[] = { + CR65, 6, 2, + CR65, 0, 1, + VGA_REG_END +}; + +VgaReg s3_enable_2d_3d[] = { + CR66, 0, 1, + VGA_REG_END +}; + +VgaReg s3_pci_disconnect_enable[] = { + CR66, 3, 1, + VGA_REG_END +}; + +VgaReg s3_pci_retry_enable[] = { + CR66, 7, 1, + VGA_REG_END +}; + +VgaReg s3_color_mode[] = { + CR67, 4, 4, + VGA_REG_END +}; + +VgaReg s3_master_control_unit_timeout[] = { + CR74, 0, 8, + VGA_REG_END +}; + +VgaReg s3_command_buffer_timeout[] = { + CR75, 0, 8, + VGA_REG_END +}; + +VgaReg s3_lpb_timeout[] = { + CR76, 0, 8, + VGA_REG_END +}; + +VgaReg s3_cpu_timeout[] = { + CR78, 0, 8, + VGA_REG_END +}; + +VgaReg s3_2d_graphics_engine_timeout[] = { + CR79, 0, 8, + VGA_REG_END +}; + +VgaReg s3_fifo_drain_delay[] = { + CR85, 0, 3, + VGA_REG_END +}; + +VgaReg s3_fifo_fetch_timing[] = { + CR85, 4, 1, + VGA_REG_END +}; + +VgaReg s3_primary_stream_l1[] = { + CR91, 0, 8, + CR90, 0, 3, + VGA_REG_END +}; + +#define CR_LAST CR91 + +#define SR00 S3_SR+0x00 +#define SR01 S3_SR+0x01 +#define SR02 S3_SR+0x02 +#define SR03 S3_SR+0x03 +#define SR04 S3_SR+0x04 +#define SR05 S3_SR+0x05 +#define SR06 S3_SR+0x06 +#define SR07 S3_SR+0x07 +#define SR08 S3_SR+0x08 +#define SR09 S3_SR+0x09 +#define SR0A S3_SR+0x0A +#define SR0B S3_SR+0x0B +#define SR0C S3_SR+0x0C +#define SR0D S3_SR+0x0D +#define SR0E S3_SR+0x0E +#define SR0F S3_SR+0x0F +#define SR10 S3_SR+0x10 +#define SR11 S3_SR+0x11 +#define SR12 S3_SR+0x12 +#define SR13 S3_SR+0x13 +#define SR14 S3_SR+0x14 +#define SR15 S3_SR+0x15 +#define SR16 S3_SR+0x16 +#define SR17 S3_SR+0x17 +#define SR18 S3_SR+0x18 +#define SR19 S3_SR+0x19 +#define SR1A S3_SR+0x1A +#define SR1B S3_SR+0x1B +#define SR1C S3_SR+0x1C +#define SR1D S3_SR+0x1D +#define SR1E S3_SR+0x1E +#define SR1F S3_SR+0x1F +#define SR20 S3_SR+0x20 +#define SR21 S3_SR+0x21 +#define SR22 S3_SR+0x22 +#define SR23 S3_SR+0x23 +#define SR24 S3_SR+0x24 +#define SR25 S3_SR+0x25 +#define SR26 S3_SR+0x26 +#define SR27 S3_SR+0x27 +#define SR28 S3_SR+0x28 +#define SR29 S3_SR+0x29 +#define SR2A S3_SR+0x2A +#define SR2B S3_SR+0x2B +#define SR2C S3_SR+0x2C +#define SR2D S3_SR+0x2D +#define SR2E S3_SR+0x2E +#define SR2F S3_SR+0x2F +#define SR30 S3_SR+0x30 +#define SR31 S3_SR+0x31 +#define SR32 S3_SR+0x32 +#define SR33 S3_SR+0x33 +#define SR34 S3_SR+0x34 +#define SR35 S3_SR+0x35 +#define SR36 S3_SR+0x36 +#define SR37 S3_SR+0x37 +#define SR38 S3_SR+0x38 +#define SR39 S3_SR+0x39 +#define SR3A S3_SR+0x3A +#define SR3B S3_SR+0x3B +#define SR3C S3_SR+0x3C +#define SR3D S3_SR+0x3D +#define SR3E S3_SR+0x3E +#define SR3F S3_SR+0x3F +#define SR40 S3_SR+0x40 +#define SR41 S3_SR+0x41 +#define SR42 S3_SR+0x42 +#define SR43 S3_SR+0x43 +#define SR44 S3_SR+0x44 +#define SR45 S3_SR+0x45 +#define SR46 S3_SR+0x46 +#define SR47 S3_SR+0x47 +#define SR48 S3_SR+0x48 +#define SR49 S3_SR+0x49 +#define SR4A S3_SR+0x4A +#define SR4B S3_SR+0x4B +#define SR4C S3_SR+0x4C +#define SR4D S3_SR+0x4D +#define SR4E S3_SR+0x4E +#define SR4F S3_SR+0x4F +#define SR50 S3_SR+0x50 +#define SR51 S3_SR+0x51 +#define SR52 S3_SR+0x52 +#define SR53 S3_SR+0x53 +#define SR54 S3_SR+0x54 +#define SR55 S3_SR+0x55 +#define SR56 S3_SR+0x56 +#define SR57 S3_SR+0x57 +#define SR58 S3_SR+0x58 +#define SR59 S3_SR+0x59 +#define SR5A S3_SR+0x5A +#define SR5B S3_SR+0x5B +#define SR5C S3_SR+0x5C +#define SR5D S3_SR+0x5D +#define SR5E S3_SR+0x5E +#define SR5F S3_SR+0x5F +#define SR60 S3_SR+0x60 +#define SR61 S3_SR+0x61 +#define SR62 S3_SR+0x62 +#define SR63 S3_SR+0x63 +#define SR64 S3_SR+0x64 +#define SR65 S3_SR+0x65 +#define SR66 S3_SR+0x66 +#define SR67 S3_SR+0x67 +#define SR68 S3_SR+0x68 +#define SR69 S3_SR+0x69 +#define SR6A S3_SR+0x6A +#define SR6B S3_SR+0x6B +#define SR6C S3_SR+0x6C +#define SR6D S3_SR+0x6D +#define SR6E S3_SR+0x6E +#define SR6F S3_SR+0x6F + +#define SR_FIRST SR02 + +VgaReg s3_dot_clock_8[] = { + SR01, 0, 1, + VGA_REG_END +}; + +VgaReg s3_screen_off[] = { + SR01, 5, 1, + VGA_REG_END +}; + +VgaReg s3_enable_write_plane[] = { + SR02, 0, 4, + VGA_REG_END +}; + +VgaReg s3_extended_memory_access[] = { + SR04, 1, 1, + VGA_REG_END +}; + +VgaReg s3_sequential_addressing_mode[] = { + SR04, 2, 1, + VGA_REG_END +}; + +VgaReg s3_select_chain_4_mode[] = { + SR04, 3, 1, + VGA_REG_END +}; + +VgaReg s3_unlock_extended_sequencer[] = { + SR08, 0, 8, /* write 0x06 */ + VGA_REG_END +}; + +VgaReg s3_linear_addressing_control[] = { + SR09, 0, 1, + VGA_REG_END +}; + +VgaReg s3_disable_io_ports[] = { + SR09, 7, 1, + VGA_REG_END +}; + +VgaReg s3_hsync_control[] = { + SR0D, 4, 2, + VGA_REG_END +}; + +VgaReg s3_vsync_control[] = { + SR0D, 6, 2, + VGA_REG_END +}; + +VgaReg s3_mclk_n[] = { + SR10, 0, 5, + VGA_REG_END +}; + +VgaReg s3_mclk_r[] = { + SR10, 5, 2, + VGA_REG_END +}; + +VgaReg s3_mclk_m[] = { + SR11, 0, 7, + VGA_REG_END +}; + +VgaReg s3_dclk_n[] = { + SR12, 0, 6, + SR29, 4, 1, + VGA_REG_END +}; + +VgaReg s3_dclk_r[] = { + SR12, 6, 2, + SR29, 2, 1, + VGA_REG_END +}; + +VgaReg s3_dclk_m[] = { + SR13, 0, 8, + SR29, 3, 1, + VGA_REG_END +}; + +VgaReg s3_mclk_load[] = { + SR15, 0, 1, + VGA_REG_END +}; + +VgaReg s3_dclk_load[] = { + SR15, 1, 1, + VGA_REG_END +}; + +VgaReg s3_dclk_over_2[] = { + SR15, 4, 1, + VGA_REG_END +}; + +VgaReg s3_clock_load_imm[] = { + SR15, 5, 1, + VGA_REG_END +}; + +VgaReg s3_dclk_invert[] = { + SR15, 6, 1, + VGA_REG_END +}; + +VgaReg s3_enable_clock_double[] = { + SR18, 7, 1, + VGA_REG_END +}; + +VgaReg s3_dclk_double_15_16_invert[] = { + SR1A, 0, 1, + VGA_REG_END +}; + +VgaReg s3_enable_gamma_correction[] = { + SR1B, 3, 1, + VGA_REG_END +}; + +VgaReg s3_enable_8_bit_luts[] = { + SR1B, 4, 1, + VGA_REG_END +}; + +VgaReg s3_dclk_control[] = { + SR1B, 7, 1, + VGA_REG_END +}; + +VgaReg s3_vga_dclk_n[] = { + SR36, 0, 6, + SR39, 4, 1, + VGA_REG_END +}; + +VgaReg s3_vga_dclk_r[] = { + SR36, 6, 2, + SR39, 2, 1, + VGA_REG_END +}; + +VgaReg s3_vga_dclk_m1[] = { + SR37, 0, 8, + SR39, 3, 1, + VGA_REG_END +}; + +VgaReg s3_vga_dclk_m2[] = { + SR38, 0, 8, + SR39, 3, 1, + VGA_REG_END +}; + +VgaReg s3_vga_clk_select[] = { + SR39, 0, 1, + VGA_REG_END +}; + +#define SR_LAST SR39 + +#define AR00 (S3_AR+0x00) +#define AR10 (S3_AR+0x10) +#define AR11 (S3_AR+0x11) +#define AR12 (S3_AR+0x12) +#define AR13 (S3_AR+0x13) +#define AR14 (S3_AR+0x14) + +#define AR_FIRST AR00 + +VgaReg s3_select_graphics_mode[] = { + AR10, 0, 1, + VGA_REG_END +}; + +VgaReg s3_enable_blinking[] = { + AR10, 3, 1, + VGA_REG_END +}; + +#define AR_LAST AR10 + +VgaReg s3_clock_select[] = { + S3_MISC_OUT, 2, 2, + VGA_REG_END +}; + +VgaReg s3_horz_sync_neg[] = { + S3_MISC_OUT, 6, 1, + VGA_REG_END +}; + +VgaReg s3_vert_sync_neg[] = { + S3_MISC_OUT, 7, 1, + VGA_REG_END +}; + +VGA8 +_s3Inb (VgaCard *card, VGA16 port) +{ + VGAVOL8 *reg; + + if (card->closure) + return *(((VGAVOL8 *) card->closure) + port); + else + return VgaInb (port); +} + +void +_s3Outb (VgaCard *card, VGA8 value, VGA16 port) +{ + VGAVOL8 *reg; + + if (card->closure) + *(((VGAVOL8 *) card->closure) + port) = value; + else + VgaOutb (value, port); +} + +void +_s3RegMap (VgaCard *card, VGA16 reg, VgaMap *map, VGABOOL write) +{ + + if (reg < S3_SR + S3_NSR) + { + map->access = VgaAccessIndIo; + map->port = 0x3c4; + map->addr = 0; + map->value = 1; + map->index = reg - S3_SR; + } + else if (reg < S3_GR + S3_NGR) + { + map->access = VgaAccessIndIo; + map->port = 0x3ce; + map->addr = 0; + map->value = 1; + map->index = reg - S3_GR; + } + else if (reg < S3_AR + S3_NAR) + { + reg -= S3_AR; + map->access = VgaAccessDone; + /* reset AFF to index */ + (void) _s3Inb (card, 0x3da); + _s3Outb (card, reg, 0x3c0); + if (write) + _s3Outb (card, map->value, 0x3c0); + else + map->value = _s3Inb (card, 0x3c1); + /* enable video display again */ + (void) _s3Inb (card, 0x3da); + _s3Outb (card, 0x20, 0x3c0); + return; + } + else if (reg < S3_CR + S3_NCR) + { + map->access = VgaAccessIndIo; + map->port = 0x3d4; + map->addr = 0; + map->value = 1; + map->index = reg - S3_CR; + } + else switch (reg) { + case S3_MISC_OUT: + map->access = VgaAccessIo; + if (write) + map->port = 0x3c2; + else + map->port = 0x3cc; + break; + } + if (card->closure) + { + map->port = map->port + (VGA32) card->closure; + if (map->access == VgaAccessIo) + map->access = VgaAccessMem; + if (map->access == VgaAccessIndIo) + map->access = VgaAccessIndMem; + } +} + +VgaSave s3Saves[] = { + CR_FIRST, CR18, + CR31, CR_LAST, + SR_FIRST, SR15, + SR18, SR_LAST, + AR_FIRST, AR_LAST, + S3_MISC_OUT, S3_MISC_OUT, + VGA_SAVE_END +}; + +void +s3RegInit (S3Vga *s3vga, VGAVOL8 *mmio) +{ + s3vga->card.map = _s3RegMap; + s3vga->card.closure = (void *) mmio; + s3vga->card.max = S3_NREG; + s3vga->card.values = s3vga->values; + s3vga->card.saves = s3Saves; +} + +void +s3Save (S3Vga *s3vga) +{ + s3vga->save_lock_crtc = s3Get(s3vga, s3_lock_crtc); + s3SetImm (s3vga, s3_lock_crtc, 0); + s3vga->save_register_lock_1 = s3Get (s3vga, s3_register_lock_1); + s3SetImm (s3vga, s3_register_lock_1, 0x48); + s3vga->save_register_lock_2 = s3Get (s3vga, s3_register_lock_2); + s3SetImm (s3vga, s3_register_lock_2, 0xa0); + s3vga->save_unlock_extended_sequencer = s3Get (s3vga, s3_unlock_extended_sequencer); + s3SetImm (s3vga, s3_unlock_extended_sequencer, 0x06); + s3vga->save_lock_horz = s3Get (s3vga, s3_lock_horz); + s3SetImm (s3vga, s3_lock_horz, 0); + s3vga->save_lock_vert = s3Get (s3vga, s3_lock_vert); + s3SetImm (s3vga, s3_lock_vert, 0); + s3vga->save_dot_clock_8 = s3Get (s3vga, s3_dot_clock_8); + VgaPreserve (&s3vga->card); +} + +void +s3Reset (S3Vga *s3vga) +{ + VgaRestore (&s3vga->card); + s3SetImm (s3vga, s3_clock_load_imm, 1); + s3SetImm (s3vga, s3_clock_load_imm, 0); + s3SetImm (s3vga, s3_dot_clock_8, s3vga->save_dot_clock_8); + s3SetImm (s3vga, s3_lock_vert, s3vga->save_lock_vert); + s3SetImm (s3vga, s3_lock_horz, s3vga->save_lock_horz); + s3SetImm (s3vga, s3_lock_dac_writes, s3vga->save_lock_dac_writes); + s3SetImm (s3vga, s3_unlock_extended_sequencer, s3vga->save_unlock_extended_sequencer); + s3SetImm (s3vga, s3_register_lock_2, s3vga->save_register_lock_2); + s3SetImm (s3vga, s3_register_lock_1, s3vga->save_register_lock_1); + s3SetImm (s3vga, s3_lock_crtc, s3vga->save_lock_crtc); + VgaFinish (&s3vga->card); +} diff --git a/hw/kdrive/savage/s3reg.h b/hw/kdrive/savage/s3reg.h new file mode 100644 index 000000000..f1ac18d03 --- /dev/null +++ b/hw/kdrive/savage/s3reg.h @@ -0,0 +1,195 @@ +/* + * $Id$ + * + * Copyright 1999 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ +/* $XFree86: $ */ + +#ifndef _S3REG_H_ +#define _S3REG_H_ + +#include "vga.h" + +#define S3_SR 0 +#define S3_NSR 0x70 +#define S3_GR (S3_SR+S3_NSR) +#define S3_NGR 0x09 +#define S3_AR (S3_GR+S3_NGR) +#define S3_NAR 0x15 +#define S3_CR (S3_AR+S3_NAR) +#define S3_NCR 0xc0 +#define S3_MISC_OUT (S3_CR+S3_NCR) +#define S3_NREG (S3_MISC_OUT+1) + +extern VgaReg s3_h_total[]; +extern VgaReg s3_h_display_end[]; +extern VgaReg s3_h_blank_start[]; +extern VgaReg s3_h_blank_end[]; +extern VgaReg s3_display_skew[]; +extern VgaReg s3_h_sync_start[]; +extern VgaReg s3_h_sync_end[]; +extern VgaReg s3_h_skew[]; +extern VgaReg s3_v_total[]; +extern VgaReg s3_preset_row_scan[]; +extern VgaReg s3_max_scan_line[]; +extern VgaReg s3_start_address[]; +extern VgaReg s3_v_retrace_start[]; +extern VgaReg s3_v_retrace_end[]; +extern VgaReg s3_clear_v_retrace_int[]; +extern VgaReg s3_disable_v_retrace_int[]; +extern VgaReg s3_lock_crtc[]; +extern VgaReg s3_v_display_end[]; +extern VgaReg s3_screen_offset[]; +extern VgaReg s3_count_by_4_mode[]; +extern VgaReg s3_doubleword_mode[]; +extern VgaReg s3_v_blank_start[]; +extern VgaReg s3_v_blank_end[]; +extern VgaReg s3_v_total_double[]; +extern VgaReg s3_word_mode[]; +extern VgaReg s3_byte_mode[]; +extern VgaReg s3_line_compare[]; +extern VgaReg s3_device_id[]; +extern VgaReg s3_revision[]; +extern VgaReg s3_enable_vga_16bit[]; +extern VgaReg s3_enhanced_memory_mapping[]; +extern VgaReg s3_enable_sff[]; +extern VgaReg s3_lock_dac_writes[]; +extern VgaReg s3_border_select[]; +extern VgaReg s3_lock_vert[]; +extern VgaReg s3_lock_horz[]; +extern VgaReg s3_io_disable[]; +extern VgaReg s3_mem_size[]; +extern VgaReg s3_register_lock_1 []; +extern VgaReg s3_register_lock_2 []; +extern VgaReg s3_refresh_control[]; +extern VgaReg s3_enable_256[]; +extern VgaReg s3_disable_pci_read_bursts[]; +extern VgaReg s3_h_start_fifo_fetch[]; +extern VgaReg s3_enable_2d_access[]; +extern VgaReg s3_interlace[]; +extern VgaReg s3_old_screen_off_8[]; +extern VgaReg s3_h_counter_double_mode[]; +extern VgaReg s3_cursor_enable[]; +extern VgaReg s3_cursor_right[]; +extern VgaReg s3_cursor_xhigh[]; +extern VgaReg s3_cursor_xlow[]; +extern VgaReg s3_cursor_yhigh[]; +extern VgaReg s3_cursor_ylow[]; +extern VgaReg s3_cursor_fg[]; +extern VgaReg s3_cursor_bg[]; +extern VgaReg s3_cursor_address[]; +extern VgaReg s3_cursor_xoff[]; +extern VgaReg s3_cursor_yoff[]; +extern VgaReg s3_ge_screen_width[]; +extern VgaReg s3_pixel_length[]; +extern VgaReg s3_big_endian_linear[]; +extern VgaReg s3_mmio_select[]; +extern VgaReg s3_mmio_window[]; +extern VgaReg s3_swap_nibbles[]; +extern VgaReg s3_cursor_ms_x11[]; +extern VgaReg s3_linear_window_size[]; +extern VgaReg s3_enable_linear[]; +extern VgaReg s3_h_blank_extend[]; +extern VgaReg s3_h_sync_extend[]; +extern VgaReg s3_sdclk_skew[]; +extern VgaReg s3_delay_blank[]; +extern VgaReg s3_delay_h_enable[]; +extern VgaReg s3_enable_2d_3d[]; +extern VgaReg s3_pci_disconnect_enable[]; +extern VgaReg s3_pci_retry_enable[]; +extern VgaReg s3_color_mode[]; +extern VgaReg s3_master_control_unit_timeout[]; +extern VgaReg s3_command_buffer_timeout[]; +extern VgaReg s3_lpb_timeout[]; +extern VgaReg s3_cpu_timeout[]; +extern VgaReg s3_2d_graphics_engine_timeout[]; +extern VgaReg s3_fifo_drain_delay[]; +extern VgaReg s3_fifo_fetch_timing[]; +extern VgaReg s3_primary_stream_l1[]; + +extern VgaReg s3_dot_clock_8[]; +extern VgaReg s3_screen_off[]; +extern VgaReg s3_enable_write_plane[]; +extern VgaReg s3_extended_memory_access[]; +extern VgaReg s3_sequential_addressing_mode[]; +extern VgaReg s3_select_chain_4_mode[]; + +extern VgaReg s3_unlock_extended_sequencer[]; +extern VgaReg s3_linear_addressing_control[]; +extern VgaReg s3_disable_io_ports[]; +extern VgaReg s3_hsync_control[]; +extern VgaReg s3_vsync_control[]; +extern VgaReg s3_mclk_n[]; +extern VgaReg s3_mclk_r[]; +extern VgaReg s3_mclk_m[]; +extern VgaReg s3_dclk_n[]; +extern VgaReg s3_dclk_r[]; +extern VgaReg s3_dclk_m[]; +extern VgaReg s3_mclk_load[]; +extern VgaReg s3_dclk_load[]; +extern VgaReg s3_dclk_over_2[]; +extern VgaReg s3_clock_load_imm[]; +extern VgaReg s3_dclk_invert[]; +extern VgaReg s3_enable_clock_double[]; +extern VgaReg s3_dclk_double_15_16_invert[]; +extern VgaReg s3_enable_gamma_correction[]; +extern VgaReg s3_enable_8_bit_luts[]; +extern VgaReg s3_dclk_control[]; +extern VgaReg s3_vga_dclk_n[]; +extern VgaReg s3_vga_dclk_r[]; +extern VgaReg s3_vga_dclk_m1[]; +extern VgaReg s3_vga_dclk_m2[]; +extern VgaReg s3_vga_clk_select[]; +extern VgaReg s3_select_graphics_mode[]; +extern VgaReg s3_enable_blinking[]; +extern VgaReg s3_clock_select[]; +extern VgaReg s3_horz_sync_neg[]; +extern VgaReg s3_vert_sync_neg[]; + +#define s3Get(sv,r) VgaGet(&(sv)->card, (r)) +#define s3GetImm(sv,r) VgaGetImm(&(sv)->card, (r)) +#define s3Set(sv,r,v) VgaSet(&(sv)->card, (r), (v)) +#define s3SetImm(sv,r,v) VgaSetImm(&(sv)->card, (r), (v)) + +typedef struct _s3Vga { + VgaCard card; + VgaValue values[S3_NREG]; + VGA32 save_lock_crtc; + VGA32 save_register_lock_1; + VGA32 save_register_lock_2; + VGA32 save_unlock_extended_sequencer; + VGA32 save_lock_dac_writes; + VGA32 save_lock_horz; + VGA32 save_lock_vert; + VGA32 save_dot_clock_8; +} S3Vga; + +void +s3RegInit (S3Vga *s3vga, VGAVOL8 *mmio); + +void +s3Save (S3Vga *s3vga); + +void +s3Reset (S3Vga *s3vga); + +#endif /* _S3REG_H_ */ diff --git a/hw/kdrive/savage/s3rtst.c b/hw/kdrive/savage/s3rtst.c new file mode 100644 index 000000000..c3989f216 --- /dev/null +++ b/hw/kdrive/savage/s3rtst.c @@ -0,0 +1,141 @@ +/* + * $Id$ + * + * Copyright 1999 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ +/* $XFree86: $ */ + +#include <stdio.h> +#include "s3reg.h" + +typedef struct { + VgaReg *reg; + char *name; +} NamedVgaReg; + +NamedVgaReg s3VRegs[] = { + s3_h_total, "h_total", + s3_h_display_end, "h_display_end", + s3_h_blank_start, "h_blank_start", + s3_h_blank_end, "h_blank_end", + s3_display_skew, "display_skew", + s3_h_sync_start, "h_sync_start", + s3_h_sync_end, "h_sync_end", + s3_h_skew, "h_skew", + s3_v_total, "v_total", + s3_preset_row_scan, "preset_row_scan", + s3_max_scan_line, "max_scan_line", + s3_start_address, "start_address", + s3_v_retrace_start, "v_retrace_start", + s3_v_retrace_end, "v_retrace_end", + s3_clear_v_retrace_int, "clear_v_retrace_int", + s3_disable_v_retrace_int, "disable_v_retrace_int", + s3_lock_crtc, "lock_crtc", + s3_v_display_end, "v_display_end", + s3_screen_offset, "screen_offset", + s3_count_by_4_mode, "count_by_4_mode", + s3_doubleword_mode, "doubleword_mode", + s3_v_blank_start, "v_blank_start", + s3_v_blank_end, "v_blank_end", + s3_v_total_double, "v_total_double", + s3_word_mode, "word_mode", + s3_byte_mode, "byte_mode", + s3_line_compare, "line_compare", + s3_device_id, "device_id", + s3_revision, "revision", + s3_lock_vert, "lock_vert", + s3_lock_horz, "lock_horz", + s3_io_disable, "io_disable", + s3_mem_size, "mem_size", + s3_register_lock_1 , "register_lock_1 ", + s3_register_lock_2 , "register_lock_2 ", + s3_refresh_control, "refresh_control", + s3_enable_256, "enable_256", + s3_enable_pci_read_bursts, "enable_pci_read_bursts", + s3_h_start_fifo_fetch, "h_start_fifo_fetch", + s3_interlace, "interlace", + s3_old_screen_off_8, "old_screen_off_8", + s3_h_counter_double_mode, "h_counter_double_mode", + s3_hardware_cursor_enable, "hardware_cursor_enable", + s3_hardware_cursor_right, "hardware_cursor_right", + s3_hardware_cursor_x, "hardware_cursor_x", + s3_hardware_cursor_y, "hardware_cursor_y", + s3_hardware_cursor_fg, "hardware_cursor_fg", + s3_cursor_address, "cursor_address", + s3_cursor_start_x, "cursor_start_x", + s3_cursor_start_y, "cursor_start_y", + s3_ge_screen_width, "ge_screen_width", + s3_pixel_length, "pixel_length", + s3_big_endian_linear, "big_endian_linear", + s3_mmio_select, "mmio_select", + s3_mmio_window, "mmio_window", + s3_swap_nibbles, "swap_nibbles", + s3_hardware_cursor_ms_x11, "hardware_cursor_ms_x11", + s3_h_blank_extend, "h_blank_extend", + s3_h_sync_extend, "h_sync_extend", + s3_enable_2d_3d, "enable_2d_3d", + s3_pci_disconnect_enable, "pci_disconnect_enable", + s3_pci_retry_enable, "pci_retry_enable", + s3_color_mode, "color_mode", + s3_screen_off, "screen_off", + s3_unlock_extended_sequencer, "unlock_extended_sequencer", + s3_disable_io_ports, "disable_io_ports", + s3_hsync_control, "hsync_control", + s3_vsync_control, "vsync_control", + s3_mclk_n, "mclk_n", + s3_mclk_r, "mclk_r", + s3_mclk_m, "mclk_m", + s3_dclk_n, "dclk_n", + s3_dclk_r, "dclk_r", + s3_dclk_m, "dclk_m", + s3_mclk_load, "mclk_load", + s3_dclk_load, "dclk_load", + s3_dclk_over_2, "dclk_over_2", + s3_clock_load_imm, "clock_load_imm", + s3_dclk_invert, "dclk_invert", + s3_enable_clock_double, "enable_clock_double", + s3_dclk_double_15_16_invert, "dclk_double_15_16_invert", + s3_enable_gamma_correction, "enable_gamma_correction", + s3_enable_8_bit_luts, "enable_8_bit_luts", + s3_dclk_control, "dclk_control", + s3_vga_dclk_n, "vga_dclk_n", + s3_vga_dclk_r, "vga_dclk_r", + s3_vga_dclk_m1, "vga_dclk_m1", + s3_vga_dclk_m2, "vga_dclk_m2", + s3_vga_clk_select, "vga_clk_select", + s3_clock_select, "clock_select", +}; + +#define NUM_S3_VREGS (sizeof (s3VRegs)/ sizeof (s3VRegs[0])) + +main (int argc, char **argv) +{ + int i; + + iopl(3); + s3SetImm(s3_register_lock_1, 0x48); + s3SetImm(s3_register_lock_2, 0xa0); + s3SetImm(s3_unlock_extended_sequencer, 0x06); + for (i = 0; i < NUM_S3_VREGS; i++) + printf ("%-20.20s %8x\n", s3VRegs[i].name, s3Get (s3VRegs[i].reg)); + s3Restore (); +} diff --git a/hw/kdrive/savage/s3stub.c b/hw/kdrive/savage/s3stub.c new file mode 100644 index 000000000..59e187984 --- /dev/null +++ b/hw/kdrive/savage/s3stub.c @@ -0,0 +1,60 @@ +/* + * $Id$ + * + * Copyright 1999 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ +/* $XFree86: $ */ + +#include "s3.h" + +void +InitCard (char *name) +{ + KdCardAttr attr; + CARD32 count; + + count = 0; + while (LinuxFindPci (0x5333, 0x8a22, count, &attr)) + { + KdCardInfoAdd (&s3Funcs, &attr, 0); + count++; + } +} + +void +InitOutput (ScreenInfo *pScreenInfo, int argc, char **argv) +{ + KdInitOutput (pScreenInfo, argc, argv); +} + +void +InitInput (int argc, char **argv) +{ + KdInitInput (&Ps2MouseFuncs, &LinuxKeyboardFuncs); +} + +void +OsVendorInit (void) +{ + KdOsInit (&LinuxFuncs); +} + |