summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Starr <shawn.starr@rogers.com>2014-12-11 06:44:56 +0000
committerShawn Starr <shawn.starr@rogers.com>2014-12-11 06:44:56 +0000
commit13d7b0c0a457b17e60ff5900151b2c6614849b4a (patch)
tree355c5eadaab9f809a281bde4491c39ef12e1adb3
downloadxf86-video-s3virge-exa.git-master.zip
xf86-video-s3virge-exa.git-master.tar.gz
xf86-video-s3virge-exa.git-master.tar.xz
Initial commit of S3virge EXA supportHEADmaster
-rw-r--r--.cvsignore19
-rw-r--r--.gitignore29
-rw-r--r--CALLMAP23
-rw-r--r--COPYING12
-rw-r--r--CVS/Entries11
-rw-r--r--CVS/Entries.Log2
-rw-r--r--CVS/Repository1
-rw-r--r--CVS/Root1
-rw-r--r--Makefile.am29
-rw-r--r--README91
-rw-r--r--README.sgml61
-rw-r--r--TODO_NOTES326
-rwxr-xr-xautogen.sh12
-rw-r--r--configure.ac80
-rw-r--r--man/.cvsignore2
-rw-r--r--man/CVS/Entries4
-rw-r--r--man/CVS/Repository1
-rw-r--r--man/CVS/Root1
-rw-r--r--man/Makefile.am59
-rw-r--r--man/s3virge.man244
-rw-r--r--src/.cvsignore6
-rw-r--r--src/CVS/Entries16
-rw-r--r--src/CVS/Repository1
-rw-r--r--src/CVS/Root1
-rw-r--r--src/Makefile.am46
-rw-r--r--src/newmmio.h619
-rw-r--r--src/regs3v.h310
-rw-r--r--src/s3v.h427
-rw-r--r--src/s3v_accel.c400
-rw-r--r--src/s3v_dac.c125
-rw-r--r--src/s3v_dga.c362
-rw-r--r--src/s3v_driver.c3953
-rw-r--r--src/s3v_exa.c326
-rw-r--r--src/s3v_hwcurs.c266
-rw-r--r--src/s3v_i2c.c120
-rw-r--r--src/s3v_macros.h127
-rw-r--r--src/s3v_rop.h207
-rw-r--r--src/s3v_shadow.c305
-rw-r--r--src/s3v_xaa.c757
-rw-r--r--src/s3v_xv.c981
40 files changed, 10363 insertions, 0 deletions
diff --git a/.cvsignore b/.cvsignore
new file mode 100644
index 0000000..fb1befd
--- /dev/null
+++ b/.cvsignore
@@ -0,0 +1,19 @@
+Makefile
+Makefile.in
+*.la
+*.lo
+aclocal.m4
+autom4te.cache
+config.guess
+config.h
+config.h.in
+config.log
+config.status
+config.sub
+configure
+depcomp
+install-sh
+libtool
+ltmain.sh
+missing
+stamp-h1
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b3b1de1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,29 @@
+ChangeLog
+Makefile
+Makefile.in
+*.la
+*.lo
+aclocal.m4
+autom4te.cache
+config.guess
+config.h
+config.h.in
+config.log
+config.status
+config.sub
+configure
+compile
+depcomp
+install-sh
+libtool
+ltmain.sh
+missing
+releases
+stamp-h1
+stamp-h
+stamp-h.in
+*~
+*.orig
+glint.4
+.deps
+.libs
diff --git a/CALLMAP b/CALLMAP
new file mode 100644
index 0000000..7ca58e0
--- /dev/null
+++ b/CALLMAP
@@ -0,0 +1,23 @@
+-- Only Once, calling order --
+ChipIdentify (S3VIdentify)
+ChipProbe (S3VProbe)
+ Passive only, no ram determination, no writing
+
+-- For each ScrnInfoRec, still calling order --
+ChipPreInit (S3VPreInit)
+ Allows probing and mapping, hardware must remain unchanged
+ ChipGetRec
+
+ChipScreenInit
+ ChipMapMem
+ ChipSave
+ vgaHWSaveMMIO
+ ChipModeInit
+ vtSema=TRUE
+ ChipWriteMode
+ vgaHWRestoreMMIO
+
+
+
+
+$XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/CALLMAP,v 1.1 1998/11/01 12:35:58 dawes Exp $
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..7f33cbf
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,12 @@
+This is a stub file. This package has not yet had its complete licensing
+information compiled. Please see the individual source files for details on
+your rights to use and modify this software.
+
+Please submit updated COPYING files to the Xorg bugzilla:
+
+https://bugs.freedesktop.org/enter_bug.cgi?product=xorg
+
+All licensing questions regarding this software should be directed at the
+Xorg mailing list:
+
+http://lists.freedesktop.org/mailman/listinfo/xorg
diff --git a/CVS/Entries b/CVS/Entries
new file mode 100644
index 0000000..a9fb17d
--- /dev/null
+++ b/CVS/Entries
@@ -0,0 +1,11 @@
+/.cvsignore/1.1/Mon Nov 21 10:49:17 2005//
+/CALLMAP/1.2/Fri Apr 23 19:43:44 2004//
+/COPYING/1.1/Mon Dec 19 16:25:54 2005//
+/ChangeLog/1.9/Wed Feb 8 16:17:05 2006//
+/Makefile.am/1.3/Mon Oct 3 21:22:08 2005//
+/README/1.1/Tue Oct 4 20:01:03 2005//
+/README.sgml/1.2/Fri Apr 23 19:23:59 2004//
+/TODO_NOTES/1.2/Fri Apr 23 19:43:44 2004//
+/autogen.sh/1.2/Thu Aug 18 09:03:48 2005//
+/configure.ac/1.12/Wed Dec 21 02:30:02 2005//
+D
diff --git a/CVS/Entries.Log b/CVS/Entries.Log
new file mode 100644
index 0000000..31c90bb
--- /dev/null
+++ b/CVS/Entries.Log
@@ -0,0 +1,2 @@
+A D/man////
+A D/src////
diff --git a/CVS/Repository b/CVS/Repository
new file mode 100644
index 0000000..1c19bca
--- /dev/null
+++ b/CVS/Repository
@@ -0,0 +1 @@
+driver/xf86-video-s3virge
diff --git a/CVS/Root b/CVS/Root
new file mode 100644
index 0000000..725164d
--- /dev/null
+++ b/CVS/Root
@@ -0,0 +1 @@
+:pserver:anoncvs@cvs.freedesktop.org:/cvs/xorg
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..4443535
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,29 @@
+# Copyright 2005 Adam Jackson.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# on the rights to use, copy, modify, merge, publish, distribute, sub
+# license, and/or sell copies of the Software, and to permit persons to whom
+# the Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+# ADAM JACKSON BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+AUTOMAKE_OPTIONS = foreign
+SUBDIRS = src man
+
+if BUILD_LINUXDOC
+README: README.sgml
+ $(MAKE_TEXT) README.sgml && mv README.txt README
+endif
+
+EXTRA_DIST = CALLMAP TODO_NOTES README.sgml
diff --git a/README b/README
new file mode 100644
index 0000000..d16f23f
--- /dev/null
+++ b/README
@@ -0,0 +1,91 @@
+
+What works:
+- Supports 8bpp, 15/16bpp, 24bpp and 32bpp. Heavy testing on ViRGE DX.
+- There is some known instability in ViRGE GX2, please report problems.
+- Silken Mouse is enabled by default, use the generic server option of
+ -nosilk to disable it.
+
+XCONFIG options:
+
+The driver supports quite a few different XConfig options, which can
+be used to tune the driver and improve performance. Without any options,
+the driver will use conservative settings which should work on most
+hardware. Large improvements in performance are possible by selecting
+the proper options, which will probably work on most systems.
+
+Cursor:
+
+- "hwcursor" "off" behaves exactly like "swcursor". Default: "on"
+- "swcursor" will disable the HW Cursor. HW Cursor is used by default and
+ no option is needed to enable it.
+
+Display:
+- "ShadowFB" Use shadow framebuffer. Disables HW acceleration. Default: off.
+- "Rotate" " cw "|" ccw " Rotate the screen CW - clockwise or CCW - counter
+ clockwise. Disables HW Acceleration and HW Cursor, uses ShadowFB.
+ Default: no rotation.
+- "XVideo" Disable XVideo support by using the off option. This changes FIFO
+ settings which prevent screen noise for high-res modes. Default: on
+
+Video memory:
+
+- "slow_edodram" will switch the standard ViRGE to 2-cycle edo mode. Try this
+ if you encounter pixel corruption on the ViRGE. Using this option will
+ cause a large decrease in performance.
+- "fpm_vram" will switch the ViRGE/VX to fast page mode vram mode
+- "slow_dram " | " fast_dram" Change Trio 3D and 3D/2X memory options.
+ Default: Use BIOS defaults.
+- "early_ras_precharge", "late_ras_precharge" adjust memory parameters. One
+ of these will us the same settings as your video card defaults, and
+ using neither in the config file does the same.
+- "set_mclk" sets the memory clock, format is:
+ Option "set_mclk" "50000"
+ in the XF86Config file. Valid values are any
+ integer <= 100000, where 100000 == 100 MHz.
+- "set_refclk" sets the ref clock for ViRGE MX, format is:
+ Option "set_refclk" "50000"
+
+Acceleration and graphic engine:
+
+- "NoAccel" turns off all acceleration
+- "fifo_aggressive", "fifo_moderate" and "fifo_conservative" alter the settings
+ for the threshold at which the pixel FIFO takes over the internal
+ memory bus to refill itself. The smaller this threshold, the better
+ the acceleration performance of the card. You may try the fastest
+ setting ("aggressive") and move down if you encounter pixel corruption.
+ The optimal setting will probably depend on dot-clock and on color
+ depth. Note that specifying any of these options will also alter other
+ memory settings which should increase performance, so you should at
+ least use "fifo_conservative" (this uses the chip defaults).
+- Common XAA acceleration options to disable primitives for test purposes:
+ "XaaNoScreenToScreenCopy"
+ "XaaNoSolidFillRect"
+ "XaaNoColor8x8PatternFillRect"
+ "XaaNoImageWriteRect"
+ "XaaNoPixmapCache"
+
+PCI bus:
+- "pci_burst" will enable PCI burst mode. This should work on all but a
+ few "broken" PCI chipsets, and will increase performance. Option may
+ take a parameter "on", "off", "yes", etc...
+- "pci_retry" will allow the driver to rely on PCI Retry to program the
+ ViRGE registers. "pci_burst" must be enabled for this to work.
+ This will increase performance, especially for small fills/blits,
+ because the driver does not have to poll the ViRGE before sending it
+ commands to make sure it is ready. It should work on most
+ recent PCI chipsets.
+
+ViRGE MX LCD options:
+- "lcd_center"
+- "set_lcdclk" allows setting the clock for a ViRGE MX LCD display. Format is:
+ Option "set_lcdclk" "30000"
+ in the config file. Valid values are ?
+
+Debug:
+- "ShowCache" Enable or disable viewing offscreen cache memory. A
+ development debug option. Default: off.
+- "mx_cr3a_fix" Enable or disable a cr3a fix added for ViRGE MX.
+ Default: on.
+
+
+$XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/README,v 1.9 2000/06/14 21:57:54 dawes Exp $
diff --git a/README.sgml b/README.sgml
new file mode 100644
index 0000000..e47b8c4
--- /dev/null
+++ b/README.sgml
@@ -0,0 +1,61 @@
+<!DOCTYPE linuxdoc PUBLIC "-//Xorg//DTD linuxdoc//EN" [
+<!ENTITY % defs SYSTEM "defs.ent"> %defs;
+]>
+
+<article>
+<title> Information for S3 ViRGE Users
+<author>The XFree86 Project Inc.
+<date>19 Dec 2001
+
+<ident>
+</ident>
+
+<toc>
+
+<sect> Supported hardware
+<p>
+The s3virge driver in X11R&relvers; supports the S3 ViRGE, ViRGE DX, GX, GX2, MX, MX+, and VX chipsets. It also supports Trio3D and Trio3D/2x chips. A majority of testing is done on ViRGE DX chips, making them the most stable to date. This release has added support for doublescan modes on DX.
+
+This driver is moderately stable, however please use caution with any new install. Please report any problems to bugzilla.freedesktop.org, using the xorg component.
+
+<sect>Features:
+<p>
+
+<itemize>
+<item>Fully accelerated support for S3 ViRGE family video adapters
+<item>uses linear frame buffer
+<item>supports resolutions up to 2048x2048
+<item>supports color depths of 8, 15, 16 and 24
+<item>full use of video card memory for acceleration caching when visible framebuffer leaves extra memory
+<item>XVideo on DX, GX, GX2, MX, MX+ and Trio3D/2X at depth 16 and 24
+<item>Doublescan modes on DX, possibly others (untested)
+</itemize>
+
+<sect>Configuration:
+<p>
+
+The driver auto-detects RAM size, RAMDAC and ClockChip. Do not bother putting
+these in your "Device" section.
+
+<sect>Documentation:
+<p>
+
+The driver has several supported options which are documented in the s3virge man
+page. Please refer to it for additional details about configuration options.
+
+<sect>Support:
+<p>
+For support with X11R&relvers video drivers please refer to our web site at <url name="wiki.x.org" url="http://wiki.x.org">.
+
+<sect>Authors
+<p>
+
+<itemize>
+<item>Mark Vojkovich <email>mvojkovich@nvidia.com</email>
+<item>Sebastien Marineau
+<item>Harald Koenig <email>koenig@tat.physik.uni-tuebingen.de</email>
+<item>Matt Grossman <email>mattg@oz.net</email>
+<item>Kevin Brosius <email>cobra@compuserve.com</email>
+</itemize>
+
+</article>
diff --git a/TODO_NOTES b/TODO_NOTES
new file mode 100644
index 0000000..7d6a878
--- /dev/null
+++ b/TODO_NOTES
@@ -0,0 +1,326 @@
+S3 ViRGE 4.0 devel notes
+
+
+
+Status
+------
+1/26/2003
+Ver 1.8.6
+Pre-4.3.0 release. 320x240 doublescan support w/mouse adjust,
+power management printouts, DAC error printout fix, log XVideo status based
+on chipset, preliminary support for disabling XV when a mode doesn't
+support it.
+
+5/18/2002
+Ver 1.8.5
+320x240 mode support (doublescan).
+
+2/2/02
+Ver 1.8.4
+Make 320x240 mode work in depth 15 & 16.
+Testing, need to switch streams on/off based on dblscan_v flag and mode.
+Virge MX panel_on test (doesn't work.)
+
+1/10/02
+Ver 1.8.3
+DGA fix, buffer pointer used wrong value. Submitted for 4.2.0 (late).
+
+Ver 1.8.2
+DPMS testing (display DPMS status, disable MX LCD panel), DGA testing.
+
+11/11/01 KJB
+Ver 1.8.1
+ViRGE MX (& GX2) fix to CR63 for problems with modes < 1024x768 from
+max <sunmax@libero.it>. Submitted for 4.2.0.
+
+11/5/01 KJB
+Ver 1.8.0
+ViRGE MX & GX2 XVideo changes. Fix overlap/color keying on MX, fix
+and enable GX2 XVideo.
+Submitted for 4.2.0.
+
+11/4/01 KJB
+Ver 1.7.0
+Bump version for 4.2.0. Update man and README.
+
+11/3/01 KJB
+Ver 1.6.16
+Pre-4.2.0 patch. cr3a fix, virge mx xvideo support, xvideo disable option
+(helps with high res modes on dx and screen noise), remove accel solid
+fill rect for trio3d, bring over some trio3d and mx fixes from 4.0.3 test
+drivers. Includes VERBLEV bump to 5 to remove register dumps in log file.
+
+Ver 1.6.15
+Experimental - Scanline color expand - GX2
+
+9/21/01 KJB
+Ver 1.6.14
+ModeInit - cr3a for MX/GX2, don't clear reserved bit 0x40 (revert change).
+Back out previous cr3a patch for testing.
+
+9/18/01 KJB
+Ver 1.6.13
+Option "xvideo" added. Add patch provided by Sven Menke
+<Menke@SLAC.Stanford.EDU> for XV support on MX (slight changes to logic).
+
+Ver 1.6.12
+Adam J. Richter's cr3a fix (possibly temporary).
+
+5/30/01 KJB
+Ver 1.6.10
+Disable MaxHValue & MaxVValue setting.
+
+1/03/01 KJB
+Ver 1.6.0
+Revert ViRGE to pre-Xv changes. ViRGE DX still supports Xv, but changes
+added for Xv and ViRGE caused problems with normal display.
+
+11/27/00 KJB
+Ver 1.5.0
+Clean up, bump version for 4.0.2 submission.
+CR3A, bit 0x40 (reserved) cleared for MX/GX2. Update man page.
+
+11/24/00 KJB
+Disable CPU to screen color expansion on GX2, causes lockups on GX2 with
+'locate html' in an xterm. Add WaitCmd code to prevent accelerator and
+reg command path activity at the same time on GX2.
+XVideo fixes, left side clipping fixed for video windows extending off left
+side of screen. Add horizontal filtering modes for 1-2x and >3x scaling.
+
+11/7/00 KJB
+Ver 1.4.0
+Enable MX fixes, testing with accel BLT_BUG set is worse on GX2, so left
+it out. BLT_BUG wasn't being enabled on ViRGE & VX because of case usage,
+enabled now. Re-enable silken mouse for GX2. Add Render/fbPicture support.
+Fix a few compiler warnings.
+
+11/5/00 KJB
+Continued work on GX2, much stabler now, but I think there is a lockup case
+left if you enable pci_burst and pci_retry with accel. I still see screen
+flashes with vertical bars once in a while, and the log reports a GEReset.
+Added fbPicture (render) support, untested. XV code for GX2 is added,
+but not working yet.
+
+10/29/00 KJB
+Much work on GX2, now SWCursor locks up but HWCursor is stable, go figure.
+Loading Netscape a couple times with the mail window was enough to lock it
+up twice in a row. Server was locked but not a box (PCI) lock. Also,
+vertical barring still occurred a couple times, so HW cursor wasn't causing
+that. Try blt_bug flag again for lock up case. And attach to debug server
+and bt... Sleep now...
+
+10/21/00 KJB
+Ver 1.3.0
+Depth 16 Xv support added. Testing on ViRGE DX. 1280x1024x24 is noisy, so
+needs FIFO tuning.
+
+9/27/00 KJB
+Initial Xv support in depth 24.
+
+9/10/00 KJB
+Convert to FB. Add option "UseFB", default true. Added
+VerticalRetraceWait timeout back as default. #if0 out the line accel
+code in s3v_accel.c. The Subsequent...Bresenham line code causes a lockup
+when used with fb. We didn't have any hardware accel in there anyway...
+
+7/25/00 KJB
+Started Xv additions.
+
+6/26/00 KJB
+GX2 seems to have an accel bug. I see the entire screen go solid color or
+a wide stripe pattern for about 1 second. The S3VGEReset gets called twice,
+and then everything is okay. Unless SilkenMouse is enabled... That seems to
+get you a server lock instead. Short term is to disable SilkenMouse for GX2
+only. SilkenMouse isn't really the problem of course, it just happens that if
+we move the mouse during the 1 second engine lockup we appear more likely to
+never recover.
+
+6/23/00 KJB
+Ver 1.2.0 - Fix console corruption on GX2 caused by reserved bit use in CR3A.
+Fix GX2 noise on screen in hi-res depth 24 by increasing FIFO fill threshold.
+
+6/12/00 KJB
+Ver 1.1.0 - Add Init for SilkenMouse, add xf86SetBackingStore call, move
+int10Symbols[] to remove warnings.
+
+3/3/00 KJB
+Ver 1.0.0 - S3VProbeDDC code for X -configure option added, add timeout to
+WAITIDLE macro in s3v_macros.h, change ImageWriteFlags adding NO_GXCOPY.
+Start of GX2 fixes, use CR regs for FIFO settings. Update copyrights.
+
+2/11/00 KJB
+Ver 0.11.0 - Add cfb16/24BresS to module symbols to remove warnings.
+Fix viewport restore problem after EnterVT in 24 bpp.
+Clean up log output, removing register dumps from normal console log.
+
+6/26/99 KJB
+Make the memory settings for fifo_conservative the default, 'fifo_conservative'
+does nothing additional now. Patch includes DGA2 additions below, non-working.
+Expected to be included in 3.9Pu.
+
+Changes in 3.9Pt by others include additions for newer RAC support. Some reports
+say multi-head works now with ViRGE.
+
+6/17/99 KJB
+Ver 0.9.0 - Prelim DGA2 support modeled after MGA.
+
+5/28/99 KJB
+Ver 0.8.0 - Changes to 3.9Po - Cleaned up debug register printing function, minor
+changes to man page, remove S3V.sgml and add new s3virge.sgml in doc/sgml, also
+remove README.S3V from doc directory.
+
+
+4/5/99 KJB
+3.9Ph - Ver 0.7.0 - Virge man page added, HW Cursor fixed, rename chipsets removing
+slashes in the names.
+
+03/27/99 KJB
+Ver 0.6.0 - hwcursor additions, added s3v_hwcurs.c and Option "swcursor".
+Default is hwcursor, Option "swcursor" will disable it.
+
+Ver 0.5.0 - patch against 3.9Pf (seq 2615), fix depth 24 and Accel flags, sync pci_burst option to previous changes, remove s3v_comp.h and s3v_pio.c and merge as needed.
+
+03/21/99 KJB
+3.9Pf has Matt Grossman's Alpha changes.
+For next patch - remove s3v_pio.c and s3v_comp.h. Include the EnableMMIO and
+DisableMMIO functions from s3v_pio.c in s3v_driver.c.
+
+03/02/99 KJB
+3.9Pc - depth 24 doesn't work on my ViRGE DX. NoAccel doesn't start, accel does
+but has blocky noise.
+
+03/01/99 KJB
+Macro change done, VGAIN/VGAOUT for register access, INREG/OUTREG for s3v_accel.c.
+Added Mark Vojkovich's re-write of the accel code. It may only be clean for ViRGE DX
+at the moment. x11perf showed a couple artifacts in 'move window via parent'.
+In progress, attempt to call cfbScreenInit() functions after MapMem/EnterVT. Not
+working yet. Version stamped 0.4.0.
+
+02/22/99 KJB
+Macro change coming to add Mark's accel update. VGAOUT for old stuff and MEMOUT
+for new stuff? That way there's no confusion with the old INREG/OUTREG macros.
+Or maybe just stick with INREG/OUTREG for new stuff.
+
+01/30/99 KJB
+Version stamp 0.3.0. Changed Chipset flags to use PCI IDs exclusively, also use
+common/xf86PciInfo.h for PCI IDs rather than coding them in regs3v.h.
+
+11/28/98 KJB
+Bumped version stamp to 0.2, expect code in 3.9No. Cleaned up s3v.h and
+s3v_driver.c by removing unused definition & code sections. Added
+options set_mclk (from 3.3.2) and set_lcdclk (3.3.3 MX). Code support
+from 3.3.3 for ViRGE GX2 and MX+ is included.
+Disabled call to 32 bpp AccelInit to get -depth 24 -bpp 32 working again.
+
+11/27/98 KJB
+More 3.3.3 import.
+New registers saved, CR40,CR45,SR8,(for MX) SR29,SR45,SR55,SR56,SR57.
+Reviewed s3vdriver.h, rehs3v.h, newmmio.h, s3v_accel.c, s3v_driver.c.
+Added ViRGE MX, MX+ & GX2 support. Re-synced parts of mode save and init
+with 3.3.3 versions. Added timeout ability for WaitIdle() and friends.
+Added chipnames and numbers to Chipsets struct.
+
+11/26/98 KJB
+Import additions from 3.3.3, newmmio.h, regs3v.h,
+
+Trap fills disabled because they don't match cfb, pixmap cache & ImageWrite
+working, fixed depth 8 color loss on VT switches, INREG & OUTREG modified to
+use a single offset value instead of adding the base and offset together.
+
+11/18/98 KJB
+3.9Nn
+Acceleration working for Bitblt, ScreenToScreenCopy, Color 8x8 Rect fills,
+and Rect/Trap fills.
+Trap fills do not support transparency, so that needs to be exported to XAA.
+
+
+10/31/98 KJB
+Working depth 8, discolored dep 16 but runs, dep 24 screen goes black,
+C-A-Bkspc restores text console. At 3.9Nk tree level, module would not
+load in Loader server. why? Static server tested.
+
+10/29/98 KJB
+ModeInit() needs work, options are heavily #if'd to try and get 8bpp
+working.
+
+10/16/98 KJB
+General 4.0 architecture is setup. Presently at 3.9Nc level, if moved
+to a newer tree you will need to add the resource handling functions from
+Egbert (I haven't tackled that yet).
+
+At the moment the ScreenInit() function is coded to return FALSE. On my
+ViRGE DX card this version does not lock up, but it does destroy the
+video mode. Make sure you have an external terminal or network connection
+if you run it (or blindly do a restart from your main terminal). I make
+no guarantees that it won't hard lock other versions of ViRGE.
+
+I've left out the Alpha memory mapping, along with all option processing.
+Those will need to be done once the driver is minimally working.
+
+Note that everything in s3v_driver.c is MMIO only. There are a pair of
+PIO functions in s3v_pio.c, but that is the only place. See notes below
+about my ViRGE DX BIOS and why I needed to do this on my hardware.
+
+Other stuff...
+Some test stuff is assuming 8bpp, so 16 & 24 are broken.
+On my hardware, I am presently trying to get the Save/Restore sequence to
+recover the video mode. At the moment, when I run this driver, I get:
+ScreenInit() runs to completion.
+It returns FALSE, so the Server aborts.
+LeaveVT() is called, and runs to completion.
+The Server exits gracefully, but my monitor goes powersaver and the video
+mode is not recovered.
+
+
+
+TODO items
+----------
+1/30/03 General option "videoram" is ignored by the virge driver.
+ (Meelis Roos)
+3/24/02 Xv reported to not work as secondary in Xinerama multihead.
+ (xav on irc)
+3/24/02 DPMS doesn't fully disable the screen. Blue line across the
+ center in all modes. (xav on irc)
+3/25/02 Secondary reports primary BIOS during int10 detection. ie:
+
+(II) S3VIRGE(1): VESA BIOS detected
+(II) S3VIRGE(1): VESA VBE Version 2.0
+(II) S3VIRGE(1): VESA VBE Total Mem: 4194240 kB
+(II) S3VIRGE(1): VESA VBE OEM: ATI RAGE128
+(II) S3VIRGE(1): VESA VBE OEM Software Rev: 1.0
+(II) S3VIRGE(1): VESA VBE OEM Vendor: ATI Technologies Inc.
+(II) S3VIRGE(1): VESA VBE OEM Product: R128
+(II) S3VIRGE(1): VESA VBE OEM Product Rev: 01.00
+
+(xav on irc)
+
+
+Check CR65 usage, bit 2 set based on S3_EARLY_SC? In my manual bit 2 is
+enable MMIO to RAMDAC registers.
+
+Notes:
+----------
+
+/config/cf/xfree86.cf
+
+have to add s3v to XF86CardDrivers for imake to make the
+drivers/s3v Makefile.
+
+To remake makefiles, after editing Imakefile, go to dir above drivers/s3v
+and do a 'make Makefiles'.
+
+For debug, make CDEBUGFLAGS='-g -DDEBUG', adding -DMetroLink enables
+timeout for VerticalRetraceWait().
+
+
+
+S3 ViRGE DX stuff:
+
+Card seems to power up (or BIOS forces) with MMIO disabled. All flavors are
+disabled, because CR53 comes up as 0. This may preclude using this card
+as the second device in a multi-head situation although David D. says that
+the new config. management stuff may help here.
+
+
+
+$XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/TODO_NOTES,v 1.22 2003/02/04 02:20:49 dawes Exp $
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..904cd67
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+autoreconf -v --install || exit 1
+cd $ORIGDIR || exit $?
+
+$srcdir/configure --enable-maintainer-mode "$@"
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..24b656c
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,80 @@
+# Copyright 2005 Adam Jackson.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# on the rights to use, copy, modify, merge, publish, distribute, sub
+# license, and/or sell copies of the Software, and to permit persons to whom
+# the Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+# ADAM JACKSON BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Process this file with autoconf to produce a configure script
+
+AC_PREREQ(2.57)
+AC_INIT([xf86-video-s3virge],
+ 1.8.6.5,
+ [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
+ xf86-video-s3virge)
+
+AC_CONFIG_SRCDIR([Makefile.am])
+AM_CONFIG_HEADER([config.h])
+AC_CONFIG_AUX_DIR(.)
+
+AM_INIT_AUTOMAKE([dist-bzip2])
+
+AM_MAINTAINER_MODE
+
+# Checks for programs.
+AC_DISABLE_STATIC
+AC_PROG_LIBTOOL
+AC_PROG_CC
+
+AH_TOP([#include "xorg-server.h"])
+
+AC_ARG_WITH(xorg-module-dir,
+ AC_HELP_STRING([--with-xorg-module-dir=DIR],
+ [Default xorg module directory [[default=$libdir/xorg/modules]]]),
+ [moduledir="$withval"],
+ [moduledir="$libdir/xorg/modules"])
+
+# Checks for extensions
+XORG_DRIVER_CHECK_EXT(RANDR, randrproto)
+XORG_DRIVER_CHECK_EXT(RENDER, renderproto)
+XORG_DRIVER_CHECK_EXT(XV, videoproto)
+XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto)
+
+# Checks for pkg-config packages
+PKG_CHECK_MODULES(XORG, [xorg-server xproto fontsproto $REQUIRED_MODULES])
+sdkdir=$(pkg-config --variable=sdkdir xorg-server)
+
+# Checks for libraries.
+
+# Checks for header files.
+AC_HEADER_STDC
+
+AC_SUBST([XORG_CFLAGS])
+AC_SUBST([moduledir])
+
+DRIVER_NAME=s3virge
+AC_SUBST([DRIVER_NAME])
+
+XORG_MANPAGE_SECTIONS
+XORG_RELEASE_VERSION
+
+XORG_CHECK_LINUXDOC
+
+AC_OUTPUT([
+ Makefile
+ src/Makefile
+ man/Makefile
+])
diff --git a/man/.cvsignore b/man/.cvsignore
new file mode 100644
index 0000000..282522d
--- /dev/null
+++ b/man/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/man/CVS/Entries b/man/CVS/Entries
new file mode 100644
index 0000000..8ab1bdd
--- /dev/null
+++ b/man/CVS/Entries
@@ -0,0 +1,4 @@
+/.cvsignore/1.1/Mon Nov 21 10:49:17 2005//
+/Makefile.am/1.6/Tue Dec 6 22:48:37 2005//
+/s3virge.man/1.2/Fri Apr 23 19:43:44 2004//
+D
diff --git a/man/CVS/Repository b/man/CVS/Repository
new file mode 100644
index 0000000..38436f0
--- /dev/null
+++ b/man/CVS/Repository
@@ -0,0 +1 @@
+driver/xf86-video-s3virge/man
diff --git a/man/CVS/Root b/man/CVS/Root
new file mode 100644
index 0000000..725164d
--- /dev/null
+++ b/man/CVS/Root
@@ -0,0 +1 @@
+:pserver:anoncvs@cvs.freedesktop.org:/cvs/xorg
diff --git a/man/Makefile.am b/man/Makefile.am
new file mode 100644
index 0000000..8e2a8ce
--- /dev/null
+++ b/man/Makefile.am
@@ -0,0 +1,59 @@
+# $Id: Makefile.am,v 1.6 2005/12/06 22:48:37 kem Exp $
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+#
+# 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.
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the copyright holders shall
+# not be used in advertising or otherwise to promote the sale, use or
+# other dealings in this Software without prior written authorization
+# from the copyright holders.
+#
+
+drivermandir = $(DRIVER_MAN_DIR)
+
+driverman_PRE = @DRIVER_NAME@.man
+
+driverman_DATA = $(driverman_PRE:man=@DRIVER_MAN_SUFFIX@)
+
+EXTRA_DIST = @DRIVER_NAME@.man
+
+CLEANFILES = $(driverman_DATA)
+
+SED = sed
+
+# Strings to replace in man pages
+XORGRELSTRING = @PACKAGE_STRING@
+ XORGMANNAME = X Version 11
+
+MAN_SUBSTS = \
+ -e 's|__vendorversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \
+ -e 's|__xorgversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \
+ -e 's|__xservername__|Xorg|g' \
+ -e 's|__xconfigfile__|xorg.conf|g' \
+ -e 's|__projectroot__|$(prefix)|g' \
+ -e 's|__appmansuffix__|$(APP_MAN_SUFFIX)|g' \
+ -e 's|__drivermansuffix__|$(DRIVER_MAN_SUFFIX)|g' \
+ -e 's|__adminmansuffix__|$(ADMIN_MAN_SUFFIX)|g' \
+ -e 's|__miscmansuffix__|$(MISC_MAN_SUFFIX)|g' \
+ -e 's|__filemansuffix__|$(FILE_MAN_SUFFIX)|g'
+
+SUFFIXES = .$(DRIVER_MAN_SUFFIX) .man
+
+.man.$(DRIVER_MAN_SUFFIX):
+ sed $(MAN_SUBSTS) < $< > $@
diff --git a/man/s3virge.man b/man/s3virge.man
new file mode 100644
index 0000000..3232130
--- /dev/null
+++ b/man/s3virge.man
@@ -0,0 +1,244 @@
+.\" $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/s3virge.man,v 1.3 2001/11/21 22:43:00 dawes Exp $
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH s3virge __drivermansuffix__ __vendorversion__
+.SH NAME
+s3virge \- S3 ViRGE video driver
+.SH SYNOPSIS
+.B "Section \*qDevice\*q"
+.br
+.BI " Identifier \*q" devname \*q
+.br
+.B " Driver \*qs3virge\*q"
+.br
+\ \ ...
+.br
+\ \ [
+.B "Option"
+"optionname" ["optionvalue"]]
+.br
+.B EndSection
+.SH DESCRIPTION
+.B s3virge
+is an __xservername__ driver for S3 based video cards. The driver is fully
+accelerated, and provides support for the following framebuffer depths:
+8, 15, 16, and 24. All
+visual types are supported for depth 8, and TrueColor
+visuals are supported for the other depths. XVideo hardware up scaling
+is supported in depth 16 and 24 on the DX, GX, GX2, MX, MX+, and
+Trio3D/2X. Doublescan modes are supported and tested in depth 8
+and 16 on DX, but disable XVideo. Doublescan modes on other chipsets
+are untested.
+.SH SUPPORTED HARDWARE
+The
+.B s3virge
+driver supports PCI and AGP video cards based on the following S3 chips:
+.TP 12
+.B ViRGE
+86C325
+.TP 12
+.B ViRGE VX
+86C988
+.TP 12
+.B ViRGE DX
+86C375
+.TP 12
+.B ViRGE GX
+86C385
+.TP 12
+.B ViRGE GX2
+86C357
+.TP 12
+.B ViRGE MX
+86C260
+.TP 12
+.B ViRGE MX+
+86C280
+.TP 12
+.B Trio 3D
+86C365
+.TP 12
+.B Trio 3D/2X
+86C362, 86C368
+.SH CONFIGURATION DETAILS
+Please refer to __xconfigfile__(__filemansuffix__) for general configuration
+details. This section only covers configuration details specific to this
+driver. All options names are case and white space insensitive when
+parsed by the server, for example, "virge vx" and "VIRGEvx" are equivalent.
+.PP
+The driver auto-detects the chipset type, but the following
+.B ChipSet
+names may optionally be specified in the config file
+.B \*q"Device\*q"
+section, and will override the auto-detection:
+.PP
+.RS 4
+"virge", "86c325", "virge vx", "86c988", "virge dx", "86c375",
+"virge gx", "86c385", "virge gx2", "86c357", "virge mx", "86c260",
+"virge mx+", "86c280", "trio 3d", "86c365", "trio 3d/2x", "86c362",
+"86c368".
+.RE
+
+.PP
+The following Cursor
+.B Options
+are supported:
+.TP
+.BI "Option \*qHWCursor\*q [\*q" boolean \*q]
+Enable or disable the HW cursor. Default: on.
+.TP
+.BI "Option \*qSWCursor\*q [\*q" boolean \*q]
+Inverse of "HWCursor". Default: off.
+
+.PP
+The following display
+.B Options
+are supported:
+.TP
+.BI "Option \*qShadowFB\*q [\*q" boolean \*q]
+Use shadow framebuffer. Disables HW acceleration. Default: off.
+.TP
+.BR "Option \*qRotate\*q \*q" cw " | " ccw \*q
+Rotate the screen CW - clockwise or CCW - counter clockwise.
+Disables HW Acceleration and HW Cursor, uses ShadowFB.
+Default: no rotation.
+.TP
+.BR "Option \*qXVideo\*q [\*q" boolean \*q]
+Disable XVideo support by using the off option. This changes FIFO
+settings which prevent screen noise for high-res modes. Default: on
+
+.PP
+The following video memory
+.B Options
+are supported:
+.TP
+.BI "Option \*qslow_edodram\*q"
+Switch the standard ViRGE to 2-cycle edo mode. Try this
+if you encounter pixel corruption on the ViRGE. Using this option will
+cause a large decrease in performance. Default: off.
+.TP
+.BI "Option \*qfpm_vram\*q"
+Switch the ViRGE/VX to fast page mode vram mode. Default: off.
+.TP
+.BR "Option \*qslow_dram " | " fast_dram\*q"
+Change Trio 3D and 3D/2X memory options. Default: Use BIOS defaults.
+.TP
+.BR "Option \*qearly_ras_precharge " | " late_ras_precharge\*q"
+adjust memory parameters. One
+of these will us the same settings as your video card defaults, and
+using neither in the config file does the same. Default: none.
+.TP
+.BI "Option \*qset_mclk\*q \*q" integer \*q
+sets the memory clock, where
+.I integer
+is in kHz, and
+.I integer
+<= 100000. Default: probe the memory clock value,
+and use it at server start.
+.TP
+.BI "Option \*qset_refclk\*q \*q" integer \*q
+sets the ref clock for ViRGE MX, where
+.I integer
+is in kHz. Default: probe the memory clock value,
+and use it at server start.
+
+
+.PP
+The following acceleration and graphics engine
+.B Options
+are supported:
+.TP
+.B "Option \*qNoAccel\*q"
+Disable acceleration. Very useful for determining if the
+driver has problems with drawing and acceleration routines. This is the first
+option to try if your server runs but you see graphic corruption on the screen.
+Using it decreases performance, as it uses software emulation for drawing
+operations the video driver can accelerate with hardware.
+Default: acceleration is enabled.
+.TP
+.B "Option \*qUseFB\*q"
+There are two framebuffer rendering methods. fb and cfb. Both are
+available in the driver. fb is the newer and default method. To switch
+back to cfb use this option with no, off or other negative parameter.
+Default: on.
+.TP
+.BR "Option \*qfifo_aggressive " | " fifo_moderate " | " fifo_conservative\*q"
+alter the settings
+for the threshold at which the pixel FIFO takes over the internal
+memory bus to refill itself. The smaller this threshold, the better
+the acceleration performance of the card. You may try the fastest
+setting
+.RB ( "fifo_aggressive" )
+and move down if you encounter pixel corruption.
+The optimal setting will probably depend on dot-clock and on color
+depth. Note that specifying any of these options will also alter other
+memory settings which may increase performance, so trying
+.B "fifo_conservative"
+will in most cases be a slight benefit (this uses the chip defaults).
+If pixel corruption or transient streaking is observed during drawing
+operations then removing any fifo options is recommended. Default: none.
+
+.PP
+The following PCI bus
+.B Options
+are supported:
+.TP
+.BI "Option \*qpci_burst\*q [\*q" boolean \*q]
+will enable PCI burst mode. This should work on all but a
+few broken PCI chipsets, and will increase performance. Default: off.
+.TP
+.BI "Option \*qpci_retry\*q [\*q" boolean \*q]
+will allow the driver to rely on PCI Retry to program the
+ViRGE registers.
+.B "pci_burst"
+must be enabled for this to work.
+This will increase performance, especially for small fills/blits,
+because the driver does not have to poll the ViRGE before sending it
+commands to make sure it is ready. It should work on most
+recent PCI chipsets. Default: off.
+.PP
+The following ViRGE MX LCD
+.B Options
+are supported:
+.TP
+.BI "Option \*qlcd_center\*q"
+.TP
+.BI "Option \*qset_lcdclk\*q \*q" integer \*q
+allows setting the clock for a ViRGE MX LCD display.
+.I integer
+is in Hz. Default: use probed value.
+
+.PP
+The following additional
+.B Options
+are supported:
+.TP
+.BI "Option \*qShowCache\*q [\*q" boolean \*q]
+Enable or disable viewing offscreen cache memory. A
+development debug option. Default: off.
+.TP
+.BI "Option \*qmx_cr3a_fix\*q [\*q" boolean \*q]
+Enable or disable a cr3a fix added for ViRGE MX. Default: on.
+
+.SH SEE ALSO
+__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__)
+
+.SH KNOWN BUGS
+The VideoRam generic driver parameter is presently ignored by the
+s3virge driver. On PPC this is reported to cause problems for 2M
+cards, because they may autodetect as 4M.
+
+.SH SUPPORT
+For assistance with this driver, or __xservername__ in general, check the web
+site at http://www.x.org. If you find a problem with __xservername__ or have a
+question not answered in the FAQ please use our bug report form available on
+the web site. When reporting problems
+with the driver send as much detail as possible, including chipset type, a
+server output log, and operating system specifics.
+
+.SH AUTHORS
+Kevin Brosius,
+Matt Grossman,
+Harald Koenig,
+Sebastien Marineau,
+Mark Vojkovich.
diff --git a/src/.cvsignore b/src/.cvsignore
new file mode 100644
index 0000000..9730646
--- /dev/null
+++ b/src/.cvsignore
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
diff --git a/src/CVS/Entries b/src/CVS/Entries
new file mode 100644
index 0000000..44feb81
--- /dev/null
+++ b/src/CVS/Entries
@@ -0,0 +1,16 @@
+/.cvsignore/1.1/Mon Nov 21 10:49:17 2005//
+/Makefile.am/1.1/Tue Jul 26 18:47:44 2005//
+/newmmio.h/1.1.1.1/Fri Nov 14 16:48:55 2003//
+/regs3v.h/1.1.1.1/Fri Nov 14 16:48:55 2003//
+/s3v.h/1.4/Wed Feb 8 16:17:05 2006//
+/s3v_accel.c/1.4/Mon Jul 11 02:29:59 2005//
+/s3v_dac.c/1.2/Mon Jul 11 02:29:59 2005//
+/s3v_dga.c/1.2/Mon Jul 11 02:29:59 2005//
+/s3v_driver.c/1.11/Wed Feb 8 16:17:05 2006//
+/s3v_hwcurs.c/1.2/Mon Jul 11 02:29:59 2005//
+/s3v_i2c.c/1.2/Mon Jul 11 02:29:59 2005//
+/s3v_macros.h/1.1.1.1/Fri Nov 14 16:48:55 2003//
+/s3v_rop.h/1.2/Fri Apr 23 19:43:44 2004//
+/s3v_shadow.c/1.3/Mon Jul 11 02:29:59 2005//
+/s3v_xv.c/1.3/Mon Jul 11 02:29:59 2005//
+D
diff --git a/src/CVS/Repository b/src/CVS/Repository
new file mode 100644
index 0000000..6847d53
--- /dev/null
+++ b/src/CVS/Repository
@@ -0,0 +1 @@
+driver/xf86-video-s3virge/src
diff --git a/src/CVS/Root b/src/CVS/Root
new file mode 100644
index 0000000..725164d
--- /dev/null
+++ b/src/CVS/Root
@@ -0,0 +1 @@
+:pserver:anoncvs@cvs.freedesktop.org:/cvs/xorg
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..a14dbac
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,46 @@
+# Copyright 2005 Adam Jackson.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# on the rights to use, copy, modify, merge, publish, distribute, sub
+# license, and/or sell copies of the Software, and to permit persons to whom
+# the Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+# ADAM JACKSON BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+# this is obnoxious:
+# -module lets us name the module exactly how we want
+# -avoid-version prevents gratuitous .0.0.0 version numbers on the end
+# _ladir passes a dummy rpath to libtool so the thing will actually link
+# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
+AM_CFLAGS = @XORG_CFLAGS@
+s3virge_drv_la_LTLIBRARIES = s3virge_drv.la
+s3virge_drv_la_LDFLAGS = -module -avoid-version
+s3virge_drv_ladir = @moduledir@/drivers
+
+s3virge_drv_la_SOURCES = \
+ newmmio.h \
+ regs3v.h \
+ s3v_accel.c \
+ s3v_xaa.c \
+ s3v_exa.c \
+ s3v_dac.c \
+ s3v_dga.c \
+ s3v_driver.c \
+ s3v.h \
+ s3v_hwcurs.c \
+ s3v_i2c.c \
+ s3v_macros.h \
+ s3v_rop.h \
+ s3v_shadow.c \
+ s3v_xv.c
diff --git a/src/newmmio.h b/src/newmmio.h
new file mode 100644
index 0000000..59ba575
--- /dev/null
+++ b/src/newmmio.h
@@ -0,0 +1,619 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/newmmio.h,v 1.5 1999/03/21 07:35:15 dawes Exp $ */
+
+/*
+Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the XFree86 Project shall not
+be used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the XFree86 Project.
+*/
+
+/***************************************************************************
+ *
+ * typedefs and macros for MMIO mode, S3 ViRGE
+ *
+ * who when vers
+ * HK 9609126 0.0
+ *
+ * based on:
+ *
+ * typedefs and macros for old and new MMIO mode, Trio64V+ and 868/968
+ *
+ * who when vers
+ * BL 0300296 0.1
+ * SM 200497 0.2 Added Caching version of register macros.
+ * KJB 9/98 0.3 Added S3V_MMIO_REGSIZE
+ ***************************************************************************/
+
+#ifndef _NEWMMIO_H
+#define _NEWMMIO_H
+
+/* base for S3_OUTW macro */
+#define S3_NEWMMIO_REGBASE 0x1000000 /* 16MB */
+#define S3_NEWMMIO_REGSIZE 0x10000 /* 64KB */
+#define S3V_MMIO_REGSIZE 0x8000 /* 32KB */
+
+
+/* #include <Xmd.h> */
+
+
+#define int16 CARD16
+#define int32 CARD32
+
+#define S3_NEWMMIO_VGABASE (S3_NEWMMIO_REGBASE + 0x8000)
+
+#if 0
+typedef struct { int16 vendor_ID; int16 device_ID; } pci_id;
+typedef struct { int16 cmd; int16 devsel; } cmd_devsel;
+
+typedef struct {
+ pci_id pci_ident;
+ cmd_devsel cmd_device_sel;
+ int32 class_code;
+ char dummy_0c;
+ char latnecy_timer;
+ int16 dummy_0e;
+ int32 base0;
+ char dummy_14[0x20-sizeof(int32)];
+ int32 bios_base;
+ int32 dummy_34;
+ int32 dummy_38;
+ char int_line;
+ char int_pin;
+ int16 latency_grant;
+} pci_conf_regs;
+
+
+typedef struct {
+ int32 prim_stream_cntl;
+ int32 col_chroma_key_cntl;
+ char dummy1[0x8190 - 0x8184-sizeof(int32)];
+ int32 second_stream_cntl;
+ int32 chroma_key_upper_bound;
+ int32 second_stream_stretch;
+ char dummy2[0x81a0 - 0x8198-sizeof(int32)];
+ int32 blend_cntl;
+ char dummy3[0x81c0 - 0x81a0-sizeof(int32)];
+ int32 prim_fbaddr0;
+ int32 prim_fbaddr1;
+ int32 prim_stream_stride;
+ int32 double_buffer;
+ int32 second_fbaddr0;
+ int32 second_fbaddr1;
+ int32 second_stream_stride;
+ int32 opaq_overlay_cntl;
+ int32 k1;
+ int32 k2;
+ int32 dda_vert;
+ int32 streams_fifo;
+ int32 prim_start_coord;
+ int32 prim_window_size;
+ int32 second_start_coord;
+ int32 second_window_size;
+} streams_proc_regs;
+
+typedef struct {
+ int32 fifo_control;
+ int32 miu_control;
+ int32 streams_timeout;
+ int32 misc_timeout;
+ int32 dummy_8210, dummy_8214, dummy_8218, dummy_821c;
+ int32 dma_read_base_addr;
+ int32 dma_read_stride_width;
+} memport_proc_regs;
+
+typedef struct {
+ int32 subsystem_csr;
+ int32 dummy_8508;
+ int32 adv_func_cntl;
+} subsys_regs;
+
+typedef struct {
+ int32 start_sysmem_addr;
+ int32 transfer_length;
+ int32 transfer_enable;
+} video_dma_regs;
+
+typedef struct {
+ int32 base_addr;
+ int32 write_pointer;
+ int32 read_pointer;
+ int32 dma_enable;
+} cmd_dma_regs;
+
+typedef struct {
+ video_dma_regs video;
+ int32 dummy_858c;
+ cmd_dma_regs cmd;
+} dma_regs;
+
+typedef struct {
+ int32 lpb_mode;
+ int32 lpb_fifostat;
+ int32 lpb_intflags;
+ int32 lpb_fb0addr;
+ int32 lpb_fb1addr;
+ int32 lpb_direct_addr;
+ int32 lpb_direct_data;
+ int32 lpb_gpio;
+ int32 lpb_serial_port;
+ int32 lpb_input_winsize;
+ int32 lpb_data_offsets;
+ int32 lpb_hor_decimctl;
+ int32 lpb_vert_decimctl;
+ int32 lpb_line_stride;
+ int32 lpb_output_fifo;
+} lpbus_regs;
+
+
+typedef struct { char atr_cntl_ind; char attr_cntl_dat; char misc_out;
+ char viseo_enable; } v3c0;
+typedef struct { char seq_index; char seq_data; char dac_mask;
+ char dac_rd_index; } v3c4;
+typedef struct { char dac_wr_index; char dac_data; char feature_cntl;
+ char filler; } v3c8;
+typedef struct v3cc { char misc_out; char filler; char graph_cntl_index;
+ char graph_cntl_data; } v3cc;
+typedef struct {
+ v3c0 v3c0_regs;
+ v3c4 v3c4_regs;
+ v3c8 v3c8_regs;
+ v3cc v3cc_regs;
+} vga_3c_regs;
+
+typedef struct { char crt_index; char crt_data; int16 filler; } v3d4;
+typedef struct { int16 filler1; char feature_cntl; char filler2;} v3d8;
+
+typedef struct {
+ int32 filler;
+ v3d4 v3d4_regs;
+ v3d8 v3d8_regs;
+} vga_3bd_regs ;
+
+
+
+typedef struct {
+ char filler1[-(0xa000-0xa100)];
+ int32 patt[-(0xa100-0xa1bc) / sizeof(int32) + 1];
+} colpatt_regs;
+
+typedef struct {
+ char filler1[-(0xa400-0xa4d4)];
+ int32 src_base;
+ int32 dest_base;
+ int32 clip_l_r;
+ int32 clip_t_b;
+ int32 dest_src_str;
+ int32 mono_pat0;
+ int32 mono_pat1;
+ int32 pat_bg_clr;
+ int32 pat_fg_clr;
+ int32 src_bg_clr;
+ int32 src_fg_clr;
+ int32 cmd_set;
+ int32 rwidth_height;
+ int32 rsrc_xy;
+ int32 rdest_xy;
+} bltfill_regs;
+
+typedef struct {
+ char filler1[-(0xa800-0xa8d4)];
+ int32 src_base;
+ int32 dest_base;
+ int32 clip_l_r;
+ int32 clip_t_b;
+ int32 dest_src_str;
+ int32 dummy1;
+ int32 dummy2;
+ int32 dummy3;
+ int32 pat_fg_clr;
+ int32 dummy4;
+ int32 dummy5;
+ int32 cmd_set;
+ char filler2[-(0xa904-0xa96c)];
+ int32 lxend0_end1;
+ int32 ldx;
+ int32 lxstart;
+ int32 lystart;
+ int32 lycnt;
+} line_regs;
+
+typedef struct {
+ char filler1[-(0xac00-0xacd4)];
+ int32 src_base;
+ int32 dest_base;
+ int32 clip_l_r;
+ int32 clip_t_b;
+ int32 dest_src_str;
+ int32 mono_pat0;
+ int32 mono_pat1;
+ int32 pat_bg_clr;
+ int32 pat_fg_clr;
+ int32 dummy1;
+ int32 dummy2;
+ int32 cmd_set;
+ char filler2[-(0xad04-0xad68)];
+ int32 prdx;
+ int32 prxstart;
+ int32 pldx;
+ int32 plxstart;
+ int32 pystart;
+ int32 pycnt;
+} polyfill_regs;
+
+typedef struct {
+ char filler1[-(0xb000-0xb0d4)];
+ int32 z_base;
+ int32 dest_base;
+ int32 clip_l_r;
+ int32 clip_t_b;
+ int32 dest_src_str;
+ int32 z_stride;
+ int32 dummy1;
+ int32 dummy2;
+ int32 fog_clr;
+ int32 dummy3;
+ int32 dummy4;
+ int32 cmd_set;
+ char filler2[-(0xb104-0xb144)];
+ int32 dgdy_dbdy;
+ int32 dady_drdy;
+ int32 gs_bs;
+ int32 as_rs;
+ int32 dummy5;
+ int32 dz;
+ int32 zstart;
+ int32 dummy6;
+ int32 dummy7;
+ int32 dummy8;
+ int32 xend0_end1;
+ int32 dx;
+ int32 xstart;
+ int32 ystart;
+ int32 ycnt;
+} line3d_regs;
+
+typedef struct {
+ char filler1[-(0xb400-0xb4d4)];
+ int32 z_base;
+ int32 dest_base;
+ int32 clip_l_r;
+ int32 clip_t_b;
+ int32 dest_src_str;
+ int32 z_stride;
+ int32 tex_base;
+ int32 tex_bdr_clr;
+ int32 fog_clr;
+ int32 color0;
+ int32 color1;
+ int32 cmd_set;
+ int32 bv;
+ int32 bu;
+ int32 dwdx;
+ int32 dwdy;
+ int32 ws;
+ int32 dddx;
+ int32 dvdx;
+ int32 dudx;
+ int32 dddy;
+ int32 dvdy;
+ int32 dudy;
+ int32 ds;
+ int32 vs;
+ int32 us;
+ int32 dgdx_dbdx;
+ int32 dadx_drdx;
+ int32 dgdy_dbdy;
+ int32 dady_drdy;
+ int32 gs_bs;
+ int32 as_rs;
+ int32 dzdx;
+ int32 dzdy;
+ int32 zs;
+ int32 dxdy12;
+ int32 xend12;
+ int32 dxdy01;
+ int32 xend01;
+ int32 dxdy02;
+ int32 xstart02;
+ int32 ystart;
+ int32 y01_y12;
+} triangle3d_regs;
+
+
+typedef struct {
+ int32 img[0x8000/4];
+ union { pci_conf_regs regs;
+ char dummy[-(0x8000 - 0x8180)];
+ } pci_regs;
+ union { streams_proc_regs regs;
+ char dummy[-(0x8180 - 0x8200)];
+ } streams_regs;
+ union { memport_proc_regs regs;
+ char dummy[-(0x8200 - 0x83b0)];
+ } memport_regs;
+ union { vga_3bd_regs regs;
+ char dummy[-(0x83b0 - 0x83c0)];
+ } v3b_regs;
+ union { vga_3c_regs regs;
+ char dummy[-(0x83c0 - 0x83d0)];
+ } v3c_regs;
+ union { vga_3bd_regs regs;
+ char dummy[-(0x83d0 - 0x8504)];
+ } v3d_regs;
+ union { subsys_regs regs;
+ char dummy[-(0x8504 - 0x8580)];
+ } subsys_regs;
+ union { dma_regs regs;
+ char dummy[-(0x8580 - 0xa000)];
+ } dma_regs;
+ union { colpatt_regs regs;
+ char dummy[-(0xa000 - 0xa400)];
+ } colpatt_regs;
+ union { bltfill_regs regs;
+ char dummy[-(0xa400 - 0xa800)];
+ } bltfill_regs;
+ union { line_regs regs;
+ char dummy[-(0xa800 - 0xac00)];
+ } line_regs;
+ union { polyfill_regs regs;
+ char dummy[-(0xac00 - 0xb000)];
+ } polyfill_regs;
+ union { line3d_regs regs;
+ char dummy[-(0xb000 - 0xb400)];
+ } line3d_regs;
+ union { triangle3d_regs regs;
+ char dummy[-(0xb400 - 0xff00)];
+ } triangle3d_regs;
+ union { lpbus_regs regs;
+ char dummy[-(0xff00 - 0xff5c)];
+ } lbp_regs;
+} mm_virge_regs ;
+
+
+
+#define mmtr volatile mm_virge_regs *
+
+#define SET_WRT_MASK(msk) /* */
+#define SET_RD_MASK(msk) /* */
+#define SET_FRGD_COLOR(col) /* */
+#define SET_BKGD_COLOR(col) /* */
+#define SET_FRGD_MIX(fmix) /* */
+#define SET_BKGD_MIX(bmix) /* */
+#define SET_PIX_CNTL(val) /* */
+#define SET_MIN_AXIS_PCNT(min) /* */
+#define SET_MAJ_AXIS_PCNT(maj) /* */
+#define SET_CURPT(c_x, c_y) /* */
+#define SET_CUR_X(c_x) /* */
+#define SET_CUR_Y(c_y) /* */
+#define SET_DESTSTP(x,y) /* */
+#define SET_AXIS_PCNT(maj, min) /* */
+#define SET_CMD(c_d) /* */
+#define SET_ERR_TERM(e) /* */
+#define SET_SCISSORS(x1,y1,x2,y2) /* */
+#define SET_SCISSORS_RB(x,y) /* */
+#define SET_MULT_MISC(val) /* */
+
+#define SET_PIX_TRANS_W(val) /* */
+#define SET_PIX_TRANS_L(val) /* */
+#define SET_MIX(fmix,bmix) /* */
+
+#endif /* 0 */
+
+/*
+ * reads from SUBSYS_STAT
+ */
+#define IN_SUBSYS_STAT() (INREG(SUBSYS_STAT_REG))
+#define SET_SUBSYS_CRTL(val) do { write_mem_barrier();\
+OUTREG((val), SUBSYS_STAT_REG);\
+write_mem_barrier(); } while (0)
+
+
+#if 0
+#define SET_DAC_W_INDEX(index) OUTREG8(DAC_W_INDEX, index)
+#define SET_DAC_DATA(val) OUTREG8(DAC_DATA,val)
+#endif
+
+#if 0
+
+#define IMG_TRANS (((mmtr)s3vMmioMem)->img)
+#define SET_PIXTRANS(a,v) IMG_TRANS[a] = (v)
+#define COLOR_PATTERN (((mmtr)s3vMmioMem)->colpatt_regs.regs)
+
+#define CMD_DMA_BASE(val) (((mmtr)s3vMmioMem)->dma_regs.regs.cmd.base_addr) = (val)
+#define CMD_DMA_WRITEP(val) (((mmtr)s3vMmioMem)->dma_regs.regs.cmd.write_pointer) = (val)
+#define CMD_DMA_READP(val) (((mmtr)s3vMmioMem)->dma_regs.regs.cmd.read_pointer) = (val)
+#define CMD_DMA_ENABLE(val) (((mmtr)s3vMmioMem)->dma_regs.regs.cmd.dma_enable) = (val)
+
+#define SETB_SRC_BASE(val) ((mmtr)s3vMmioMem)->bltfill_regs.regs.src_base = (val)
+#define SETB_DEST_BASE(val) ((mmtr)s3vMmioMem)->bltfill_regs.regs.dest_base = (val)
+#define SETB_CLIP_L_R(l,r) ((mmtr)s3vMmioMem)->bltfill_regs.regs.clip_l_r = ((l)<<16 | (r))
+#define SETB_CLIP_T_B(t,b) ((mmtr)s3vMmioMem)->bltfill_regs.regs.clip_t_b = ((t)<<16 | (b))
+/* #define SETB_DEST_SRC_STR(d,s) ((mmtr)s3vMmioMem)->bltfill_regs.regs.dest_src_str = ((d)<<16 | (s)) */
+
+#define SETB_DEST_SRC_STR(d, s) (OUTREG(DEST_SRC_STR, ((d) << 16 | (s))))
+
+#define SETB_MONO_PAT0(val) ((mmtr)s3vMmioMem)->bltfill_regs.regs.mono_pat0 = (val)
+#define SETB_MONO_PAT1(val) ((mmtr)s3vMmioMem)->bltfill_regs.regs.mono_pat1 = (val)
+#define SETB_PAT_BG_CLR(val) ((mmtr)s3vMmioMem)->bltfill_regs.regs.pat_bg_clr = (val)
+#define SETB_PAT_FG_CLR(val) ((mmtr)s3vMmioMem)->bltfill_regs.regs.pat_fg_clr = (val)
+#define SETB_SRC_BG_CLR(val) ((mmtr)s3vMmioMem)->bltfill_regs.regs.src_bg_clr = (val)
+#define SETB_SRC_FG_CLR(val) ((mmtr)s3vMmioMem)->bltfill_regs.regs.src_fg_clr = (val)
+#define SETB_CMD_SET(val) do { write_mem_barrier(); ((mmtr)s3vMmioMem)->bltfill_regs.regs.cmd_set = (val); write_mem_barrier(); } while (0)
+#define SETB_RWIDTH_HEIGHT(w,h) ((mmtr)s3vMmioMem)->bltfill_regs.regs.rwidth_height = ((w)<<16 | (h))
+#define SETB_RSRC_XY(x,y) ((mmtr)s3vMmioMem)->bltfill_regs.regs.rsrc_xy = ((x)<<16 | (y))
+#define SETB_RDEST_XY(x,y) do { write_mem_barrier(); ((mmtr)s3vMmioMem)->bltfill_regs.regs.rdest_xy = ((x)<<16 | (y)); write_mem_barrier(); } while (0)
+
+/* Caching version of the same MACROs */
+
+#define CACHE_SETB_CLIP_L_R(l,r) do { unsigned int clip = ((l)<<16 | (r)); if (s3vCached_CLIP_LR != clip) { ((mmtr)s3vMmioMem)->bltfill_regs.regs.clip_l_r = clip; s3vCached_CLIP_LR = clip; s3vCacheMiss++;} else s3vCacheHit++;} while(0)
+#define CACHE_SETB_CLIP_T_B(t,b) do { unsigned int clip = ((t)<<16 | (b)); if (s3vCached_CLIP_TB != clip) { ((mmtr)s3vMmioMem)->bltfill_regs.regs.clip_t_b = clip; s3vCached_CLIP_TB = clip; s3vCacheMiss++;} else s3vCacheHit++;} while(0)
+#define CACHE_SETB_RSRC_XY(x,y) do { unsigned int src = ((x)<<16 | (y)); if (s3vCached_RSRC_XY != src) { ((mmtr)s3vMmioMem)->bltfill_regs.regs.rsrc_xy = src; s3vCached_RSRC_XY = src; s3vCacheMiss++;} else s3vCacheHit++;} while(0)
+#define CACHE_SETB_RWIDTH_HEIGHT(w,h) do { unsigned int rwh = ((w)<<16 | (h)); if (s3vCached_RWIDTH_HEIGHT != rwh) { ((mmtr)s3vMmioMem)->bltfill_regs.regs.rwidth_height = rwh; s3vCached_RWIDTH_HEIGHT = rwh; s3vCacheMiss++;} else s3vCacheHit++;} while(0)
+#define CACHE_SETB_MONO_PAT0(val) do { \
+ if (s3vCached_MONO_PATTERN0 != (val)) { \
+ ((mmtr)s3vMmioMem)->bltfill_regs.regs.mono_pat0 = (val); \
+ s3vCached_MONO_PATTERN0 = (val); \
+ s3vCacheMiss++; \
+ } else s3vCacheHit++; \
+} while(0)
+#define CACHE_SETB_MONO_PAT1(val) do { \
+ if (s3vCached_MONO_PATTERN1 != (val)) { \
+ ((mmtr)s3vMmioMem)->bltfill_regs.regs.mono_pat1 = (val); \
+ s3vCached_MONO_PATTERN1 = (val); \
+ s3vCacheMiss++; \
+ } else s3vCacheHit++;\
+} while(0)
+#define CACHE_SETB_PAT_FG_CLR(val) do { \
+ if (s3vCached_PAT_FGCLR != (val)) { \
+ ((mmtr)s3vMmioMem)->bltfill_regs.regs.pat_fg_clr = (val); \
+ s3vCached_PAT_FGCLR = (val); \
+ s3vCacheMiss++; \
+ } else s3vCacheHit++; \
+} while(0)
+#define CACHE_SETB_PAT_BG_CLR(val) do { \
+ if (s3vCached_PAT_BGCLR != (val)) { \
+ ((mmtr)s3vMmioMem)->bltfill_regs.regs.pat_bg_clr = (val); \
+ s3vCached_PAT_BGCLR = (val); \
+ s3vCacheMiss++; \
+ } else s3vCacheHit++; \
+} while(0)
+#define CACHE_SETB_CMD_SET(val) do { \
+ if (s3vCached_CMD_SET != (val)) { \
+ write_mem_barrier(); \
+ ((mmtr)s3vMmioMem)->bltfill_regs.regs.cmd_set = (val); \
+ s3vCached_CMD_SET = (val); \
+ s3vCacheMiss++; \
+ write_mem_barrier(); \
+ } else s3vCacheHit++; \
+} while(0)
+#define SETL_SRC_BASE(val) ((mmtr)s3vMmioMem)->line_regs.regs.src_base = (val)
+#define SETL_DEST_BASE(val) ((mmtr)s3vMmioMem)->line_regs.regs.dest_base = (val)
+#define SETL_CLIP_L_R(l,r) ((mmtr)s3vMmioMem)->line_regs.regs.clip_l_r = ((l)<<16 | (r))
+#define SETL_CLIP_T_B(t,b) ((mmtr)s3vMmioMem)->line_regs.regs.clip_t_b = ((t)<<16 | (b))
+#define SETL_DEST_SRC_STR(d,s) ((mmtr)s3vMmioMem)->line_regs.regs.dest_src_str = ((d)<<16 | (s))
+#define SETL_PAT_FG_CLR(val) ((mmtr)s3vMmioMem)->line_regs.regs.pat_fg_clr = (val)
+#define SETL_CMD_SET(val) do { write_mem_barrier(); ((mmtr)s3vMmioMem)->line_regs.regs.cmd_set = (val); write_mem_barrier(); } while (0)
+#define SETL_LXEND0_END1(e0,e1) ((mmtr)s3vMmioMem)->line_regs.regs.lxend0_end1 = ((e0)<<16 | (e1))
+#define SETL_LDX(val) ((mmtr)s3vMmioMem)->line_regs.regs.ldx = (val)
+#define SETL_LXSTART(val) ((mmtr)s3vMmioMem)->line_regs.regs.lxstart = (val)
+#define SETL_LYSTART(val) ((mmtr)s3vMmioMem)->line_regs.regs.lystart = (val)
+#define SETL_LYCNT(val) do { write_mem_barrier(); ((mmtr)s3vMmioMem)->line_regs.regs.lycnt = (val); write_mem_barrier(); } while (0)
+
+/* Cache version */
+#define CACHE_SETL_CMD_SET(val) do { if (s3vCached_CMD_SET != val) { write_mem_barrier(); ((mmtr)s3vMmioMem)->line_regs.regs.cmd_set = val; s3vCached_CMD_SET = val; s3vCacheMiss++; write_mem_barrier(); } else s3vCacheHit++;} while(0)
+
+
+
+#define SETP_SRC_BASE(val) ((mmtr)s3vMmioMem)->polyfill_regs.regs.src_base = (val)
+#define SETP_DEST_BASE(val) ((mmtr)s3vMmioMem)->polyfill_regs.regs.dest_base = (val)
+#define SETP_CLIP_L_R(l,r) ((mmtr)s3vMmioMem)->polyfill_regs.regs.clip_l_r = ((l)<<16 | (r))
+#define SETP_CLIP_T_B(t,b) ((mmtr)s3vMmioMem)->polyfill_regs.regs.clip_t_b = ((t)<<16 | (b))
+#define SETP_DEST_SRC_STR(d,s) ((mmtr)s3vMmioMem)->polyfill_regs.regs.dest_src_str = ((d)<<16 | (s))
+#define SETP_MONO_PAT0(val) ((mmtr)s3vMmioMem)->polyfill_regs.regs.mono_pat0 = (val)
+#define SETP_MONO_PAT1(val) ((mmtr)s3vMmioMem)->polyfill_regs.regs.mono_pat1 = (val)
+#define SETP_PAT_BG_CLR(val) ((mmtr)s3vMmioMem)->polyfill_regs.regs.pat_bg_clr = (val)
+#define SETP_PAT_FG_CLR(val) ((mmtr)s3vMmioMem)->polyfill_regs.regs.pat_fg_clr = (val)
+#define SETP_CMD_SET(val) do { write_mem_barrier(); ((mmtr)s3vMmioMem)->polyfill_regs.regs.cmd_set = (val); write_mem_barrier(); } while (0)
+#define SETP_RWIDTH_HEIGHT(w,h) ((mmtr)s3vMmioMem)->polyfill_regs.regs.rwidth_height = ((w)<<16 | (h))
+#define SETP_PRDX(val) ((mmtr)s3vMmioMem)->polyfill_regs.regs.prdx = (val)
+#define SETP_PRXSTART(val) ((mmtr)s3vMmioMem)->polyfill_regs.regs.prxstart = (val)
+#define SETP_PLDX(val) ((mmtr)s3vMmioMem)->polyfill_regs.regs.pldx = (val)
+#define SETP_PLXSTART(val) ((mmtr)s3vMmioMem)->polyfill_regs.regs.plxstart = (val)
+#define SETP_PYSTART(val) ((mmtr)s3vMmioMem)->polyfill_regs.regs.pystart = (val)
+#define SETP_PYCNT(val) do { write_mem_barrier(); ((mmtr)s3vMmioMem)->polyfill_regs.regs.pycnt = (val); write_mem_barrier(); } while (0)
+
+/* Cache version */
+#define CACHE_SETP_CMD_SET(val) do { if (s3vCached_CMD_SET != val) { write_mem_barrier(); ((mmtr)s3vMmioMem)->polyfill_regs.regs.cmd_set = val; s3vCached_CMD_SET = val; s3vCacheMiss++; write_mem_barrier(); } else s3vCacheHit++;} while(0)
+
+
+#define SETL3_Z_BASE(val) ((mmtr)s3vMmioMem)->line3d_regs.regs.z_base = (val)
+#define SETL3_DEST_BASE(val) ((mmtr)s3vMmioMem)->line3d_regs.regs.dest_base = (val)
+#define SETL3_CLIP_L_R(l,r) ((mmtr)s3vMmioMem)->line3d_regs.regs.clip_l_r = ((l)<<16 | (r))
+#define SETL3_CLIP_T_B(t,b) ((mmtr)s3vMmioMem)->line3d_regs.regs.clip_t_b = ((t)<<16 | (b))
+#define SETL3_DEST_SRC_STR(d,s) ((mmtr)s3vMmioMem)->line3d_regs.regs.dest_src_str = ((d)<<16 | (s))
+#define SETL3_Z_STRIDE(val) ((mmtr)s3vMmioMem)->line3d_regs.regs.z_stride = (val)
+#define SETL3_FOG_CLR(val) ((mmtr)s3vMmioMem)->line3d_regs.regs.fog_clr = (val)
+#define SETL3_CMD_SET(val) do { write_mem_barrier(); ((mmtr)s3vMmioMem)->line3d_regs.regs.cmd_set = (val); write_mem_barrier(); } while (0)
+#define SETL3_DGDY_DBDY(dg,db) ((mmtr)s3vMmioMem)->line3d_regs.regs.dgdy_dbdy = ((dg)<<16 | (db))
+#define SETL3_DADY_DRDY(da,dr) ((mmtr)s3vMmioMem)->line3d_regs.regs.dady_drdy = ((da)<<16 | (dr))
+#define SETL3_GS_BS(gs,bs) ((mmtr)s3vMmioMem)->line3d_regs.regs.gs_bs = ((gs)<<16 | (bs))
+#define SETL3_AS_RS(as,rs) ((mmtr)s3vMmioMem)->line3d_regs.regs.as_rs = ((as)<<16 | (rs))
+#define SETL3_DZ(val) ((mmtr)s3vMmioMem)->line3d_regs.regs.dz = (val)
+#define SETL3_ZSTART(val) ((mmtr)s3vMmioMem)->line3d_regs.regs.zstart = (val)
+#define SETL3_XEND0_END1(e0,e1) ((mmtr)s3vMmioMem)->line3d_regs.regs.xend0_end1 = ((e0)<<16 | (e1))
+#define SETL3_DX(val) ((mmtr)s3vMmioMem)->line3d_regs.regs.dx = (val)
+#define SETL3_XSTART(val) ((mmtr)s3vMmioMem)->line3d_regs.regs.xstart = (val)
+#define SETL3_YSTART(val) ((mmtr)s3vMmioMem)->line3d_regs.regs.ystart = (val)
+#define SETL3_YCNT(val) do { write_mem_barrier(); ((mmtr)s3vMmioMem)->line3d_regs.regs.ycnt = (val); write_mem_barrier(); } while (0)
+
+
+
+#define SETT3_Z_BASE(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.z_base = (val)
+#define SETT3_DEST_BASE(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.dest_base = (val)
+#define SETT3_CLIP_L_R(l,r) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.clip_l_r = ((l)<<16 | (r))
+#define SETT3_CLIP_T_B(t,b) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.clip_t_b = ((t)<<16 | (b))
+#define SETT3_DEST_SRC_STR(d,s) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.dest_src_str = ((d)<<16 | (s))
+#define SETT3_Z_STRIDE(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.z_stride = (val)
+#define SETT3_TEX_BASE(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.tex_base = (val)
+#define SETT3_TEX_BDR_CLR(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.tex_bdr_clr = (val)
+#define SETT3_FOG_CLR(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.fog_clr = (val)
+#define SETT3_COLOR0(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.color0 = (val)
+#define SETT3_COLOR1(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.color1 = (val)
+#define SETT3_CMD_SET(val) do { write_mem_barrier(); ((mmtr)s3vMmioMem)->triangle3d_regs.regs.cmd_set = (val); write_mem_barrier(); } while (0)
+#define SETT3_BV(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.bv = (val)
+#define SETT3_BU(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.bu = (val)
+#define SETT3_DWDX(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.dwdx = (val)
+#define SETT3_DWDY(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.dwdy = (val)
+#define SETT3_WS(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.ws = (val)
+#define SETT3_DDDX(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.dddx = (val)
+#define SETT3_DVDX(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.dvdx = (val)
+#define SETT3_DUDX(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.dudx = (val)
+#define SETT3_DDDY(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.dddy = (val)
+#define SETT3_DVDY(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.dvdy = (val)
+#define SETT3_DUDY(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.dudy = (val)
+#define SETT3_DS(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.ds = (val)
+#define SETT3_VS(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.vs = (val)
+#define SETT3_US(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.us = (val)
+#define SETT3_DGDX_DBDX(gx,bx) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.dgdx_dbdx = ((gx)<<16 | (bx))
+#define SETT3_DADX_DRDX(ax,rx) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.dadx_drdx = ((ax)<<16 | (rx))
+#define SETT3_DGDY_DBDY(gy,by) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.dgdy_dbdy = ((gy)<<16 | (by))
+#define SETT3_DADY_DRDY(ay,ry) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.dady_drdy = ((ay)<<16 | (ry))
+#define SETT3_GS_BS(gs,bs) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.gs_bs = ((gs)<<16 | (bs))
+#define SETT3_AS_RS(as,rs) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.as_rs = ((as)<<16 | (rs))
+#define SETT3_DZDX(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.dzdx = (val)
+#define SETT3_DZDY(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.dzdy = (val)
+#define SETT3_ZS(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.zs = (val)
+#define SETT3_DXDY12(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.dxdy12 = (val)
+#define SETT3_XEND12(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.xend12 = (val)
+#define SETT3_DXDY01(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.dxdy01 = (val)
+#define SETT3_XEND01(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.xend01 = (val)
+#define SETT3_DXDY02(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.dxdy02 = (val)
+#define SETT3_XSTART02(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.xstart02 = (val)
+#define SETT3_YSTART(val) ((mmtr)s3vMmioMem)->triangle3d_regs.regs.ystart = (val)
+#define SETT3_Y01_Y12(y01,y12) do { write_mem_barrier(); ((mmtr)s3vMmioMem)->triangle3d_regs.regs.y01_y12 = ((y01)<<16 | (y12)); write_mem_barrier(); } while (0)
+
+
+
+#define DBGOUT(p) /* OUTREG8(0x3bc,p) */
+
+#endif /* 0 */
+
+#endif /* _NEWMMIO_H */
diff --git a/src/regs3v.h b/src/regs3v.h
new file mode 100644
index 0000000..6053054
--- /dev/null
+++ b/src/regs3v.h
@@ -0,0 +1,310 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/regs3v.h,v 1.9 2002/01/25 21:56:08 tsi Exp $ */
+
+/*
+Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the XFree86 Project shall not
+be used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the XFree86 Project.
+*/
+
+/*
+ * regs3v.h
+ *
+ * Port to 4.0 design level
+ *
+ * S3 ViRGE driver
+ *
+ * Portions based on code containing the following notices:
+ **********************************************************
+ *
+ * Written by Jake Richter Copyright (c) 1989, 1990 Panacea Inc., Londonderry,
+ * NH - All Rights Reserved
+ *
+ * This code may be freely incorporated in any program without royalty, as long
+ * as the copyright notice stays intact.
+ *
+ * Additions by Kevin E. Martin (martin@cs.unc.edu)
+ *
+ * KEVIN E. MARTIN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEVIN E. MARTIN 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.
+ *
+ */
+
+/* Taken from accel/s3_virge code */
+/* 23/03/97 S. Marineau: fixed bug with first Doubleword Offset macros
+ * and added macro CommandWaitIdle to wait for the command FIFO to empty
+ */
+
+
+#ifndef _REGS3V_H
+#define _REGS3V_H
+
+#define S3_ViRGE_SERIES(chip) ((chip&0xfff0)==0x31e0)
+#define S3_ViRGE_GX2_SERIES(chip) (chip == S3_ViRGE_GX2 || chip == S3_TRIO_3D_2X)
+#define S3_ViRGE_MX_SERIES(chip) (chip == S3_ViRGE_MX || chip == S3_ViRGE_MXP)
+#define S3_ViRGE_MXP_SERIES(chip) (chip == S3_ViRGE_MXP)
+#define S3_ViRGE_VX_SERIES(chip) ((chip&0xfff0)==0x3de0)
+#define S3_TRIO_3D_SERIES(chip) (chip == S3_TRIO_3D)
+#define S3_TRIO_3D_2X_SERIES(chip) (chip == S3_TRIO_3D_2X)
+
+/* Chip tags */
+#define PCI_S3_VENDOR_ID PCI_VENDOR_S3
+#define S3_UNKNOWN 0
+#define S3_ViRGE PCI_CHIP_VIRGE
+#define S3_ViRGE_VX PCI_CHIP_VIRGE_VX
+#define S3_ViRGE_DXGX PCI_CHIP_VIRGE_DXGX
+#define S3_ViRGE_GX2 PCI_CHIP_VIRGE_GX2
+#define S3_ViRGE_MX PCI_CHIP_VIRGE_MX
+#define S3_ViRGE_MXP PCI_CHIP_VIRGE_MXP
+#define S3_TRIO_3D PCI_CHIP_Trio3D
+#define S3_TRIO_3D_2X PCI_CHIP_Trio3D_2X
+
+/* Subsystem Control Register */
+#define GPCTRL_NC 0x0000
+#define GPCTRL_ENAB 0x4000
+#define GPCTRL_RESET 0x8000
+
+
+/* Command Register */
+#define CMD_OP_MSK (0xf << 27)
+#define CMD_BITBLT (0x0 << 27)
+#define CMD_RECT ((0x2 << 27) | 0x0100)
+#define CMD_LINE (0x3 << 27)
+#define CMD_POLYFILL (0x5 << 27)
+#define CMD_NOP (0xf << 27)
+
+#define BYTSEQ 0
+#define _16BIT 0
+#define PCDATA 0x80
+#define INC_Y CMD_YP
+#define YMAJAXIS 0
+#define INC_X CMD_XP
+#define DRAW 0x0020
+#define LINETYPE 0x0008
+#define LASTPIX 0
+#define PLANAR 0 /* MIX_MONO_SRC */
+#define WRTDATA 0
+
+/*
+ * Short Stroke Vector Transfer Register (The angular Defs also apply to the
+ * Command Register
+ */
+#define VECDIR_000 0x0000
+#define VECDIR_045 0x0020
+#define VECDIR_090 0x0040
+#define VECDIR_135 0x0060
+#define VECDIR_180 0x0080
+#define VECDIR_225 0x00a0
+#define VECDIR_270 0x00c0
+#define VECDIR_315 0x00e0
+#define SSVDRAW 0x0010
+
+/* Command AutoExecute */
+#define CMD_AUTOEXEC 0x01
+
+/* Command Hardware Clipping Enable */
+#define CMD_HWCLIP 0x02
+
+/* Destination Color Format */
+#define DST_8BPP 0x00
+#define DST_16BPP 0x04
+#define DST_24BPP 0x08
+
+/* BLT Mix modes */
+#define MIX_BITBLT 0x0000
+#define MIX_MONO_SRC 0x0040
+#define MIX_CPUDATA 0x0080
+#define MIX_MONO_PATT 0x0100
+#define MIX_COLOR_PATT 0x0000
+#define MIX_MONO_TRANSP 0x0200
+
+/* Image Transfer Alignments */
+#define CMD_ITA_BYTE 0x0000
+#define CMD_ITA_WORD 0x0400
+#define CMD_ITA_DWORD 0x0800
+
+/* First Doubleword Offset (Image Transfer) */
+#define CMD_FDO_BYTE0 0x00000
+#define CMD_FDO_BYTE1 0x01000
+#define CMD_FDO_BYTE2 0x02000
+#define CMD_FDO_BYTE3 0x03000
+
+/* X Positive, Y Positive (Bit BLT) */
+#define CMD_XP 0x2000000
+#define CMD_YP 0x4000000
+
+/* 2D or 3D Select */
+#define CMD_2D 0x00000000
+#define CMD_3D 0x80000000
+
+/* The Mix ROPs (selected ones, not all 256) */
+#if 0
+
+#define ROP_0 (0x00<<17)
+#define ROP_DSon (0x11<<17)
+#define ROP_DSna (0x22<<17)
+#define ROP_Sn (0x33<<17)
+#define ROP_SDna (0x44<<17)
+#define ROP_Dn (0x55<<17)
+#define ROP_DSx (0x66<<17)
+#define ROP_DSan (0x77<<17)
+#define ROP_DSa (0x88<<17)
+#define ROP_DSxn (0x99<<17)
+#define ROP_D (0xaa<<17)
+#define ROP_DSno (0xbb<<17)
+#define ROP_S (0xcc<<17)
+#define ROP_SDno (0xdd<<17)
+#define ROP_DSo (0xee<<17)
+#define ROP_1 (0xff<<17)
+
+/* ROP -> (ROP & P) | (D & ~P) */
+#define ROP_0_PaDPnao /* DPna */ (0x0a<<17)
+#define ROP_DSon_PaDPnao /* PDSPaox */ (0x1a<<17)
+#define ROP_DSna_PaDPnao /* DPSana */ (0x2a<<17)
+#define ROP_Sn_PaDPnao /* SPDSxox */ (0x3a<<17)
+#define ROP_SDna_PaDPnao /* DPSDoax */ (0x4a<<17)
+#define ROP_Dn_PaDPnao /* DPx */ (0x5a<<17)
+#define ROP_DSx_PaDPnao /* DPSax */ (0x6a<<17)
+#define ROP_DSan_PaDPnao /* DPSDnoax */ (0x7a<<17)
+#define ROP_DSa_PaDPnao /* DSPnoa */ (0x8a<<17)
+#define ROP_DSxn_PaDPnao /* DPSnax */ (0x9a<<17)
+#define ROP_D_PaDPnao /* D */ (0xaa<<17)
+#define ROP_DSno_PaDPnao /* DPSnao */ (0xba<<17)
+#define ROP_S_PaDPnao /* DPSDxax */ (0xca<<17)
+#define ROP_SDno_PaDPnao /* DPSDanax */ (0xda<<17)
+#define ROP_DSo_PaDPnao /* DPSao */ (0xea<<17)
+#define ROP_1_PaDPnao /* DPo */ (0xfa<<17)
+
+
+/* S -> P */
+#define ROP_DPon (0x05<<17)
+#define ROP_DPna (0x0a<<17)
+#define ROP_Pn (0x0f<<17)
+#define ROP_PDna (0x50<<17)
+#define ROP_DPx (0x5a<<17)
+#define ROP_DPan (0x5f<<17)
+#define ROP_DPa (0xa0<<17)
+#define ROP_DPxn (0xa5<<17)
+#define ROP_DPno (0xaf<<17)
+#define ROP_P (0xf0<<17)
+#define ROP_PDno (0xf5<<17)
+#define ROP_DPo (0xfa<<17)
+
+/* ROP -> (ROP & S) | (~ROP & D) */
+#define ROP_DPSDxax (0xca<<17)
+#define ROP_DSPnoa (0x8a<<17)
+#define ROP_DPSao (0xea<<17)
+#define ROP_DPSoa (0xa8<<17)
+#define ROP_DSa (0x88<<17)
+#define ROP_SSPxDSxax (0xe8<<17)
+#define ROP_SDPoa (0xc8<<17)
+#define ROP_DSPnao (0xae<<17)
+#define ROP_SSDxPDxax (0x8e<<17)
+#define ROP_DSo (0xee<<17)
+#define ROP_SDPnao (0xce<<17)
+#define ROP_SPDSxax (0xac<<17)
+#define ROP_SDPnoa (0x8c<<17)
+#define ROP_SDPao (0xec<<17)
+
+/* ROP_sp -> (ROP_sp & S) | (D & ~S) */
+#define ROP_0_SaDSnao /* DSna */ (0x22<<17)
+#define ROP_DPa_SaDSnao /* DPSnoa */ (0xa2<<17)
+#define ROP_PDna_SaDSnao /* DSPDoax */ (0x62<<17)
+#define ROP_P_SaDSnao /* DSPDxax */ (0xe2<<17)
+#define ROP_DPna_SaDSnao /* DPSana */ (0x2a<<17)
+#define ROP_D_SaDSnao /* D */ (0xaa<<17)
+#define ROP_DPx_SaDSnao /* DPSax */ (0x6a<<17)
+#define ROP_DPo_SaDSnao /* DPSao */ (0xea<<17)
+#define ROP_DPon_SaDSnao /* SDPSaox */ (0x26<<17)
+#define ROP_DPxn_SaDSnao /* DSPnax */ (0xa6<<17)
+#define ROP_Dn_SaDSnao /* DSx */ (0x66<<17)
+#define ROP_PDno_SaDSnao /* SDPSanax */ (0xe6<<17)
+#define ROP_Pn_SaDSnao /* PSDPxox */ (0x2e<<17)
+#define ROP_DPno_SaDSnao /* DSPnao */ (0xae<<17)
+#define ROP_DPan_SaDSnao /* SDPSnoax */ (0x6e<<17)
+#define ROP_1_SaDSnao /* DSo */ (0xee<<17)
+
+#endif
+
+
+#define MAXLOOP 0x0fffff /* timeout value for engine waits, 0.5 secs */
+
+/* Wait until "v" queue entries are free */
+#define WaitQueue(v) \
+ if (ps3v->NoPCIRetry) { \
+ do { int loop=0; mem_barrier(); \
+ while ((((IN_SUBSYS_STAT()) & 0x1f00) < (((v)+2) << 8)) && (loop++<MAXLOOP)); \
+ if (loop >= MAXLOOP) S3VGEReset(pScrn,1,__LINE__,__FILE__); \
+ } while (0); }
+
+/* Wait until GP is idle and queue is empty */
+#define WaitIdleEmpty() \
+ do { int loop=0; mem_barrier(); \
+ if(S3_TRIO_3D_SERIES(ps3v->Chipset)) \
+ while (((IN_SUBSYS_STAT() & 0x3f802000 & 0x20002000) != 0x20002000) && \
+ (loop++<MAXLOOP)); \
+ else \
+ while (((IN_SUBSYS_STAT() & 0x3f00) != 0x3000) && (loop++<MAXLOOP)); \
+ if (loop >= MAXLOOP) S3VGEReset(pScrn,1,__LINE__,__FILE__); \
+ } while (0)
+
+/* Wait until GP is idle */
+#define WaitIdle() \
+ do { int loop=0; mem_barrier(); \
+ while ((!(IN_SUBSYS_STAT() & 0x2000)) && (loop++<MAXLOOP)); \
+ if (loop >= MAXLOOP) S3VGEReset(pScrn,1,__LINE__,__FILE__); \
+ } while (0)
+
+
+/* Wait until Command FIFO is empty */
+#define WaitCommandEmpty() do { int loop=0; mem_barrier(); \
+ if (S3_ViRGE_GX2_SERIES(S3_ViRGE_GX2) || S3_ViRGE_MX_SERIES(ps3v->Chipset)) \
+ while ((!(((((mmtr)s3vMmioMem)->subsys_regs.regs.adv_func_cntl)) & 0x400)) && (loop++<MAXLOOP)); \
+ else if (S3_TRIO_3D_SERIES(ps3v->Chipset)) \
+ while (((IN_SUBSYS_STAT() & 0x5f00) != 0x5f00) && (loop++<MAXLOOP)); \
+ else \
+ while ((!(((((mmtr)s3vMmioMem)->subsys_regs.regs.adv_func_cntl)) & 0x200)) && (loop++<MAXLOOP)); \
+ if (loop >= MAXLOOP) S3VGEReset(pScrn,1,__LINE__,__FILE__); \
+ } while (0)
+
+/* Wait until a DMA transfer is done */
+#define WaitDMAEmpty() \
+ do { int loop=0; mem_barrier(); \
+ while (((((mmtr)s3vMmioMem)->dma_regs.regs.cmd.write_pointer) != (((mmtr)s3vMmioMem)->dma_regs.regs.cmd.read_pointer)) && (loop++<MAXLOOP)); \
+ if (loop >= MAXLOOP) S3VGEReset(pScrn,1,__LINE__,__FILE__); \
+ } while(0)
+
+
+
+
+
+#define RGB8_PSEUDO (-1)
+#define RGB16_565 0
+#define RGB16_555 1
+#define RGB32_888 2
+
+#endif /* _REGS3V_H */
+
diff --git a/src/s3v.h b/src/s3v.h
new file mode 100644
index 0000000..62436ff
--- /dev/null
+++ b/src/s3v.h
@@ -0,0 +1,427 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/s3v.h,v 1.31 2003/02/04 02:20:49 dawes Exp $ */
+
+/*
+Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the XFree86 Project shall not
+be used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the XFree86 Project.
+*/
+
+#ifndef _S3V_H
+#define _S3V_H
+
+/* All drivers should typically include these */
+#include "xf86.h"
+#include "xf86_OSproc.h"
+
+/* All drivers need this */
+#include "xf86_ansic.h"
+
+/* Everything using inb/outb, etc needs "compiler.h" */
+#include "compiler.h"
+
+/* Drivers for PCI hardware need this */
+#include "xf86PciInfo.h"
+
+/* Drivers that need to access the PCI config space directly need this */
+#include "xf86Pci.h"
+
+#include "xf86Cursor.h"
+
+#include "vgaHW.h"
+
+#include "s3v_macros.h"
+
+/* All drivers initialising the SW cursor need this */
+#include "mipointer.h"
+
+/* All drivers using the mi colormap manipulation need this */
+#include "micmap.h"
+
+/* fb support */
+
+#include "fb.h"
+
+/* Drivers using the XAA interface ... */
+#include "xaa.h"
+#include "xaalocal.h"
+#include "xf86cmap.h"
+#include "xf86i2c.h"
+
+#include "vbe.h"
+
+/* Drivers using the EXA interface ... */
+#include "exa.h"
+
+#include "xf86xv.h"
+#include <X11/extensions/Xv.h>
+#include "fourcc.h"
+
+#ifndef _S3V_VGAHWMMIO_H
+#define _S3V_VGAHWMMIO_H
+
+#define VGAIN8(addr) MMIO_IN8(ps3v->MapBase,(S3V_MMIO_REGSIZE + (addr)))
+#define VGAIN16(addr) MMIO_IN16(ps3v->MapBase,(S3V_MMIO_REGSIZE + (addr)))
+#define VGAIN(addr) MMIO_IN32(ps3v->MapBase,(S3V_MMIO_REGSIZE + (addr)))
+#define VGAOUT8(addr,val) MMIO_OUT8(ps3v->MapBase,(S3V_MMIO_REGSIZE + (addr)),\
+ val)
+#define VGAOUT16(addr,val) MMIO_OUT16(ps3v->MapBase,\
+ (S3V_MMIO_REGSIZE + (addr)), val)
+#define VGAOUT(addr, val) MMIO_OUT32(ps3v->MapBase,\
+ (S3V_MMIO_REGSIZE + (addr)), val)
+
+#define INREG(addr) MMIO_IN32(ps3v->MapBase, addr)
+#define OUTREG(addr, val) MMIO_OUT32(ps3v->MapBase, addr, val)
+#define NEW_INREG(addr) MMIO_IN32(s3vMmioMem, addr)
+#define NEW_OUTREG(addr, val) MMIO_OUT32(s3vMmioMem, addr, val)
+
+#endif /*_S3V_VGAHWMMIO_H*/
+
+/******************* s3v_i2c ****************************/
+
+Bool S3V_I2CInit(ScrnInfoPtr pScrn);
+
+/******************* s3v_accel ****************************/
+
+void S3VGEReset(ScrnInfoPtr pScrn, int from_timeout, int line, char *file);
+
+
+/*********************************************/
+/* locals */
+
+/* Some S3 ViRGE structs */
+#include "newmmio.h"
+
+/* More ViRGE defines */
+#include "regs3v.h"
+
+/*********************************************/
+
+
+
+/* Driver data structure; this should contain all needed info for a mode */
+/* used to be in s3v_driver.h for pre 4.0 */
+typedef struct {
+ unsigned char SR08, SR0A, SR0F;
+ unsigned char SR10, SR11, SR12, SR13, SR15, SR18; /* SR9-SR1C, ext seq. */
+ unsigned char SR29;
+ unsigned char SR54, SR55, SR56, SR57;
+ unsigned char Clock;
+ unsigned char s3DacRegs[0x101];
+ unsigned char CR31, CR33, CR34, CR36, CR3A, CR3B, CR3C;
+ unsigned char CR40, CR41, CR42, CR43, CR45;
+ unsigned char CR51, CR53, CR54, CR55, CR58, CR5D, CR5E;
+ unsigned char CR63, CR65, CR66, CR67, CR68, CR69, CR6D; /* Video attrib. */
+ unsigned char CR7B, CR7D;
+ unsigned char CR85, CR86, CR87;
+ unsigned char CR90, CR91, CR92, CR93;
+ unsigned char ColorStack[8]; /* S3 hw cursor color stack CR4A/CR4B */
+ unsigned int STREAMS[22]; /* Streams regs */
+ unsigned int MMPR0, MMPR1, MMPR2, MMPR3; /* MIU regs */
+} S3VRegRec, *S3VRegPtr;
+
+
+/*********************************/
+/* S3VPortPrivRec */
+/*********************************/
+
+typedef struct {
+ unsigned char brightness;
+ unsigned char contrast;
+ FBAreaPtr area;
+ RegionRec clip;
+ CARD32 colorKey;
+ CARD32 videoStatus;
+ Time offTime;
+ Time freeTime;
+ int lastPort;
+} S3VPortPrivRec, *S3VPortPrivPtr;
+
+
+/*************************/
+/* S3VRec */
+/*************************/
+
+typedef struct _S3V {
+ /* S3V console saved mode registers */
+ S3VRegRec SavedReg;
+ /* XServer video state mode registers */
+ S3VRegRec ModeReg;
+ /* HW Cursor info */
+ xf86CursorInfoPtr CursorInfoRec;
+ /* Flag indicating ModeReg has been */
+ /* duped from console state. */
+ Bool ModeStructInit;
+ /* Is STREAMS processor needed for */
+ /* this mode? */
+ Bool NeedSTREAMS;
+ /* Is STREAMS running now ? */
+ Bool STREAMSRunning;
+ int Width, Bpp,Bpl, ScissB;
+ unsigned PlaneMask;
+ I2CBusPtr I2C;
+ /* In units as noted, set in PreInit */
+ int videoRambytes;
+ int videoRamKbytes;
+ /* In Kbytes, set in PreInit */
+ int MemOffScreen;
+
+ /* These are linear addresses */
+ unsigned char* MapBase;
+ unsigned char* MapBaseDense;
+ /* Same as MapBase, except framebuffer*/
+ unsigned char* FBBase;
+ /* Current visual FB starting location */
+ unsigned char* FBStart;
+
+ /* Flag indicating if vgaHWMapMem was */
+ /* used successfully for this screen */
+ Bool PrimaryVidMapped;
+ int HorizScaleFactor;
+ Bool bankedMono;
+ /* Memory Clock, input reference Clock and MX LCD clock */
+ int MCLK, REFCLK, LCDClk;
+ /* MX reference clock scale */
+ double refclk_fact;
+ /* Limit the number of errors */
+ /* printed using a counter */
+ int GEResetCnt;
+
+ /* ViRGE options */
+ OptionInfoPtr Options;
+ /* Enable PCI burst mode for reads? */
+ Bool pci_burst;
+ /* Diasable PCI retries */
+ Bool NoPCIRetry;
+ /* Adjust fifo for acceleration? */
+ Bool fifo_conservative;
+ Bool fifo_moderate;
+ Bool fifo_aggressive;
+ /* Set memory options */
+ Bool slow_edodram;
+ Bool slow_dram;
+ Bool fast_dram;
+ Bool fpm_vram;
+ /* Disable Acceleration */
+ Bool NoAccel;
+ /* Adjust memory ras precharge */
+ /* timing */
+ Bool ShowCache;
+ Bool early_ras_precharge;
+ Bool late_ras_precharge;
+ /* MX LCD centering */
+ Bool lcd_center;
+ /* hardware cursor enabled */
+ Bool hwcursor;
+ Bool UseFB;
+ Bool mx_cr3a_fix;
+ Bool XVideo;
+
+ /* Pointer used to save wrapped */
+ /* CloseScreen function. */
+ CloseScreenProcPtr CloseScreen;
+
+ /* accel additions */
+ CARD32 AccelFlags;
+ CARD32 AccelCmd;
+ CARD32 SrcBaseY, DestBaseY;
+ CARD32 Stride;
+ CARD32 CommonCmd;
+ CARD32 FullPlaneMask;
+ GCPtr CurrentGC;
+ /* fb support */
+ DrawablePtr CurrentDrawable;
+ /* end accel stuff */
+ /* ViRGE specifics -start- */
+ /* Xv support */
+ XF86VideoAdaptorPtr adaptor;
+ S3VPortPrivPtr portPrivate;
+
+ /* Compatibility variables */
+ int vgaCRIndex, vgaCRReg;
+ /* XAA */
+ int bltbug_width1, bltbug_width2;
+ /* Cursor storage location */
+ CARD32 FBCursorOffset;
+ /* Saved CR53 value */
+ unsigned char EnableMmioCR53;
+ /* Extended reg unlock storage */
+ unsigned char CR38,CR39,CR40;
+
+ /* Accel WaitFifo function */
+ void (*pWaitFifo)(struct _S3V *, int);
+ /* Accel WaitCmd function */
+ void (*pWaitCmd)(struct _S3V *);
+ void (*WaitForEmpty)(void);
+
+ /* Used by ViRGE driver, but generic */
+
+ /* PCI info vars. */
+ pciVideoPtr PciInfo;
+ PCITAG PciTag;
+ /* Chip info, set using PCI */
+ /* above. */
+ int Chipset;
+ int ChipRev;
+
+ /* support for EXA */
+ ExaDriverPtr EXADriverPtr;
+ Bool useEXA;
+ unsigned long EXAendfb;
+ unsigned long dst_offset;
+ unsigned long src_offset;
+ unsigned long dst_stride;
+ unsigned long src_stride;
+
+ /* XAA info Rec */
+ XAAInfoRecPtr AccelInfoRec;
+ /* DGA2 */
+ DGAModePtr DGAModes;
+ int numDGAModes;
+ Bool DGAactive;
+ int DGAViewportStatus;
+ vbeInfoPtr pVbe;
+
+ /* Support for shadowFB and rotation */
+ Bool shadowFB;
+ int rotate;
+ unsigned char* ShadowPtr;
+ int ShadowPitch;
+ void (*PointerMoved)(int index, int x, int y);
+
+} S3VRec, *S3VPtr;
+
+
+#define S3VPTR(p) ((S3VPtr)((p)->driverPrivate))
+
+
+/* #define S3V_DEBUG */
+
+#ifdef S3V_DEBUG
+#define PVERB5(arg) ErrorF(arg)
+#define VERBLEV 1
+#else
+#define PVERB5(arg) xf86ErrorFVerb(5, arg)
+#define VERBLEV 5
+#endif
+
+
+/******************* regs3v *******************************/
+
+/* cep kjb */
+#define VertDebug 1
+
+/* #ifndef MetroLink */
+#if !defined (MetroLink) && !defined (VertDebug)
+#define VerticalRetraceWait() do { \
+ VGAOUT8(vgaCRIndex, 0x17); \
+ if ( VGAIN8(vgaCRReg) & 0x80 ) { \
+ while ((VGAIN8(vgaIOBase + 0x0A) & 0x08) == 0x00) ; \
+ while ((VGAIN8(vgaIOBase + 0x0A) & 0x08) == 0x08) ; \
+ while ((VGAIN8(vgaIOBase + 0x0A) & 0x08) == 0x00) ; \
+ }\
+} while (0)
+
+#else
+#define SPIN_LIMIT 1000000
+#define VerticalRetraceWait() do { \
+ VGAOUT8(vgaCRIndex, 0x17); \
+ if ( VGAIN8(vgaCRReg) & 0x80 ) { \
+ volatile unsigned long _spin_me; \
+ for (_spin_me = 0; \
+ ((VGAIN8(vgaIOBase + 0x0A) & 0x08) == 0x00) && _spin_me <= SPIN_LIMIT; \
+ _spin_me++) ; \
+ if (_spin_me > SPIN_LIMIT) \
+ ErrorF("s3v: warning: VerticalRetraceWait timed out(1:3).\n"); \
+ for (_spin_me = 0; \
+ ((VGAIN8(vgaIOBase + 0x0A) & 0x08) == 0x08) && _spin_me <= SPIN_LIMIT; \
+ _spin_me++) ; \
+ if (_spin_me > SPIN_LIMIT) \
+ ErrorF("s3v: warning: VerticalRetraceWait timed out(2:3).\n"); \
+ for (_spin_me = 0; \
+ ((VGAIN8(vgaIOBase + 0x0A) & 0x08) == 0x00) && _spin_me <= SPIN_LIMIT; \
+ _spin_me++) ; \
+ if (_spin_me > SPIN_LIMIT) \
+ ErrorF("s3v: warning: VerticalRetraceWait timed out(3:3).\n"); \
+ } \
+} while (0)
+#endif
+
+
+/*********************************************************/
+
+
+/* Various defines which are used to pass flags between the Setup and
+ * Subsequent functions.
+ */
+
+#define NO_MONO_FILL 0x00
+#define NEED_MONO_FILL 0x01
+#define MONO_TRANSPARENCY 0x02
+
+/* prototypes */
+/* s3v_dac.c */
+extern void S3VCommonCalcClock(ScrnInfoPtr pScrn, DisplayModePtr mode,
+ long freq, int min_m, int min_n1, int max_n1,
+ int min_n2, int max_n2, long freq_min, long freq_max,
+ unsigned char * mdiv, unsigned char * ndiv);
+
+/* s3v_accel.c */
+extern Bool S3VAccelInit(ScreenPtr pScreen);
+extern Bool S3VAccelInit32(ScreenPtr pScreen);
+void S3VAccelSync(ScrnInfoPtr);
+void S3VWaitFifoGX2(S3VPtr ps3v, int slots );
+void S3VWaitFifoMain(S3VPtr ps3v, int slots );
+void S3VWaitCmdGX2(S3VPtr ps3v);
+void S3VWaitDummy(S3VPtr ps3v);
+
+/* XAA and EXA */
+Bool S3VXAAInit(ScreenPtr);
+Bool S3VEXAInit(ScreenPtr);
+
+/* s3v_hwcurs.c */
+extern Bool S3VHWCursorInit(ScreenPtr pScreen);
+
+/* s3v_driver.c */
+void S3VAdjustFrame(int scrnIndex, int x, int y, int flags);
+Bool S3VSwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
+
+/* s3v_dga.c */
+Bool S3VDGAInit(ScreenPtr pScreen);
+
+/* in s3v_shadow.c */
+void s3vPointerMoved(int index, int x, int y);
+void s3vRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+void s3vRefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+void s3vRefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+void s3vRefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+void s3vRefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+
+/* s3v_xv.c X Video Extension support */
+void S3VInitVideo(ScreenPtr pScreen);
+int S3VQueryXvCapable(ScrnInfoPtr);
+
+#endif /*_S3V_H*/
+
+
+/*EOF*/
+
+
diff --git a/src/s3v_accel.c b/src/s3v_accel.c
new file mode 100644
index 0000000..ce5643e
--- /dev/null
+++ b/src/s3v_accel.c
@@ -0,0 +1,400 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/s3v_accel.c,v 1.25 2003/11/06 18:38:05 tsi Exp $ */
+
+/*
+Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the XFree86 Project shall not
+be used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the XFree86 Project.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* fb includes are in s3v.h */
+#include "s3v.h"
+#include "miline.h"
+
+#include "servermd.h" /* LOG2_BYTES_PER_SCANLINE_PAD */
+
+static void S3VWriteMask(CARD32*, int);
+
+static void S3VNopAllCmdSets(ScrnInfoPtr pScrn);
+
+void VWaitFifoGX2(S3VPtr ps3v, int slots);
+void S3VWaitFifoMain(S3VPtr ps3v, int slots);
+void S3VWaitDummy(S3VPtr ps3v);
+void S3VEngineReset(ScrnInfoPtr pScrn);
+
+Bool S3VAccelInit(ScreenPtr pScreen);
+Bool S3VAccelInit32(ScreenPtr pScreen);
+
+Bool
+S3VAccelInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ switch(ps3v->Chipset)
+ {
+ case S3_ViRGE:
+ case S3_ViRGE_VX:
+ ps3v->AccelFlags = BLT_BUG;
+ break;
+ default:
+ ps3v->AccelFlags = 0;
+ break;
+ }
+
+ ps3v->AccelFlags |= MONO_TRANS_BUG; /* which aren't broken ? */
+
+ ps3v->EXAendfb = ps3v->videoRambytes -
+ 1024 - /* hw cursor */
+ 0x200000;
+
+ if (ps3v->useEXA)
+ return S3VEXAInit(pScreen);
+ else
+ return S3VXAAInit(pScreen);
+}
+
+Bool
+S3VAccelInit32(ScreenPtr pScreen)
+{
+ return FALSE;
+}
+
+void
+S3VNopAllCmdSets(ScrnInfoPtr pScrn)
+{
+ int i;
+ int max_it=1000;
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ if (xf86GetVerbosity() > 1) {
+ ErrorF("\tTrio3D -- S3VNopAllCmdSets: SubsysStats#1 = 0x%08lx\n",
+ (unsigned long)IN_SUBSYS_STAT());
+ }
+
+ mem_barrier();
+ for(i=0;i<max_it;i++) {
+ if( (IN_SUBSYS_STAT() & 0x3f802000 & 0x20002000) == 0x20002000) {
+ break;
+ }
+ }
+
+ if(i!=max_it) {
+ if (xf86GetVerbosity() > 1) ErrorF("\tTrio3D -- S3VNopAllCmdSets: state changed after %d iterations\n",i);
+ } else {
+ if (xf86GetVerbosity() > 1) ErrorF("\tTrio3D -- S3VNopAllCmdSets: state DIDN'T changed after %d iterations\n",max_it);
+ }
+
+ WaitQueue(5);
+
+ OUTREG(CMD_SET, CMD_NOP);
+
+ if (xf86GetVerbosity() > 1) {
+ ErrorF("\tTrio3D -- S3VNopAllCmdSets: SubsysStats#2 = 0x%08lx\n",
+ (unsigned long)IN_SUBSYS_STAT());
+ }
+}
+
+void
+S3VGEReset(ScrnInfoPtr pScrn, int from_timeout, int line, char *file)
+{
+ unsigned long gs1, gs2; /* -- debug info for graphics state -- */
+ unsigned char tmp, sr1, resetidx=0x66; /* FIXME */
+ int r;
+ int ge_was_on = 0;
+ CARD32 fifo_control = 0, miu_control = 0;
+ CARD32 streams_timeout = 0, misc_timeout = 0;
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ S3VPtr ps3v = S3VPTR(pScrn);
+ int vgaCRIndex, vgaCRReg, vgaIOBase;
+ vgaIOBase = hwp->IOBase;
+ vgaCRIndex = vgaIOBase + 4;
+ vgaCRReg = vgaIOBase + 5;
+
+
+ if (S3_TRIO_3D_SERIES(ps3v->Chipset)) {
+ VGAOUT8(0x3c4,0x01);
+ sr1 = VGAIN8(0x3c5);
+
+ if (sr1 & 0x20) {
+ if (xf86GetVerbosity() > 1)
+ ErrorF("\tTrio3D -- Display is on...turning off\n");
+ VGAOUT8(0x3c5,sr1 & ~0x20);
+ VerticalRetraceWait();
+ }
+ }
+
+ if (from_timeout) {
+ if (ps3v->GEResetCnt++ < 10 || xf86GetVerbosity() > 1)
+ ErrorF("\tS3VGEReset called from %s line %d\n",file,line);
+ }
+ else {
+ if (S3_TRIO_3D_SERIES(ps3v->Chipset))
+ S3VNopAllCmdSets(pScrn);
+ WaitIdleEmpty();
+ }
+
+
+ if (from_timeout && (ps3v->Chipset == S3_ViRGE || ps3v->Chipset == S3_ViRGE_VX || ps3v->Chipset == S3_ViRGE_DXGX)) {
+ /* reset will trash these registers, so save them */
+ fifo_control = INREG(FIFO_CONTROL_REG);
+ miu_control = INREG(MIU_CONTROL_REG);
+ streams_timeout = INREG(STREAMS_TIMEOUT_REG);
+ misc_timeout = INREG(MISC_TIMEOUT_REG);
+ }
+
+ if(ps3v->Chipset == S3_ViRGE_VX){
+ VGAOUT8(vgaCRIndex, 0x63);
+ }
+ else {
+ VGAOUT8(vgaCRIndex, 0x66);
+ }
+ if (!S3_TRIO_3D_SERIES(ps3v->Chipset)) {
+ tmp = VGAIN8(vgaCRReg);
+
+ usleep(10000);
+ for (r=1; r<10; r++) { /* try multiple times to avoid lockup of ViRGE/MX */
+ VGAOUT8(vgaCRReg, tmp | 0x02);
+ usleep(10000);
+ VGAOUT8(vgaCRReg, tmp & ~0x02);
+ usleep(10000);
+
+ xf86ErrorFVerb(VERBLEV, " S3VGEReset sub_stat=%lx \n",
+ (unsigned long)IN_SUBSYS_STAT()
+ );
+
+ if (!from_timeout)
+ WaitIdleEmpty();
+
+ OUTREG(DEST_SRC_STR, ps3v->Bpl << 16 | ps3v->Bpl);
+
+ usleep(10000);
+ if (((IN_SUBSYS_STAT() & 0x3f00) != 0x3000))
+ xf86ErrorFVerb(VERBLEV, "restarting S3 graphics engine reset %2d ...\n",r);
+ else
+ break;
+ }
+ } else {
+ usleep(10000);
+
+ for (r=1; r<10; r++) {
+ VerticalRetraceWait();
+ VGAOUT8(vgaCRIndex,resetidx);
+ tmp = VGAIN8(vgaCRReg);
+
+ VGAOUT8(0x3c4,0x01);
+ sr1 = VGAIN8(0x3c5);
+
+ if(sr1 & 0x20) {
+ if(xf86GetVerbosity() > 1) {
+ ErrorF("\tTrio3D -- Upps Display is on again ...turning off\n");
+ }
+ VGAOUT8(0x3c4,0x01);
+ VerticalRetraceWait();
+ VGAOUT8(0x3c5,sr1 & ~0x20);
+ }
+
+ VerticalRetraceWait();
+ gs1 = (long) IN_SUBSYS_STAT();
+
+ /* turn off the GE */
+
+ VGAOUT8(vgaCRIndex,resetidx);
+ if(tmp & 0x01) {
+ /* tmp &= ~0x01; */
+ VGAOUT8(vgaCRReg, tmp);
+ ge_was_on = 1;
+ usleep(10000);
+ }
+
+ gs2 = (long) IN_SUBSYS_STAT();
+ VGAOUT8(vgaCRReg, (tmp | 0x02));
+ usleep(10000);
+
+ VerticalRetraceWait();
+ VGAOUT8(vgaCRIndex,resetidx);
+ VGAOUT8(vgaCRReg, (tmp & ~0x02));
+ usleep(10000);
+
+ if(ge_was_on) {
+ tmp |= 0x01;
+ VGAOUT8(vgaCRReg, tmp);
+ usleep(10000);
+ }
+
+ if (xf86GetVerbosity() > 2) {
+ ErrorF("\tTrio3D -- GE was %s ST#1: 0x%08lx ST#2: 0x%08lx\n",
+ (ge_was_on) ? "on" : "off", gs1, gs2);
+ }
+
+ VerticalRetraceWait();
+
+ if (!from_timeout) {
+ S3VNopAllCmdSets(pScrn);
+ WaitIdleEmpty();
+ }
+
+ OUTREG(DEST_SRC_STR, ps3v->Bpl << 16 | ps3v->Bpl);
+ usleep(10000);
+
+ if((IN_SUBSYS_STAT() & 0x3f802000 & 0x20002000) != 0x20002000) {
+ if(xf86GetVerbosity() > 1)
+ ErrorF("restarting S3 graphics engine reset %2d ...%lx\n",
+ r, (unsigned long)IN_SUBSYS_STAT());
+ }
+ else
+ break;
+ }
+ }
+
+ if (from_timeout && (ps3v->Chipset == S3_ViRGE || ps3v->Chipset == S3_ViRGE_VX
+ || ps3v->Chipset == S3_ViRGE_DXGX)) {
+ /* restore trashed registers */
+ OUTREG(FIFO_CONTROL_REG, fifo_control);
+ OUTREG(MIU_CONTROL_REG, miu_control);
+ OUTREG(STREAMS_TIMEOUT_REG, streams_timeout);
+ OUTREG(MISC_TIMEOUT_REG, misc_timeout);
+ }
+
+ WAITFIFO(2);
+/* SETB_SRC_BASE(0); */
+/* SETB_DEST_BASE(0); */
+ OUTREG(SRC_BASE, 0);
+ OUTREG(DEST_BASE, 0);
+
+ WAITFIFO(4);
+ OUTREG(CLIP_L_R, ((0) << 16) | ps3v->Width);
+ OUTREG(CLIP_T_B, ((0) << 16) | ps3v->ScissB);
+ OUTREG(MONO_PAT_0, ~0);
+ OUTREG(MONO_PAT_1, ~0);
+
+ if (!from_timeout && S3_TRIO_3D_SERIES(ps3v->Chipset))
+ S3VNopAllCmdSets(pScrn);
+}
+
+void
+S3VEngineReset(ScrnInfoPtr pScrn)
+{
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ ps3v->SrcBaseY = 0;
+ ps3v->DestBaseY = 0;
+ ps3v->Stride = pScrn->displayWidth * pScrn->bitsPerPixel >> 3;
+
+ switch(pScrn->bitsPerPixel) {
+ case 8: ps3v->CommonCmd = DRAW | DST_8BPP;
+ ps3v->FullPlaneMask = 0x000000ff;
+ ps3v->bltbug_width1 = 51;
+ ps3v->bltbug_width2 = 64;
+ break;
+ case 16: ps3v->CommonCmd = DRAW | DST_16BPP;
+ ps3v->FullPlaneMask = 0x0000ffff;
+ ps3v->bltbug_width1 = 26;
+ ps3v->bltbug_width2 = 32;
+ break;
+ case 24: ps3v->CommonCmd = DRAW | DST_24BPP;
+ ps3v->FullPlaneMask = 0x00ffffff;
+ ps3v->bltbug_width1 = 16;
+ ps3v->bltbug_width2 = 22;
+ break;
+ }
+
+
+ WAITFIFO(5);
+ OUTREG(SRC_BASE, 0);
+ OUTREG(DEST_BASE, 0);
+ OUTREG(DEST_SRC_STR, ps3v->Stride | (ps3v->Stride << 16));
+
+ OUTREG(CLIP_L_R, ((0) << 16) | ps3v->Width);
+ OUTREG(CLIP_T_B, ((0) << 16) | ps3v->ScissB);
+}
+
+
+static void
+S3VWriteMask(
+ CARD32 *dstBase,
+ int dwords
+){
+ /* on alphas, be sure to call this with MapBaseDense, not MapBase! */
+ int numLeft;
+ CARD32 *dst = dstBase;
+
+ while(dwords >= 8192) {
+ numLeft = 8192;
+ while(numLeft) {
+ dst[0] = ~0; dst[1] = ~0;
+ dst[2] = ~0; dst[3] = ~0;
+ dst += 4;
+ numLeft -= 4;
+ }
+ dwords -= 8192;
+ dst = dstBase;
+ }
+ while(dwords >= 4) {
+ dst[0] = ~0; dst[1] = ~0;
+ dst[2] = ~0; dst[3] = ~0;
+ dst += 4;
+ dwords -= 4;
+ }
+ if(!dwords) return;
+ dst[0] = ~0;
+ if(dwords == 1) return;
+ dst[1] = ~0;
+ if(dwords == 2) return;
+ dst[2] = ~0;
+
+ return;
+}
+
+void
+S3VWaitFifoGX2(S3VPtr ps3v, int slots )
+{
+ if(ps3v->NoPCIRetry)
+ while(((INREG(SUBSYS_STAT_REG) >> 9) & 0x60) < slots){}
+}
+
+void
+S3VWaitFifoMain(S3VPtr ps3v, int slots )
+{
+ if(ps3v->NoPCIRetry)
+ while(((INREG(SUBSYS_STAT_REG) >> 8) & 0x1f) < slots){}
+}
+
+
+void
+S3VWaitCmdGX2(S3VPtr ps3v)
+{
+ while(((INREG(ADV_FUNC_CNTR) >> 6) & 0x1f) != 16){}
+}
+
+
+void
+S3VWaitDummy(S3VPtr ps3v)
+{
+ /* do nothing */
+}
+
+/*EOF*/
+
diff --git a/src/s3v_dac.c b/src/s3v_dac.c
new file mode 100644
index 0000000..180b7f4
--- /dev/null
+++ b/src/s3v_dac.c
@@ -0,0 +1,125 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/s3v_dac.c,v 1.4 2003/02/04 02:20:50 dawes Exp $ */
+
+/*
+Copyright (C) 1994-1998 The XFree86 Project, Inc. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the XFree86 Project shall not
+be used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the XFree86 Project.
+*/
+
+/*
+ * s3v_dac.c
+ * Port to 4.0 design level
+ *
+ * S3 ViRGE driver
+ *
+ *
+ * s3vcommonCalcClock from S3gendac.c in pre 4.0 tree.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "s3v.h"
+
+
+#define BASE_FREQ 14.31818 /* MHz */
+
+
+ /* function */
+void
+S3VCommonCalcClock(ScrnInfoPtr pScrn, DisplayModePtr mode,
+ long freq, int min_m, int min_n1,
+ int max_n1, int min_n2, int max_n2,
+ long freq_min, long freq_max,
+ unsigned char * mdiv, unsigned char * ndiv)
+{
+ double ffreq, ffreq_min, ffreq_max, ffreq_min_warn;
+ double div, diff, best_diff;
+ unsigned int m;
+ unsigned char n1, n2;
+ unsigned char best_n1=16+2, best_n2=2, best_m=125+2;
+
+ ffreq = freq / 1000.0 / BASE_FREQ;
+ ffreq_min = freq_min / 1000.0 / BASE_FREQ;
+ ffreq_max = freq_max / 1000.0 / BASE_FREQ;
+
+ /* Doublescan modes can run at half the min frequency */
+ /* But only use that value for warning and changing */
+ /* ffreq, don't change the actual min used for clock calcs below. */
+ if(mode->Flags & V_DBLSCAN && ffreq_min)
+ ffreq_min_warn = ffreq_min / 2;
+ else
+ ffreq_min_warn = ffreq_min;
+
+ if (ffreq < ffreq_min_warn / (1<<max_n2)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "invalid frequency %1.3f MHz [freq <= %1.3f MHz]\n",
+ ffreq*BASE_FREQ, ffreq_min_warn*BASE_FREQ / (1<<max_n2));
+ ffreq = ffreq_min_warn / (1<<max_n2);
+ }
+ if (ffreq > ffreq_max / (1<<min_n2)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "invalid frequency %1.3f MHz [freq >= %1.3f MHz]\n",
+ ffreq*BASE_FREQ, ffreq_max*BASE_FREQ / (1<<min_n2));
+ ffreq = ffreq_max / (1<<min_n2);
+ }
+
+ /* work out suitable timings */
+
+ best_diff = ffreq;
+
+ for (n2=min_n2; n2<=max_n2; n2++) {
+ for (n1 = min_n1+2; n1 <= max_n1+2; n1++) {
+ m = (int)(ffreq * n1 * (1<<n2) + 0.5) ;
+ if (m < min_m+2 || m > 127+2)
+ continue;
+ div = (double)(m) / (double)(n1);
+ if ((div >= ffreq_min) &&
+ (div <= ffreq_max)) {
+ diff = ffreq - div / (1<<n2);
+ if (diff < 0.0)
+ diff = -diff;
+ if (diff < best_diff) {
+ best_diff = diff;
+ best_m = m;
+ best_n1 = n1;
+ best_n2 = n2;
+ }
+ }
+ }
+ }
+
+#ifdef EXTENDED_DEBUG
+ ErrorF("Clock parameters for %1.6f MHz: m=%d, n1=%d, n2=%d\n",
+ ((double)(best_m) / (double)(best_n1) / (1 << best_n2)) * BASE_FREQ,
+ best_m-2, best_n1-2, best_n2);
+#endif
+
+ if (max_n1 == 63)
+ *ndiv = (best_n1 - 2) | (best_n2 << 6);
+ else
+ *ndiv = (best_n1 - 2) | (best_n2 << 5);
+ *mdiv = best_m - 2;
+}
+
diff --git a/src/s3v_dga.c b/src/s3v_dga.c
new file mode 100644
index 0000000..059ce6a
--- /dev/null
+++ b/src/s3v_dga.c
@@ -0,0 +1,362 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/s3v_dga.c,v 1.7 2002/01/14 18:02:58 dawes Exp $ */
+
+/*
+Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the XFree86 Project shall not
+be used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the XFree86 Project.
+*/
+
+/*
+Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the XFree86 Project shall not
+be used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the XFree86 Project.
+*/
+
+/*
+ * file: s3v_dga.c
+ * ported from mga
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "xf86Pci.h"
+#include "xf86PciInfo.h"
+#include "xaa.h"
+#include "xaalocal.h"
+#include "s3v.h"
+#if 0
+#include "mga_bios.h"
+#include "mga.h"
+#include "mga_reg.h"
+#include "mga_macros.h"
+#endif
+#include "dgaproc.h"
+
+
+static Bool S3V_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
+ int *, int *, int *);
+static Bool S3V_SetMode(ScrnInfoPtr, DGAModePtr);
+static int S3V_GetViewport(ScrnInfoPtr);
+static void S3V_SetViewport(ScrnInfoPtr, int, int, int);
+static void S3V_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
+static void S3V_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
+/* dummy... */
+#if 0
+static void MGA_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
+ unsigned long);
+#endif
+
+static
+DGAFunctionRec S3V_DGAFuncs = {
+ S3V_OpenFramebuffer,
+ NULL,
+ S3V_SetMode,
+ S3V_SetViewport,
+ S3V_GetViewport,
+ S3VAccelSync,
+ S3V_FillRect,
+ S3V_BlitRect,
+ NULL
+ /* dummy... MGA_BlitTransRect */
+};
+
+
+Bool
+S3VDGAInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ S3VPtr ps3v = S3VPTR(pScrn);
+ DGAModePtr modes = NULL, newmodes = NULL, currentMode;
+ DisplayModePtr pMode, firstMode;
+ int Bpp = pScrn->bitsPerPixel >> 3;
+ int num = 0;
+ Bool oneMore;
+
+ PVERB5(" S3VDGAInit\n");
+
+ pMode = firstMode = pScrn->modes;
+
+ while(pMode) {
+ /* The MGA driver wasn't designed with switching depths in
+ mind. Subsequently, large chunks of it will probably need
+ to be rewritten to accommodate depth changes in DGA mode */
+
+ if(0 /*pScrn->displayWidth != pMode->HDisplay*/) {
+ newmodes = xrealloc(modes, (num + 2) * sizeof(DGAModeRec));
+ oneMore = TRUE;
+ } else {
+ newmodes = xrealloc(modes, (num + 1) * sizeof(DGAModeRec));
+ oneMore = FALSE;
+ }
+
+ if(!newmodes) {
+ xfree(modes);
+ return FALSE;
+ }
+ modes = newmodes;
+
+SECOND_PASS:
+
+ currentMode = modes + num;
+ num++;
+
+ currentMode->mode = pMode;
+ currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
+ if(!ps3v->NoAccel)
+ currentMode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
+ if(pMode->Flags & V_DBLSCAN)
+ currentMode->flags |= DGA_DOUBLESCAN;
+ if(pMode->Flags & V_INTERLACE)
+ currentMode->flags |= DGA_INTERLACED;
+ currentMode->byteOrder = pScrn->imageByteOrder;
+ currentMode->depth = pScrn->depth;
+ currentMode->bitsPerPixel = pScrn->bitsPerPixel;
+ currentMode->red_mask = pScrn->mask.red;
+ currentMode->green_mask = pScrn->mask.green;
+ currentMode->blue_mask = pScrn->mask.blue;
+ currentMode->visualClass = (Bpp == 1) ? PseudoColor : TrueColor;
+ currentMode->viewportWidth = pMode->HDisplay;
+ currentMode->viewportHeight = pMode->VDisplay;
+ /* currentMode->xViewportStep = (3 - ps3v->BppShift); */
+ /* always 1 on ViRGE ? */
+ currentMode->xViewportStep = 1;
+ currentMode->yViewportStep = 1;
+ currentMode->viewportFlags = DGA_FLIP_RETRACE;
+ /* currentMode->offset = ps3v->YDstOrg * (pScrn->bitsPerPixel / 8);
+ * MGA, 0 for ViRGE */
+ currentMode->offset = 0;
+ /* currentMode->address = pMga->FbStart; MGA */
+ currentMode->address = ps3v->FBBase;
+/*cep*/
+ xf86ErrorFVerb(VERBLEV,
+ " S3VDGAInit firstone vpWid=%d, vpHgt=%d, Bpp=%d, mdbitsPP=%d\n",
+ currentMode->viewportWidth,
+ currentMode->viewportHeight,
+ Bpp,
+ currentMode->bitsPerPixel
+ );
+
+
+ if(oneMore) { /* first one is narrow width */
+ currentMode->bytesPerScanline = ((pMode->HDisplay * Bpp) + 3) & ~3L;
+ currentMode->imageWidth = pMode->HDisplay;
+ /* currentMode->imageHeight = pMga->FbUsableSize /
+ currentMode->bytesPerScanline;
+ MGA above */
+ currentMode->imageHeight = pMode->VDisplay;
+ currentMode->pixmapWidth = currentMode->imageWidth;
+ currentMode->pixmapHeight = currentMode->imageHeight;
+ currentMode->maxViewportX = currentMode->imageWidth -
+ currentMode->viewportWidth;
+ /* this might need to get clamped to some maximum */
+ currentMode->maxViewportY = currentMode->imageHeight -
+ currentMode->viewportHeight;
+ oneMore = FALSE;
+
+/*cep*/
+ xf86ErrorFVerb(VERBLEV,
+ " S3VDGAInit imgHgt=%d, ram=%d, bytesPerScanl=%d\n",
+ currentMode->imageHeight,
+ ps3v->videoRambytes,
+ currentMode->bytesPerScanline );
+
+ goto SECOND_PASS;
+ } else {
+ currentMode->bytesPerScanline =
+ ((pScrn->displayWidth * Bpp) + 3) & ~3L;
+ currentMode->imageWidth = pScrn->displayWidth;
+ /* currentMode->imageHeight = pMga->FbUsableSize /
+ currentMode->bytesPerScanline;
+ */
+ currentMode->imageHeight = ps3v->videoRambytes /
+ currentMode->bytesPerScanline;
+ currentMode->pixmapWidth = currentMode->imageWidth;
+ currentMode->pixmapHeight = currentMode->imageHeight;
+ currentMode->maxViewportX = currentMode->imageWidth -
+ currentMode->viewportWidth;
+ /* this might need to get clamped to some maximum */
+ currentMode->maxViewportY = currentMode->imageHeight -
+ currentMode->viewportHeight;
+ }
+
+ pMode = pMode->next;
+ if(pMode == firstMode)
+ break;
+ }
+
+ ps3v->numDGAModes = num;
+ ps3v->DGAModes = modes;
+
+ return DGAInit(pScreen, &S3V_DGAFuncs, modes, num);
+}
+
+
+static Bool
+S3V_SetMode(
+ ScrnInfoPtr pScrn,
+ DGAModePtr pMode
+){
+ static int OldDisplayWidth[MAXSCREENS];
+ int index = pScrn->pScreen->myNum;
+
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ if(!pMode) { /* restore the original mode */
+ /* put the ScreenParameters back */
+
+ pScrn->displayWidth = OldDisplayWidth[index];
+
+ S3VSwitchMode(index, pScrn->currentMode, 0);
+ ps3v->DGAactive = FALSE;
+ } else {
+ if(!ps3v->DGAactive) { /* save the old parameters */
+ OldDisplayWidth[index] = pScrn->displayWidth;
+
+ ps3v->DGAactive = TRUE;
+ }
+
+ pScrn->displayWidth = pMode->bytesPerScanline /
+ (pMode->bitsPerPixel >> 3);
+
+ S3VSwitchMode(index, pMode->mode, 0);
+ }
+
+ return TRUE;
+}
+
+
+
+static int
+S3V_GetViewport(
+ ScrnInfoPtr pScrn
+){
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ return ps3v->DGAViewportStatus;
+}
+
+static void
+S3V_SetViewport(
+ ScrnInfoPtr pScrn,
+ int x, int y,
+ int flags
+){
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ S3VAdjustFrame(pScrn->pScreen->myNum, x, y, flags);
+ ps3v->DGAViewportStatus = 0; /* MGAAdjustFrame loops until finished */
+}
+
+static void
+S3V_FillRect (
+ ScrnInfoPtr pScrn,
+ int x, int y, int w, int h,
+ unsigned long color
+){
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ if(ps3v->AccelInfoRec) {
+ (*ps3v->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
+ (*ps3v->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
+ SET_SYNC_FLAG(ps3v->AccelInfoRec);
+ }
+}
+
+static void
+S3V_BlitRect(
+ ScrnInfoPtr pScrn,
+ int srcx, int srcy,
+ int w, int h,
+ int dstx, int dsty
+){
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ if(ps3v->AccelInfoRec) {
+ int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
+ int ydir = (srcy < dsty) ? -1 : 1;
+
+ (*ps3v->AccelInfoRec->SetupForScreenToScreenCopy)(
+ pScrn, xdir, ydir, GXcopy, ~0, -1);
+ (*ps3v->AccelInfoRec->SubsequentScreenToScreenCopy)(
+ pScrn, srcx, srcy, dstx, dsty, w, h);
+ SET_SYNC_FLAG(ps3v->AccelInfoRec);
+ }
+}
+
+#if 0
+static void
+MGA_BlitTransRect(
+ ScrnInfoPtr pScrn,
+ int srcx, int srcy,
+ int w, int h,
+ int dstx, int dsty,
+ unsigned long color
+){
+ /* this one should be separate since the XAA function would
+ prohibit usage of ~0 as the key */
+}
+#endif
+
+static Bool
+S3V_OpenFramebuffer(
+ ScrnInfoPtr pScrn,
+ char **name,
+ unsigned char **mem,
+ int *size,
+ int *offset,
+ int *flags
+){
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ *name = NULL; /* no special device */
+ *mem = (unsigned char*)ps3v->PciInfo->memBase[0];
+ *size = ps3v->videoRambytes;
+ *offset = 0;
+ *flags = DGA_NEED_ROOT;
+
+ return TRUE;
+}
diff --git a/src/s3v_driver.c b/src/s3v_driver.c
new file mode 100644
index 0000000..b2d92fc
--- /dev/null
+++ b/src/s3v_driver.c
@@ -0,0 +1,3953 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/s3v_driver.c,v 1.93 2003/11/06 18:38:05 tsi Exp $ */
+
+/*
+Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the XFree86 Project shall not
+be used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the XFree86 Project.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86Resources.h"
+/* Needed by Resources Access Control (RAC) */
+#include "xf86RAC.h"
+
+#include "xf86DDC.h"
+#include "vbe.h"
+
+/* Needed by the Shadow Framebuffer */
+#include "shadowfb.h"
+
+/*
+ * s3v_driver.c
+ * Port to 4.0 design level
+ *
+ * S3 ViRGE driver
+ *
+ * 10/98 - 3/99 Kevin Brosius
+ * based largely on the SVGA ViRGE driver from 3.3.3x,
+ * Started 09/03/97 by S. Marineau
+ *
+ *
+ */
+
+
+ /* Most xf86 commons are already in s3v.h */
+#include "s3v.h"
+
+
+#include "globals.h"
+#define DPMS_SERVER
+#include <X11/extensions/dpms.h>
+
+#ifndef USE_INT10
+#define USE_INT10 0
+#endif
+
+/*
+ * Internals
+ */
+static void S3VEnableMmio(ScrnInfoPtr pScrn);
+static void S3VDisableMmio(ScrnInfoPtr pScrn);
+
+/*
+ * Forward definitions for the functions that make up the driver.
+ */
+
+/* Mandatory functions */
+static const OptionInfoRec * S3VAvailableOptions(int chipid, int busid);
+static void S3VIdentify(int flags);
+static Bool S3VProbe(DriverPtr drv, int flags);
+static Bool S3VPreInit(ScrnInfoPtr pScrn, int flags);
+
+static Bool S3VEnterVT(int scrnIndex, int flags);
+static void S3VLeaveVT(int scrnIndex, int flags);
+static void S3VSave (ScrnInfoPtr pScrn);
+static void S3VWriteMode (ScrnInfoPtr pScrn, vgaRegPtr, S3VRegPtr);
+
+static void S3VSaveSTREAMS(ScrnInfoPtr pScrn, unsigned int *streams);
+static void S3VRestoreSTREAMS(ScrnInfoPtr pScrn, unsigned int *streams);
+static void S3VDisableSTREAMS(ScrnInfoPtr pScrn);
+static Bool S3VScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv);
+static int S3VInternalScreenInit( int scrnIndex, ScreenPtr pScreen);
+static void S3VPrintRegs(ScrnInfoPtr);
+static ModeStatus S3VValidMode(int index, DisplayModePtr mode, Bool verbose, int flags);
+
+static Bool S3VMapMem(ScrnInfoPtr pScrn);
+static void S3VUnmapMem(ScrnInfoPtr pScrn);
+static Bool S3VModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
+static Bool S3VCloseScreen(int scrnIndex, ScreenPtr pScreen);
+static Bool S3VSaveScreen(ScreenPtr pScreen, int mode);
+static void S3VInitSTREAMS(ScrnInfoPtr pScrn, unsigned int *streams, DisplayModePtr mode);
+/* s3v.h - static void S3VAdjustFrame(int scrnIndex, int x, int y, int flags); */
+/* s3v.h - static Bool S3VSwitchMode(int scrnIndex, DisplayModePtr mode, int flags); */
+static void S3VLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies, LOCO *colors, VisualPtr pVisual);
+
+static void S3VDisplayPowerManagementSet(ScrnInfoPtr pScrn,
+ int PowerManagementMode,
+ int flags);
+static Bool S3Vddc1(int scrnIndex);
+static Bool S3Vddc2(int scrnIndex);
+
+static unsigned int S3Vddc1Read(ScrnInfoPtr pScrn);
+static void S3VProbeDDC(ScrnInfoPtr pScrn, int index);
+
+/*
+ * This is intentionally screen-independent. It indicates the binding
+ * choice made in the first PreInit.
+ */
+static int pix24bpp = 0;
+
+#define S3VIRGE_NAME "S3VIRGE"
+#define S3VIRGE_DRIVER_NAME "s3virge"
+#define S3VIRGE_VERSION_NAME "1.8.6"
+#define S3VIRGE_VERSION_MAJOR 1
+#define S3VIRGE_VERSION_MINOR 8
+#define S3VIRGE_PATCHLEVEL 6
+#define S3VIRGE_DRIVER_VERSION ((S3VIRGE_VERSION_MAJOR << 24) | \
+ (S3VIRGE_VERSION_MINOR << 16) | \
+ S3VIRGE_PATCHLEVEL)
+
+/*
+ * This contains the functions needed by the server after loading the
+ * driver module. It must be supplied, and gets added the driver list by
+ * the Module Setup funtion in the dynamic case. In the static case a
+ * reference to this is compiled in, and this requires that the name of
+ * this DriverRec be an upper-case version of the driver name.
+ */
+
+_X_EXPORT DriverRec S3VIRGE =
+{
+ S3VIRGE_DRIVER_VERSION,
+ S3VIRGE_DRIVER_NAME,
+ S3VIdentify,
+ S3VProbe,
+ S3VAvailableOptions,
+ NULL,
+ 0
+};
+
+
+/* Supported chipsets */
+static SymTabRec S3VChipsets[] = {
+ /* base (86C325) */
+ { PCI_CHIP_VIRGE, "virge" },
+ { PCI_CHIP_VIRGE, "86C325" },
+ /* VX (86C988) */
+ { PCI_CHIP_VIRGE_VX, "virge vx" },
+ { PCI_CHIP_VIRGE_VX, "86C988" },
+ /* DX (86C375) GX (86C385) */
+ { PCI_CHIP_VIRGE_DXGX, "virge dx" },
+ { PCI_CHIP_VIRGE_DXGX, "virge gx" },
+ { PCI_CHIP_VIRGE_DXGX, "86C375" },
+ { PCI_CHIP_VIRGE_DXGX, "86C385" },
+ /* GX2 (86C357) */
+ { PCI_CHIP_VIRGE_GX2, "virge gx2" },
+ { PCI_CHIP_VIRGE_GX2, "86C357" },
+ /* MX (86C260) */
+ { PCI_CHIP_VIRGE_MX, "virge mx" },
+ { PCI_CHIP_VIRGE_MX, "86C260" },
+ /* MX+ (86C280) */
+ { PCI_CHIP_VIRGE_MXP, "virge mx+" },
+ { PCI_CHIP_VIRGE_MXP, "86C280" },
+ /* Trio3D (86C365) */
+ { PCI_CHIP_Trio3D, "trio 3d" },
+ { PCI_CHIP_Trio3D, "86C365" },
+ /* Trio3D/2x (86C362/86C368) */
+ { PCI_CHIP_Trio3D_2X, "trio 3d/2x" },
+ { PCI_CHIP_Trio3D_2X, "86C362" },
+ { PCI_CHIP_Trio3D_2X, "86C368" },
+ {-1, NULL }
+};
+
+static PciChipsets S3VPciChipsets[] = {
+ /* numChipset, PciID, Resource */
+ { PCI_CHIP_VIRGE, PCI_CHIP_VIRGE, RES_SHARED_VGA },
+ { PCI_CHIP_VIRGE_VX, PCI_CHIP_VIRGE_VX, RES_SHARED_VGA },
+ { PCI_CHIP_VIRGE_DXGX, PCI_CHIP_VIRGE_DXGX, RES_SHARED_VGA },
+ { PCI_CHIP_VIRGE_GX2, PCI_CHIP_VIRGE_GX2, RES_SHARED_VGA },
+ { PCI_CHIP_VIRGE_MX, PCI_CHIP_VIRGE_MX, RES_SHARED_VGA },
+ { PCI_CHIP_VIRGE_MXP, PCI_CHIP_VIRGE_MXP, RES_SHARED_VGA },
+ { PCI_CHIP_Trio3D, PCI_CHIP_Trio3D, RES_SHARED_VGA },
+ { PCI_CHIP_Trio3D_2X, PCI_CHIP_Trio3D_2X, RES_SHARED_VGA },
+ { -1, -1, RES_UNDEFINED }
+};
+
+typedef enum {
+ OPTION_SLOW_EDODRAM,
+ OPTION_SLOW_DRAM,
+ OPTION_FAST_DRAM,
+ OPTION_FPM_VRAM,
+ OPTION_PCI_BURST,
+ OPTION_FIFO_CONSERV,
+ OPTION_FIFO_MODERATE,
+ OPTION_FIFO_AGGRESSIVE,
+ OPTION_PCI_RETRY,
+ OPTION_NOACCEL,
+ OPTION_ACCELMETHOD,
+ OPTION_EARLY_RAS_PRECHARGE,
+ OPTION_LATE_RAS_PRECHARGE,
+ OPTION_LCD_CENTER,
+ OPTION_LCDCLOCK,
+ OPTION_MCLK,
+ OPTION_REFCLK,
+ OPTION_SHOWCACHE,
+ OPTION_SWCURSOR,
+ OPTION_HWCURSOR,
+ OPTION_SHADOW_FB,
+ OPTION_ROTATE,
+ OPTION_FB_DRAW,
+ OPTION_MX_CR3A_FIX,
+ OPTION_XVIDEO
+} S3VOpts;
+
+static const OptionInfoRec S3VOptions[] =
+{
+ /* int token, const char* name, OptionValueType type,
+ ValueUnion value, Bool found.
+ */
+ { OPTION_SLOW_EDODRAM, "slow_edodram", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_SLOW_DRAM, "slow_dram", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_FAST_DRAM, "fast_dram", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_FPM_VRAM, "fpm_vram", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_PCI_BURST, "pci_burst", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_FIFO_CONSERV, "fifo_conservative", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_FIFO_MODERATE, "fifo_moderate", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_FIFO_AGGRESSIVE, "fifo_aggressive", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_PCI_RETRY, "pci_retry", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_ACCELMETHOD, "AccelMethod", OPTV_STRING, {0}, FALSE },
+ { OPTION_EARLY_RAS_PRECHARGE, "early_ras_precharge", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_LATE_RAS_PRECHARGE, "late_ras_precharge", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_LCD_CENTER, "lcd_center", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_LCDCLOCK, "set_lcdclk", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_MCLK, "set_mclk", OPTV_FREQ, {0}, FALSE },
+ { OPTION_REFCLK, "set_refclk", OPTV_FREQ, {0}, FALSE },
+ { OPTION_SHOWCACHE, "show_cache", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_HWCURSOR, "HWCursor", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_SWCURSOR, "SWCursor", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE },
+ { OPTION_FB_DRAW, "UseFB", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_MX_CR3A_FIX, "mxcr3afix", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_XVIDEO, "XVideo", OPTV_BOOLEAN, {0}, FALSE },
+ {-1, NULL, OPTV_NONE, {0}, FALSE}
+};
+
+
+/*
+ * Lists of symbols that may/may not be required by this driver.
+ * This allows the loader to know which ones to issue warnings for.
+ *
+ * Note that vgahwSymbols and xaaSymbols are referenced outside the
+ * XFree86LOADER define in later code, so are defined outside of that
+ * define here also.
+ */
+
+static const char *vgahwSymbols[] = {
+ "vgaHWBlankScreen",
+ "vgaHWCopyReg",
+ "vgaHWGetHWRec",
+ "vgaHWGetIOBase",
+ "vgaHWGetIndex",
+ "vgaHWInit",
+ "vgaHWLock",
+ "vgaHWMapMem",
+ "vgaHWProtect",
+ "vgaHWRestore",
+ "vgaHWSave",
+ "vgaHWSaveScreen",
+ "vgaHWSetMmioFuncs",
+ "vgaHWSetStdFuncs",
+ "vgaHWUnmapMem",
+ "vgaHWddc1SetSpeedWeak",
+ /* not used by ViRGE (at the moment :( ) */
+ /*
+ "vgaHWUnlock",
+ "vgaHWFreeHWRec",
+ */
+ NULL
+};
+
+static const char *xaaSymbols[] = {
+ "XAAGetCopyROP",
+ "XAAGetCopyROP_PM",
+ "XAADestroyInfoRec",
+ "XAACreateInfoRec",
+ "XAAHelpPatternROP",
+ "XAAHelpSolidROP",
+ "XAAInit",
+ NULL
+};
+
+static const char *exaSymbols[] = {
+ "exaDriverAlloc",
+ "exaDriverInit",
+ "exaDriverFini",
+ "exaOffscreenAlloc",
+ "exaOffscreenFree",
+ "exaGetPixmapOffset",
+ "exaGetPixmapPitch",
+ "exaGetPixmapSize",
+ NULL
+};
+
+static const char *ramdacSymbols[] = {
+ "xf86CreateCursorInfoRec",
+ "xf86InitCursor",
+#if 0
+ "xf86DestroyCursorInfoRec",
+#endif
+ NULL
+};
+
+static const char *ddcSymbols[] = {
+ "xf86PrintEDID",
+ "xf86DoEDID_DDC1",
+ "xf86DoEDID_DDC2",
+ "xf86SetDDCproperties",
+ NULL
+};
+
+static const char *i2cSymbols[] = {
+ "xf86CreateI2CBusRec",
+ "xf86I2CBusInit",
+ NULL
+};
+
+static const char *shadowSymbols[] = {
+ "ShadowFBInit",
+ NULL
+};
+
+static const char *vbeSymbols[] = {
+ "VBEInit",
+ "vbeDoEDID",
+ "vbeFree",
+ NULL
+};
+
+static const char *fbSymbols[] = {
+ "fbPictureInit",
+ "fbScreenInit",
+ NULL
+};
+
+#if USE_INT10
+static const char *int10Symbols[] = {
+ "xf86InitInt10",
+ "xf86FreeInt10",
+ NULL
+};
+#endif
+
+#ifdef XFree86LOADER
+
+static MODULESETUPPROTO(s3virgeSetup);
+
+static XF86ModuleVersionInfo S3VVersRec =
+{
+ "s3virge",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XORG_VERSION_CURRENT,
+ S3VIRGE_VERSION_MAJOR, S3VIRGE_VERSION_MINOR, S3VIRGE_PATCHLEVEL,
+ ABI_CLASS_VIDEODRV, /* This is a video driver */
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_VIDEODRV,
+ {0, 0, 0, 0}
+};
+
+
+/*
+ * This is the module init data for XFree86 modules.
+ *
+ * Its name has to be the driver name followed by ModuleData.
+ */
+_X_EXPORT XF86ModuleData s3virgeModuleData = {
+ &S3VVersRec,
+ s3virgeSetup,
+ NULL
+};
+
+static pointer
+s3virgeSetup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+ static Bool setupDone = FALSE;
+
+ if (!setupDone) {
+ setupDone = TRUE;
+ xf86AddDriver(&S3VIRGE, module, 0);
+
+ /*
+ * Modules that this driver always requires can be loaded here
+ * by calling LoadSubModule().
+ */
+
+ /*
+ * Tell the loader about symbols from other modules that this module
+ * might refer to.
+ */
+ LoaderRefSymLists(vgahwSymbols, xaaSymbols, exaSymbols, ramdacSymbols,
+ ddcSymbols, i2cSymbols,
+#if USE_INT10
+ int10Symbols,
+#endif
+ vbeSymbols, shadowSymbols, fbSymbols, NULL);
+
+ /*
+ * The return value must be non-NULL on success even though there
+ * is no TearDownProc.
+ */
+ return (pointer) 1;
+ } else {
+ if (errmaj)
+ *errmaj = LDR_ONCEONLY;
+ return NULL;
+ }
+}
+
+#endif /* XFree86LOADER */
+
+
+static unsigned char *find_bios_string(PCITAG Tag, int BIOSbase, char *match1, char *match2)
+{
+#define BIOS_BSIZE 1024
+#define BIOS_BASE 0xc0000
+
+ static unsigned char bios[BIOS_BSIZE];
+ static int init=0;
+ int i,j,l1,l2;
+
+ if (!init) {
+ init = 1;
+ if (xf86ReadDomainMemory(Tag, BIOSbase, BIOS_BSIZE, bios) != BIOS_BSIZE)
+ return NULL;
+ if ((bios[0] != 0x55) || (bios[1] != 0xaa))
+ return NULL;
+ }
+ if (match1 == NULL)
+ return NULL;
+
+ l1 = strlen(match1);
+ if (match2 != NULL)
+ l2 = strlen(match2);
+ else /* for compiler-warnings */
+ l2 = 0;
+
+ for (i=0; i<BIOS_BSIZE-l1; i++)
+ if (bios[i] == match1[0] && !memcmp(&bios[i],match1,l1)) {
+ if (match2 == NULL)
+ return &bios[i+l1];
+ else
+ for(j=i+l1; (j<BIOS_BSIZE-l2) && bios[j]; j++)
+ if (bios[j] == match2[0] && !memcmp(&bios[j],match2,l2))
+ return &bios[j+l2];
+ }
+
+ return NULL;
+}
+
+
+static Bool
+S3VGetRec(ScrnInfoPtr pScrn)
+{
+ PVERB5(" S3VGetRec\n");
+ /*
+ * Allocate an 'Chip'Rec, and hook it into pScrn->driverPrivate.
+ * pScrn->driverPrivate is initialised to NULL, so we can check if
+ * the allocation has already been done.
+ */
+ if (pScrn->driverPrivate != NULL)
+ return TRUE;
+
+ pScrn->driverPrivate = xnfcalloc(sizeof(S3VRec), 1);
+ /* Initialise it here when needed (or possible) */
+
+ return TRUE;
+}
+
+static void
+S3VFreeRec(ScrnInfoPtr pScrn)
+{
+ PVERB5(" S3VFreeRec\n");
+ if (pScrn->driverPrivate == NULL)
+ return;
+ xfree(pScrn->driverPrivate);
+ pScrn->driverPrivate = NULL;
+}
+
+static const OptionInfoRec *
+S3VAvailableOptions(int chipid, int busid)
+{
+ return S3VOptions;
+}
+
+static void
+S3VIdentify(int flags)
+{
+ PVERB5(" S3VIdentify\n");
+ xf86PrintChipsets(S3VIRGE_NAME,
+ "driver (version " S3VIRGE_VERSION_NAME ") for S3 ViRGE chipsets",
+ S3VChipsets);
+}
+
+
+static Bool
+S3VProbe(DriverPtr drv, int flags)
+{
+ int i;
+ GDevPtr *devSections;
+ int *usedChips;
+ int numDevSections;
+ int numUsed;
+ Bool foundScreen = FALSE;
+
+ PVERB5(" S3VProbe begin\n");
+
+ if ((numDevSections = xf86MatchDevice(S3VIRGE_DRIVER_NAME,
+ &devSections)) <= 0) {
+ /*
+ * There's no matching device section in the config file, so quit
+ * now.
+ */
+ return FALSE;
+ }
+ if (xf86GetPciVideoInfo() == NULL) {
+ return FALSE;
+ }
+
+ numUsed = xf86MatchPciInstances(S3VIRGE_NAME, PCI_S3_VENDOR_ID,
+ S3VChipsets, S3VPciChipsets, devSections,
+ numDevSections, drv, &usedChips);
+
+ /* Free it since we don't need that list after this */
+ xfree(devSections);
+ if (numUsed <= 0)
+ return FALSE;
+
+ if (flags & PROBE_DETECT)
+ foundScreen = TRUE;
+ else for (i = 0; i < numUsed; i++) {
+ /* Allocate a ScrnInfoRec and claim the slot */
+ ScrnInfoPtr pScrn = NULL;
+ if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i],
+ S3VPciChipsets,NULL,NULL, NULL,
+ NULL,NULL))) {
+ /* Fill in what we can of the ScrnInfoRec */
+ pScrn->driverVersion = S3VIRGE_DRIVER_VERSION;
+ pScrn->driverName = S3VIRGE_DRIVER_NAME;
+ pScrn->name = S3VIRGE_NAME;
+ pScrn->Probe = S3VProbe;
+ pScrn->PreInit = S3VPreInit;
+ pScrn->ScreenInit = S3VScreenInit;
+ pScrn->SwitchMode = S3VSwitchMode;
+ pScrn->AdjustFrame = S3VAdjustFrame;
+ pScrn->EnterVT = S3VEnterVT;
+ pScrn->LeaveVT = S3VLeaveVT;
+ pScrn->FreeScreen = NULL; /*S3VFreeScreen;*/
+ pScrn->ValidMode = S3VValidMode;
+ foundScreen = TRUE;
+ }
+ }
+ xfree(usedChips);
+ PVERB5(" S3VProbe end\n");
+ return foundScreen;
+}
+
+
+/* Mandatory */
+static Bool
+S3VPreInit(ScrnInfoPtr pScrn, int flags)
+{
+ EntityInfoPtr pEnt;
+ S3VPtr ps3v;
+ MessageType from;
+ int i;
+ double real;
+ ClockRangePtr clockRanges;
+ char *mod = NULL;
+ const char *reqSym = NULL;
+ char *s;
+
+ unsigned char config1, config2, m, n, n1, n2, cr66 = 0;
+ int mclk;
+
+ vgaHWPtr hwp;
+ int vgaCRIndex, vgaCRReg, vgaIOBase;
+
+ PVERB5(" S3VPreInit 1\n");
+
+ if (flags & PROBE_DETECT) {
+ S3VProbeDDC( pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index );
+ return TRUE;
+ }
+
+ /*
+ * Note: This function is only called once at server startup, and
+ * not at the start of each server generation. This means that
+ * only things that are persistent across server generations can
+ * be initialised here. xf86Screens[] is (pScrn is a pointer to one
+ * of these). Privates allocated using xf86AllocateScrnInfoPrivateIndex()
+ * are too, and should be used for data that must persist across
+ * server generations.
+ *
+ * Per-generation data should be allocated with
+ * AllocateScreenPrivateIndex() from the ScreenInit() function.
+ */
+
+ /* The vgahw module should be loaded here when needed */
+
+ if (!xf86LoadSubModule(pScrn, "vgahw"))
+ return FALSE;
+
+ xf86LoaderReqSymLists(vgahwSymbols, NULL);
+
+ /*
+ * Allocate a vgaHWRec
+ */
+ if (!vgaHWGetHWRec(pScrn))
+ return FALSE;
+
+
+ /* Set pScrn->monitor */
+ pScrn->monitor = pScrn->confScreen->monitor;
+
+ /*
+ * The first thing we should figure out is the depth, bpp, etc.
+ * We support both 24bpp and 32bpp layouts, so indicate that.
+ */
+ if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | Support32bppFb |
+ SupportConvert32to24 | PreferConvert32to24)) {
+ return FALSE;
+ } else {
+ /* Check that the returned depth is one we support */
+ switch (pScrn->depth) {
+ case 8:
+ case 15:
+ case 16:
+ case 24:
+ /* OK */
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Given depth (%d) is not supported by this driver\n",
+ pScrn->depth);
+ return FALSE;
+ }
+ }
+ xf86PrintDepthBpp(pScrn);
+
+ /* Get the depth24 pixmap format */
+ if (pScrn->depth == 24 && pix24bpp == 0)
+ pix24bpp = xf86GetBppFromDepth(pScrn, 24);
+
+ /*
+ * This must happen after pScrn->display has been set because
+ * xf86SetWeight references it.
+ */
+ if (pScrn->depth > 8) {
+ /* The defaults are OK for us */
+ rgb zeros = {0, 0, 0};
+
+ if (!xf86SetWeight(pScrn, zeros, zeros)) {
+ return FALSE;
+ } else {
+ /* XXX check that weight returned is supported */
+ ;
+ }
+ }
+
+ if (!xf86SetDefaultVisual(pScrn, -1)) {
+ return FALSE;
+ } else { /* editme - from MGA, does ViRGE? */
+ /* We don't currently support DirectColor at > 8bpp */
+ if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
+ " (%s) is not supported at depth %d\n",
+ xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
+ return FALSE;
+ }
+ }
+
+ /* We use a programmable clock */
+ pScrn->progClock = TRUE;
+
+ /* Allocate the S3VRec driverPrivate */
+ if (!S3VGetRec(pScrn)) {
+ return FALSE;
+ }
+ ps3v = S3VPTR(pScrn);
+
+ /* Collect all of the relevant option flags (fill in pScrn->options) */
+ xf86CollectOptions(pScrn, NULL);
+
+ /* Set the bits per RGB for 8bpp mode */
+ if (pScrn->depth == 8) {
+ /* ViRGE supports 6 RGB bits in depth 8 */
+ /* modes (with 256 entry LUT) */
+ pScrn->rgbBits = 6;
+ }
+
+ /* Process the options */
+ if (!(ps3v->Options = xalloc(sizeof(S3VOptions))))
+ return FALSE;
+ memcpy(ps3v->Options, S3VOptions, sizeof(S3VOptions));
+ xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ps3v->Options);
+
+
+ if (xf86ReturnOptValBool(ps3v->Options, OPTION_PCI_BURST, FALSE)) {
+ ps3v->pci_burst = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: pci_burst - PCI burst read enabled\n");
+ } else
+ ps3v->pci_burst = FALSE;
+ /* default */
+ ps3v->NoPCIRetry = 1;
+ /* Set option */
+ if (xf86ReturnOptValBool(ps3v->Options, OPTION_PCI_RETRY, FALSE)) {
+ if (xf86ReturnOptValBool(ps3v->Options, OPTION_PCI_BURST, FALSE)) {
+ ps3v->NoPCIRetry = 0;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: pci_retry\n");
+ }
+ else {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "\"pci_retry\" option requires \"pci_burst\".\n");
+ }
+ }
+ if (xf86IsOptionSet(ps3v->Options, OPTION_FIFO_CONSERV)) {
+ ps3v->fifo_conservative = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: fifo_conservative set\n");
+ } else
+ ps3v->fifo_conservative = FALSE;
+
+ if (xf86IsOptionSet(ps3v->Options, OPTION_FIFO_MODERATE)) {
+ ps3v->fifo_moderate = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: fifo_moderate set\n");
+ } else
+ ps3v->fifo_moderate = FALSE;
+
+ if (xf86IsOptionSet(ps3v->Options, OPTION_FIFO_AGGRESSIVE)) {
+ ps3v->fifo_aggressive = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: fifo_aggressive set\n");
+ } else
+ ps3v->fifo_aggressive = FALSE;
+
+ if (xf86IsOptionSet(ps3v->Options, OPTION_SLOW_EDODRAM)) {
+ ps3v->slow_edodram = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: slow_edodram set\n");
+ } else
+ ps3v->slow_edodram = FALSE;
+
+ if (xf86IsOptionSet(ps3v->Options, OPTION_SLOW_DRAM)) {
+ ps3v->slow_dram = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: slow_dram set\n");
+ } else
+ ps3v->slow_dram = FALSE;
+
+ if (xf86IsOptionSet(ps3v->Options, OPTION_FAST_DRAM)) {
+ ps3v->fast_dram = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: fast_dram set\n");
+ } else
+ ps3v->fast_dram = FALSE;
+
+ if (xf86IsOptionSet(ps3v->Options, OPTION_FPM_VRAM)) {
+ ps3v->fpm_vram = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: fpm_vram set\n");
+ } else
+ ps3v->fpm_vram = FALSE;
+
+ if (xf86ReturnOptValBool(ps3v->Options, OPTION_NOACCEL, FALSE)) {
+ ps3v->NoAccel = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: NoAccel - Acceleration disabled\n");
+ } else
+ ps3v->NoAccel = FALSE;
+
+ if (xf86ReturnOptValBool(ps3v->Options, OPTION_EARLY_RAS_PRECHARGE, FALSE)) {
+ ps3v->early_ras_precharge = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: early_ras_precharge set\n");
+ } else
+ ps3v->early_ras_precharge = FALSE;
+
+ if (xf86ReturnOptValBool(ps3v->Options, OPTION_LATE_RAS_PRECHARGE, FALSE)) {
+ ps3v->late_ras_precharge = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: late_ras_precharge set\n");
+ } else
+ ps3v->late_ras_precharge = FALSE;
+
+ if (xf86ReturnOptValBool(ps3v->Options, OPTION_LCD_CENTER, FALSE)) {
+ ps3v->lcd_center = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: lcd_center set\n");
+ } else
+ ps3v->lcd_center = FALSE;
+
+ if (xf86ReturnOptValBool(ps3v->Options, OPTION_SHOWCACHE, FALSE)) {
+ ps3v->ShowCache = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: show_cache set\n");
+ } else
+ ps3v->ShowCache = FALSE;
+
+ if (xf86GetOptValInteger(ps3v->Options, OPTION_LCDCLOCK, &ps3v->LCDClk)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: lcd_setclk set to %1.3f Mhz\n",
+ ps3v->LCDClk / 1000.0 );
+ } else
+ ps3v->LCDClk = 0;
+
+ if (xf86GetOptValFreq(ps3v->Options, OPTION_MCLK, OPTUNITS_MHZ, &real)) {
+ ps3v->MCLK = (int)(real * 1000.0);
+ if (ps3v->MCLK <= 100000) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: set_mclk set to %1.3f Mhz\n",
+ ps3v->MCLK / 1000.0 );
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING
+ , "Memory Clock value of %1.3f MHz is larger than limit of 100 MHz\n"
+ , ps3v->MCLK/1000.0);
+ ps3v->MCLK = 0;
+ }
+ } else
+ ps3v->MCLK = 0;
+
+ if (xf86GetOptValFreq(ps3v->Options, OPTION_REFCLK, OPTUNITS_MHZ, &real)) {
+ ps3v->REFCLK = (int)(real * 1000.0);
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: set_refclk set to %1.3f Mhz\n",
+ ps3v->REFCLK / 1000.0 );
+ } else
+ ps3v->REFCLK = 0;
+
+ from = X_DEFAULT;
+ ps3v->hwcursor = TRUE;
+ if (xf86GetOptValBool(ps3v->Options, OPTION_HWCURSOR, &ps3v->hwcursor))
+ from = X_CONFIG;
+ if (xf86ReturnOptValBool(ps3v->Options, OPTION_SWCURSOR, FALSE)) {
+ ps3v->hwcursor = FALSE;
+ from = X_CONFIG;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from, "Using %s Cursor\n",
+ ps3v->hwcursor ? "HW" : "SW");
+
+ if (xf86GetOptValBool(ps3v->Options, OPTION_SHADOW_FB,&ps3v->shadowFB))
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowFB %s.\n",
+ ps3v->shadowFB ? "enabled" : "disabled");
+
+ if ((s = xf86GetOptValString(ps3v->Options, OPTION_ROTATE))) {
+ if(!xf86NameCmp(s, "CW")) {
+ /* accel is disabled below for shadowFB */
+ ps3v->shadowFB = TRUE;
+ ps3v->rotate = 1;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Rotating screen clockwise - acceleration disabled\n");
+ } else if(!xf86NameCmp(s, "CCW")) {
+ ps3v->shadowFB = TRUE;
+ ps3v->rotate = -1;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen"
+ "counter clockwise - acceleration disabled\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid"
+ "value for Option \"Rotate\"\n", s);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Valid options are \"CW\" or \"CCW\"\n");
+ }
+ }
+
+ if (ps3v->shadowFB && !ps3v->NoAccel) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "HW acceleration not supported with \"shadowFB\".\n");
+ ps3v->NoAccel = TRUE;
+ }
+
+ if(!ps3v->NoAccel) {
+ from = X_DEFAULT;
+ char *strptr;
+ if((strptr = (char *)xf86GetOptValString(ps3v->Options, OPTION_ACCELMETHOD))) {
+ if(!xf86NameCmp(strptr,"XAA")) {
+ from = X_CONFIG;
+ ps3v->useEXA = FALSE;
+ } else if(!xf86NameCmp(strptr,"EXA")) {
+ from = X_CONFIG;
+ ps3v->useEXA = TRUE;
+ }
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration architecture\n",
+ ps3v->useEXA ? "EXA" : "XAA");
+ }
+
+ if (ps3v->rotate && ps3v->hwcursor) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "HW cursor not supported with \"rotate\".\n");
+ ps3v->hwcursor = FALSE;
+ }
+
+ ps3v->UseFB = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Using fb.\n");
+ if (xf86IsOptionSet(ps3v->Options, OPTION_FB_DRAW))
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "UseFB option is deprecated.\n");
+
+ if (xf86IsOptionSet(ps3v->Options, OPTION_MX_CR3A_FIX))
+ {
+ if (xf86GetOptValBool(ps3v->Options, OPTION_MX_CR3A_FIX ,&ps3v->mx_cr3a_fix))
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "%s mx_cr3a_fix.\n",
+ ps3v->mx_cr3a_fix ? "Enabling (default)" : "Disabling");
+ }
+ else
+ {
+ ps3v->mx_cr3a_fix = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "mx_cr3a_fix.\n");
+ }
+
+ /* Find the PCI slot for this screen */
+ /*
+ * XXX Ignoring the Type list for now. It might be needed when
+ * multiple cards are supported.
+ */
+ if (pScrn->numEntities > 1) {
+ S3VFreeRec(pScrn);
+ return FALSE;
+ }
+
+ pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
+
+ if (pEnt->resources) {
+ xfree(pEnt);
+ S3VFreeRec(pScrn);
+ return FALSE;
+ }
+
+#if USE_INT10
+ if (xf86LoadSubModule(pScrn, "int10")) {
+ xf86Int10InfoPtr pInt;
+ xf86LoaderReqSymLists(int10Symbols, NULL);
+#if 1
+ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n");
+ pInt = xf86InitInt10(pEnt->index);
+ xf86FreeInt10(pInt);
+#endif
+ }
+#endif
+ if (xf86LoadSubModule(pScrn, "vbe")) {
+ xf86LoaderReqSymLists(vbeSymbols, NULL);
+ ps3v->pVbe = VBEInit(NULL,pEnt->index);
+ }
+
+ ps3v->PciInfo = xf86GetPciInfoForEntity(pEnt->index);
+ xf86RegisterResources(pEnt->index,NULL,ResNone);
+ xf86SetOperatingState(resVgaIo, pEnt->index, ResUnusedOpr);
+ xf86SetOperatingState(resVgaMem, pEnt->index, ResDisableOpr);
+
+ /*
+ * Set the Chipset and ChipRev, allowing config file entries to
+ * override.
+ */
+ if (pEnt->device->chipset && *pEnt->device->chipset) {
+ pScrn->chipset = pEnt->device->chipset;
+ ps3v->Chipset = xf86StringToToken(S3VChipsets, pScrn->chipset);
+ from = X_CONFIG;
+ } else if (pEnt->device->chipID >= 0) {
+ ps3v->Chipset = pEnt->device->chipID;
+ pScrn->chipset = (char *)xf86TokenToString(S3VChipsets, ps3v->Chipset);
+ from = X_CONFIG;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
+ ps3v->Chipset);
+ } else {
+ from = X_PROBED;
+ ps3v->Chipset = ps3v->PciInfo->chipType;
+ pScrn->chipset = (char *)xf86TokenToString(S3VChipsets, ps3v->Chipset);
+ }
+
+ if (pEnt->device->chipRev >= 0) {
+ ps3v->ChipRev = pEnt->device->chipRev;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
+ ps3v->ChipRev);
+ } else {
+ ps3v->ChipRev = ps3v->PciInfo->chipRev;
+ }
+ xfree(pEnt);
+
+ /*
+ * This shouldn't happen because such problems should be caught in
+ * S3VProbe(), but check it just in case.
+ */
+ if (pScrn->chipset == NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "ChipID 0x%04X is not recognised\n", ps3v->Chipset);
+ vbeFree(ps3v->pVbe);
+ ps3v->pVbe = NULL;
+ return FALSE;
+ }
+ if (ps3v->Chipset < 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Chipset \"%s\" is not recognised\n", pScrn->chipset);
+ vbeFree(ps3v->pVbe);
+ ps3v->pVbe = NULL;
+ return FALSE;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset);
+
+ ps3v->PciTag = pciTag(ps3v->PciInfo->bus, ps3v->PciInfo->device,
+ ps3v->PciInfo->func);
+
+ /* Handle XVideo after we know chipset, so we can give an */
+ /* intelligent comment about support */
+ if (xf86IsOptionSet(ps3v->Options, OPTION_XVIDEO))
+ {
+ if(S3VQueryXvCapable(pScrn))
+ {
+ if (xf86GetOptValBool(ps3v->Options, OPTION_XVIDEO ,&ps3v->XVideo))
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "%s XVideo.\n",
+ ps3v->XVideo ? "Enabling (default)" : "Disabling");
+ }
+ else
+ xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "XVideo not supported.\n");
+ }
+ else
+ {
+ ps3v->XVideo = S3VQueryXvCapable(pScrn);
+ if(ps3v->XVideo)
+ xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "XVideo supported.\n");
+ else
+ xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "XVideo not supported.\n");
+ }
+
+
+ S3VMapMem(pScrn);
+ hwp = VGAHWPTR(pScrn);
+ vgaIOBase = hwp->IOBase;
+ vgaCRIndex = vgaIOBase + 4;
+ vgaCRReg = vgaIOBase + 5;
+
+ xf86ErrorFVerb(VERBLEV,
+ " S3VPreInit vgaCRIndex=%x, vgaIOBase=%x, MMIOBase=%p\n",
+ vgaCRIndex, vgaIOBase, hwp->MMIOBase );
+
+
+#if 0 /* Not needed in 4.0 flavors */
+ /* Unlock sys regs */
+ VGAOUT8(vgaCRIndex, 0x38);
+ VGAOUT8(vgaCRReg, 0x48);
+#endif
+
+ /* Next go on to detect amount of installed ram */
+
+ VGAOUT8(vgaCRIndex, 0x36); /* for register CR36 (CONFG_REG1),*/
+ config1 = VGAIN8(vgaCRReg); /* get amount of vram installed */
+
+ VGAOUT8(vgaCRIndex, 0x37); /* for register CR37 (CONFG_REG2),*/
+ config2 = VGAIN8(vgaCRReg); /* get amount of off-screen ram */
+
+ if (xf86LoadSubModule(pScrn, "ddc")) {
+ xf86MonPtr pMon = NULL;
+
+ xf86LoaderReqSymLists(ddcSymbols, NULL);
+ if ((ps3v->pVbe)
+ && ((pMon = xf86PrintEDID(vbeDoEDID(ps3v->pVbe, NULL))) != NULL))
+ xf86SetDDCproperties(pScrn,pMon);
+ else if (!S3Vddc1(pScrn->scrnIndex)) {
+ S3Vddc2(pScrn->scrnIndex);
+ }
+ }
+ if (ps3v->pVbe) {
+ vbeFree(ps3v->pVbe);
+ ps3v->pVbe = NULL;
+ }
+
+ /*
+ * If the driver can do gamma correction, it should call xf86SetGamma()
+ * here. (from MGA, no ViRGE gamma support yet, but needed for
+ * xf86HandleColormaps support.)
+ */
+ {
+ Gamma zeros = {0.0, 0.0, 0.0};
+
+ if (!xf86SetGamma(pScrn, zeros)) {
+ return FALSE;
+ }
+ }
+
+ /* And compute the amount of video memory and offscreen memory */
+ ps3v->MemOffScreen = 0;
+
+ if (!pScrn->videoRam) {
+ if (ps3v->Chipset == S3_ViRGE_VX) {
+ switch((config2 & 0x60) >> 5) {
+ case 1:
+ ps3v->MemOffScreen = 4 * 1024;
+ break;
+ case 2:
+ ps3v->MemOffScreen = 2 * 1024;
+ break;
+ }
+ switch ((config1 & 0x60) >> 5) {
+ case 0:
+ ps3v->videoRamKbytes = 2 * 1024;
+ break;
+ case 1:
+ ps3v->videoRamKbytes = 4 * 1024;
+ break;
+ case 2:
+ ps3v->videoRamKbytes = 6 * 1024;
+ break;
+ case 3:
+ ps3v->videoRamKbytes = 8 * 1024;
+ break;
+ }
+ ps3v->videoRamKbytes -= ps3v->MemOffScreen;
+ }
+ else if (S3_TRIO_3D_2X_SERIES(ps3v->Chipset)) {
+ switch((config1 & 0xE0) >> 5) {
+ case 0: /* 8MB -- only 4MB usable for display/cursor */
+ ps3v->videoRamKbytes = 4 * 1024;
+ ps3v->MemOffScreen = 4 * 1024;
+ break;
+ case 1: /* 32 bit interface -- yuck */
+ xf86ErrorFVerb(VERBLEV,
+ " found 32 bit interface for video memory -- yuck:(\n");
+ case 2:
+ ps3v->videoRamKbytes = 4 * 1024;
+ break;
+ case 6:
+ ps3v->videoRamKbytes = 2 * 1024;
+ break;
+ }
+ }
+ else if (S3_TRIO_3D_SERIES(ps3v->Chipset)) {
+ switch((config1 & 0xE0) >> 5) {
+ case 0:
+ case 2:
+ ps3v->videoRamKbytes = 4 * 1024;
+ break;
+ case 4:
+ ps3v->videoRamKbytes = 2 * 1024;
+ break;
+ }
+ }
+ else if (S3_ViRGE_GX2_SERIES(ps3v->Chipset) || S3_ViRGE_MX_SERIES(ps3v->Chipset)) {
+ switch((config1 & 0xC0) >> 6) {
+ case 1:
+ ps3v->videoRamKbytes = 4 * 1024;
+ break;
+ case 3:
+ ps3v->videoRamKbytes = 2 * 1024;
+ break;
+ }
+ }
+ else {
+ switch((config1 & 0xE0) >> 5) {
+ case 0:
+ ps3v->videoRamKbytes = 4 * 1024;
+ break;
+ case 4:
+ ps3v->videoRamKbytes = 2 * 1024;
+ break;
+ case 6:
+ ps3v->videoRamKbytes = 1 * 1024;
+ break;
+ }
+ }
+ /* And save a byte value also */
+ ps3v->videoRambytes = ps3v->videoRamKbytes * 1024;
+ /* Make sure the screen also */
+ /* has correct videoRam setting */
+ pScrn->videoRam = ps3v->videoRamKbytes;
+
+ if (ps3v->MemOffScreen)
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "videoram: %dk (plus %dk off-screen)\n",
+ ps3v->videoRamKbytes, ps3v->MemOffScreen);
+ else
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "videoram: %dk\n",
+ ps3v->videoRamKbytes);
+ } else {
+ /* Note: if ram is not probed then */
+ /* ps3v->videoRamKbytes will not be init'd */
+ /* should we? can do it here... */
+
+
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "videoram: %dk\n",
+ ps3v->videoRamKbytes);
+ }
+
+ /* reset S3 graphics engine to avoid memory corruption */
+ if (ps3v->Chipset != S3_ViRGE_VX) {
+ VGAOUT8(vgaCRIndex, 0x66);
+ cr66 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRReg, cr66 | 0x02);
+ usleep(10000); /* wait a little bit... */
+ }
+
+ /*
+ * There was a lot of plainly wrong code here. pScrn->clock is just a list
+ * of supported _dotclocks_ used when you don't have a programmable clock.
+ *
+ * S3V and Savage seem to think that this is the max ramdac speed. This
+ * driver just ignores the whole mess done before and sets
+ * clockRange->maxClock differently slightly later.
+ *
+ * In order to not ditch information, here is a table of what the dacspeeds
+ * "were" before the cleanup.
+ *
+ * Chipset ### >= 24bpp ### lower
+ *
+ * S3_ViRGE_VX 135000 220000
+ * S3_TRIO_3D_2X_SERIES 135000 230000
+ * S3_ViRGE_DXGX 135000 170000
+ * S3_ViRGE_GX2_SERIES 135000 170000
+ * S3_ViRGE_MX_SERIES 100000 135000
+ *
+ * Others devices get:
+ * > 24bpp: 57000
+ * = 24bpp: 95000
+ * < 24bpp: 135000
+ *
+ * Special case is the MELCO BIOS:
+ * > 24bpp: 83500
+ * = 24bpp: 111500
+ * > 8bpp: 162500
+ * <= 8bpp: 191500
+ */
+
+ if (find_bios_string(ps3v->PciTag, BIOS_BASE, "S3 86C325",
+ "MELCO WGP-VG VIDEO BIOS") != NULL) {
+ if (xf86GetVerbosity())
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "MELCO BIOS found\n");
+ if (ps3v->MCLK <= 0)
+ ps3v->MCLK = 74000;
+ }
+
+ if (ps3v->Chipset != S3_ViRGE_VX) {
+ VGAOUT8(vgaCRIndex, 0x66);
+ VGAOUT8(vgaCRReg, cr66 & ~0x02); /* clear reset flag */
+ usleep(10000); /* wait a little bit... */
+ }
+
+ /* Detect current MCLK and print it for user */
+ VGAOUT8(0x3c4, 0x08);
+ VGAOUT8(0x3c5, 0x06);
+ VGAOUT8(0x3c4, 0x10);
+ n = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x11);
+ m = VGAIN8(0x3c5);
+ m &= 0x7f;
+ n1 = n & 0x1f;
+ n2 = (n>>5) & 0x03;
+ mclk = ((1431818 * (m+2)) / (n1+2) / (1 << n2) + 50) / 100;
+ if (S3_ViRGE_MX_SERIES(ps3v->Chipset)) {
+ MessageType is_probed = X_PROBED;
+ /*
+ * try to figure out which reference clock is used:
+ * Toshiba Tecra 5x0/7x0 seems to use 28.636 MHz
+ * Compaq Armada 7x00 uses 14.318 MHz
+ */
+ if (find_bios_string(ps3v->PciTag, BIOS_BASE, "COMPAQ M5 BIOS", NULL) != NULL) {
+ if (xf86GetVerbosity())
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "COMPAQ M5 BIOS found\n");
+ /* ps3v->refclk_fact = 1.0; */
+ }
+ else if (find_bios_string(ps3v->PciTag, BIOS_BASE, "TOSHIBA Video BIOS", NULL) != NULL) {
+ if (xf86GetVerbosity())
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "TOSHIBA Video BIOS found\n");
+ /* ps3v->refclk_fact = 2.0; */
+ }
+ /* else */ { /* always use guessed value... */
+ if (mclk > 60000)
+ ps3v->refclk_fact = 1.0;
+ else
+ ps3v->refclk_fact = 2.0; /* don't know why ??? */
+ }
+ if (ps3v->REFCLK != 0) {
+ ps3v->refclk_fact = ps3v->REFCLK / 14318.0;
+ is_probed = X_CONFIG;
+ }
+ else
+ ps3v->REFCLK = (int)(14318.18 * ps3v->refclk_fact);
+
+ mclk = (int)(mclk * ps3v->refclk_fact);
+ xf86DrvMsg(pScrn->scrnIndex, is_probed, "assuming RefCLK value of %1.3f MHz\n",
+ ps3v->REFCLK / 1000.0);
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected current MCLK value of %1.3f MHz\n",
+ mclk / 1000.0);
+
+ if (S3_ViRGE_MX_SERIES(ps3v->Chipset) && xf86GetVerbosity()) {
+ int lcdclk, h_lcd, v_lcd;
+ if (ps3v->LCDClk) {
+ lcdclk = ps3v->LCDClk;
+ } else {
+ unsigned char sr12, sr13, sr29;
+ VGAOUT8(0x3c4, 0x12);
+ sr12 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x13);
+ sr13 = VGAIN8(0x3c5) & 0x7f;
+ VGAOUT8(0x3c4, 0x29);
+ sr29 = VGAIN8(0x3c5);
+ n1 = sr12 & 0x1f;
+ n2 = ((sr12>>6) & 0x03) | ((sr29 & 0x01) << 2);
+ lcdclk = ((int)(ps3v->refclk_fact * 1431818 * (sr13+2)) / (n1+2) / (1 << n2) + 50) / 100;
+ }
+ VGAOUT8(0x3c4, 0x61);
+ h_lcd = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x66);
+ h_lcd |= ((VGAIN8(0x3c5) & 0x02) << 7);
+ h_lcd = (h_lcd+1) * 8;
+ VGAOUT8(0x3c4, 0x69);
+ v_lcd = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x6e);
+ v_lcd |= ((VGAIN8(0x3c5) & 0x70) << 4);
+ v_lcd++;
+ xf86DrvMsg(pScrn->scrnIndex
+ , ps3v->LCDClk ? X_CONFIG : X_PROBED
+ , "LCD size %dx%d, clock %1.3f MHz\n"
+ , h_lcd, v_lcd
+ , lcdclk / 1000.0);
+ }
+
+ S3VDisableMmio(pScrn);
+ S3VUnmapMem(pScrn);
+
+ /* And finally set various possible option flags */
+
+ ps3v->bankedMono = FALSE;
+
+
+#if 0
+ vga256InfoRec.directMode = XF86DGADirectPresent;
+#endif
+
+ /*
+ * xf86ValidateModes will check that the mode HTotal and VTotal values
+ * don't exceed the chipset's limit if pScrn->maxHValue and
+ * pScrn->maxVValue are set.
+ */
+
+ /* todo - The virge limit is 2048 vertical & horizontal */
+ /* pixels, not clock register settings. */
+ /* true for all ViRGE? */
+ pScrn->maxHValue = 2048;
+ pScrn->maxVValue = 2048;
+
+ /* Lower depths default to config file */
+ pScrn->virtualX = pScrn->display->virtualX;
+ /* Adjust the virtualX to meet ViRGE hardware */
+ /* limits for depth 24, bpp 24 & 32. This is */
+ /* mostly for 32 bpp as 1024x768 is one pixel */
+ /* larger than supported. */
+ if (pScrn->depth == 24)
+ if ( ((pScrn->bitsPerPixel/8) * pScrn->display->virtualX) > 4095 ) {
+ pScrn->virtualX = 4095 / (pScrn->bitsPerPixel / 8);
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Virtual width adjusted, max for this depth & bpp is %d.\n",
+ pScrn->virtualX );
+ }
+
+ /*
+ * Setup the ClockRanges, which describe what clock ranges are available,
+ * and what sort of modes they can be used for.
+ */
+ clockRanges = xnfcalloc(sizeof(ClockRange), 1);
+ clockRanges->next = NULL;
+ clockRanges->minClock = 10000;
+ if (ps3v->Chipset == S3_ViRGE_VX )
+ clockRanges->maxClock = 440000;
+ else
+ clockRanges->maxClock = 270000;
+ clockRanges->clockIndex = -1; /* programmable */
+ clockRanges->interlaceAllowed = TRUE; /* yes, S3V SVGA 3.3.2 */
+ clockRanges->doubleScanAllowed = TRUE;
+
+ /* Screen pointer */
+ i = xf86ValidateModes(pScrn,
+ /* Available monitor modes */
+ /* (DisplayModePtr availModes) */
+ pScrn->monitor->Modes,
+ /* req mode names for screen */
+ /* (char **modesNames) */
+ pScrn->display->modes,
+ /* list of clock ranges allowed */
+ /* (ClockRangePtr clockRanges) */
+ clockRanges,
+ /* list of driver line pitches, */
+ /* supply or NULL and use min/ */
+ /* max below */
+ /* (int *linePitches) */
+ NULL,
+ /* min lin pitch (width) */
+ /* (int minPitch) */
+ 256,
+ /* max line pitch (width) */
+ /* (int maxPitch) */
+ 2048,
+ /* bits of granularity for line */
+ /* pitch (width) above, reguired*/
+ /* (int pitchInc) */
+ pScrn->bitsPerPixel,
+ /* min virt height, 0 no limit */
+ /* (int minHeight) */
+ 128,
+ /* max virt height, 0 no limit */
+ /* (int maxHeight) */
+ 2048,
+ /* force virtX, 0 for auto */
+ /* (int VirtualX) */
+ /* value is adjusted above for */
+ /* hardware limits */
+ pScrn->virtualX,
+ /* force virtY, 0 for auto */
+ /* (int VirtualY) */
+ pScrn->display->virtualY,
+ /* size (bytes) of aper used to */
+ /* access video memory */
+ /* (unsigned long apertureSize) */
+ ps3v->videoRambytes,
+ /* how to pick mode */
+ /* (LookupModeFlags strategy) */
+ LOOKUP_BEST_REFRESH);
+
+ if (i == -1) {
+ S3VFreeRec(pScrn);
+ return FALSE;
+ }
+ /* Prune the modes marked as invalid */
+ xf86PruneDriverModes(pScrn);
+
+ if (i == 0 || pScrn->modes == NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
+ S3VFreeRec(pScrn);
+ return FALSE;
+ }
+
+ xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
+ /*xf86SetCrtcForModes(pScrn, 0);*/
+
+ /* Set the current mode to the first in the list */
+ pScrn->currentMode = pScrn->modes;
+
+ /* Print the list of modes being used */
+ xf86PrintModes(pScrn);
+
+ /* Set display resolution */
+ xf86SetDpi(pScrn, 0, 0);
+ /* When running the STREAMS processor */
+ /* the max. stride is limited to 4096-1 */
+ /* so this is the virtualX limit. */
+ /* STREAMS is needed for 24 & 32 bpp, */
+ /* (all depth 24 modes) */
+ /* This should never happen... we */
+ /* checked it before ValidateModes */
+ if ( ((pScrn->depth == 24) || (pScrn->depth == 16)) &&
+ ((pScrn->bitsPerPixel/8) * pScrn->virtualX > 4095) ) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Virtual width to large for ViRGE\n");
+ S3VFreeRec(pScrn);
+ return FALSE;
+ }
+
+ /* Load bpp-specific modules */
+ if( ps3v->UseFB )
+ {
+ if( xf86LoadSubModule(pScrn, "fb") == NULL )
+ {
+ S3VFreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(fbSymbols, NULL);
+ }
+
+ /* Load XAA if needed */
+ if (!ps3v->NoAccel || ps3v->hwcursor ) {
+ char *modName = NULL;
+ const char **symNames = NULL;
+
+ if (ps3v->useEXA) {
+ modName = "exa";
+ symNames = exaSymbols;
+ XF86ModReqInfo req;
+ int errmaj, errmin;
+ memset(&req, 0, sizeof(req));
+ req.majorversion = 2;
+ req.minorversion = 0;
+
+ if ( !LoadSubModule(pScrn->module, modName,
+ NULL, NULL, NULL, &req, &errmaj, &errmin) ) {
+ LoaderErrorMsg(NULL, modName, errmaj, errmin);
+ S3VFreeRec(pScrn);
+ return FALSE;
+ }
+ } else {
+ modName = "xaa";
+ symNames = xaaSymbols;
+ if ( !xf86LoadSubModule(pScrn, "xaa") ) {
+ S3VFreeRec(pScrn);
+ return FALSE;
+ }
+ }
+
+ xf86LoaderReqSymLists(symNames, NULL);
+ }
+
+ /* Load ramdac if needed */
+ if (ps3v->hwcursor) {
+ if (!xf86LoadSubModule(pScrn, "ramdac")) {
+ S3VFreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(ramdacSymbols, NULL);
+ }
+
+ if (ps3v->shadowFB) {
+ if (!xf86LoadSubModule(pScrn, "shadowfb")) {
+ S3VFreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(shadowSymbols, NULL);
+ }
+
+ /* Setup WAITFIFO() for accel and ModeInit() */
+ /* Needs to be done prior to first ModeInit call */
+ /* and any accel activity. */
+ switch(ps3v->Chipset)
+ {
+ /* GX2_SERIES chips, GX2 & TRIO_3D_2X */
+ case S3_ViRGE_GX2:
+ case S3_TRIO_3D_2X:
+ ps3v->pWaitFifo = S3VWaitFifoGX2;
+ ps3v->pWaitCmd = S3VWaitCmdGX2;
+ break;
+ case S3_ViRGE:
+ case S3_ViRGE_VX:
+ default:
+ ps3v->pWaitFifo = S3VWaitFifoMain;
+ /* Do nothing... */
+ ps3v->pWaitCmd = S3VWaitDummy;
+ break;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * This is called when VT switching back to the X server. Its job is
+ * to reinitialise the video mode.
+ *
+ * We may wish to unmap video/MMIO memory too.
+ */
+
+
+/* Mandatory */
+static Bool
+S3VEnterVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+/* ScreenPtr pScreen = xf86Screens[scrnIndex]->pScreen; */
+ /*vgaHWPtr hwp = VGAHWPTR(pScrn);*/
+
+ PVERB5(" S3VEnterVT\n");
+ /*vgaHWUnlockMMIO(hwp);*/
+ /* Enable MMIO and map memory */
+#ifdef unmap_always
+ S3VMapMem(pScrn);
+#endif
+ S3VEnableMmio(pScrn);
+
+ S3VSave(pScrn);
+ return S3VModeInit(pScrn, pScrn->currentMode);
+}
+
+
+/*
+ * This is called when VT switching away from the X server. Its job is
+ * to restore the previous (text) mode.
+ *
+ * We may wish to remap video/MMIO memory too.
+ *
+ */
+
+/* Mandatory */
+static void
+S3VLeaveVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ S3VPtr ps3v = S3VPTR(pScrn);
+ vgaRegPtr vgaSavePtr = &hwp->SavedReg;
+ S3VRegPtr S3VSavePtr = &ps3v->SavedReg;
+
+ PVERB5(" S3VLeaveVT\n");
+ /* Like S3VRestore, but uses passed */
+ /* mode registers. */
+ S3VWriteMode(pScrn, vgaSavePtr, S3VSavePtr);
+ /* Restore standard register access */
+ /* and unmap memory. */
+ S3VDisableMmio(pScrn);
+#ifdef unmap_always
+ S3VUnmapMem(pScrn);
+#endif
+ /*vgaHWLockMMIO(hwp);*/
+
+}
+
+
+/*
+ * This function performs the inverse of the restore function: It saves all
+ * the standard and extended registers that we are going to modify to set
+ * up a video mode. Again, we also save the STREAMS context if it is needed.
+ *
+ * prototype
+ * void ChipSave(ScrnInfoPtr pScrn)
+ *
+ */
+
+static void
+S3VSave (ScrnInfoPtr pScrn)
+{
+ unsigned char cr3a, cr66;
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ vgaRegPtr vgaSavePtr = &hwp->SavedReg;
+ S3VPtr ps3v = S3VPTR(pScrn);
+ S3VRegPtr save = &ps3v->SavedReg;
+ int vgaCRIndex, vgaCRReg, vgaIOBase;
+ vgaIOBase = hwp->IOBase;
+ vgaCRIndex = 0;
+
+ vgaCRReg = 0;
+
+ vgaCRReg = vgaIOBase + 5;
+ vgaCRIndex = vgaIOBase + 4;
+
+ PVERB5(" S3VSave\n");
+
+ /*
+ * This function will handle creating the data structure and filling
+ * in the generic VGA portion.
+ */
+
+ VGAOUT8(vgaCRIndex, 0x66);
+ cr66 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRReg, cr66 | 0x80);
+ VGAOUT8(vgaCRIndex, 0x3a);
+ cr3a = VGAIN8(vgaCRReg);
+ save->CR3A = cr3a;
+
+ VGAOUT8(vgaCRReg, cr3a | 0x80);
+
+ /* VGA_SR_MODE saves mode info only, no fonts, no colormap */
+ /* Save all for primary, anything */
+ /* for secondary cards?, do MODE */
+ /* for the moment. */
+ if (xf86IsPrimaryPci(ps3v->PciInfo))
+ vgaHWSave(pScrn, vgaSavePtr, VGA_SR_ALL);
+ else
+ vgaHWSave(pScrn, vgaSavePtr, VGA_SR_MODE);
+
+ VGAOUT8(vgaCRIndex, 0x66);
+ VGAOUT8(vgaCRReg, cr66);
+ VGAOUT8(vgaCRIndex, 0x3a);
+ VGAOUT8(vgaCRReg, cr3a);
+
+ /* First unlock extended sequencer regs */
+ VGAOUT8(0x3c4, 0x08);
+ save->SR08 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c5, 0x06);
+
+ /* Now we save all the s3 extended regs we need */
+ VGAOUT8(vgaCRIndex, 0x31);
+ save->CR31 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x34);
+ save->CR34 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x36);
+ save->CR36 = VGAIN8(vgaCRReg);
+
+ /* workaround cr3a corruption */
+ if( !(ps3v->mx_cr3a_fix))
+ {
+ VGAOUT8(vgaCRIndex, 0x3a);
+ save->CR3A = VGAIN8(vgaCRReg);
+ }
+
+ if (!S3_TRIO_3D_SERIES(ps3v->Chipset)) {
+ VGAOUT8(vgaCRIndex, 0x40);
+ save->CR40 = VGAIN8(vgaCRReg);
+ }
+ if (S3_ViRGE_MX_SERIES(ps3v->Chipset)) {
+ VGAOUT8(vgaCRIndex, 0x41);
+ save->CR41 = VGAIN8(vgaCRReg);
+ }
+ VGAOUT8(vgaCRIndex, 0x42);
+ save->CR42 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x45);
+ save->CR45 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x51);
+ save->CR51 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x53);
+ save->CR53 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x54);
+ save->CR54 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x55);
+ save->CR55 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x58);
+ save->CR58 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x63);
+ save->CR63 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x66);
+ save->CR66 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x67);
+ save->CR67 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x68);
+ save->CR68 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x69);
+ save->CR69 = VGAIN8(vgaCRReg);
+
+ VGAOUT8(vgaCRIndex, 0x33);
+ save->CR33 = VGAIN8(vgaCRReg);
+ if (S3_TRIO_3D_2X_SERIES(ps3v->Chipset) || S3_ViRGE_GX2_SERIES(ps3v->Chipset)
+ /* MXTESTME */ || S3_ViRGE_MX_SERIES(ps3v->Chipset) )
+ {
+ VGAOUT8(vgaCRIndex, 0x85);
+ save->CR85 = VGAIN8(vgaCRReg);
+ }
+ if (ps3v->Chipset == S3_ViRGE_DXGX) {
+ VGAOUT8(vgaCRIndex, 0x86);
+ save->CR86 = VGAIN8(vgaCRReg);
+ }
+ if ((ps3v->Chipset == S3_ViRGE_GX2) ||
+ S3_ViRGE_MX_SERIES(ps3v->Chipset) ) {
+ VGAOUT8(vgaCRIndex, 0x7B);
+ save->CR7B = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x7D);
+ save->CR7D = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x87);
+ save->CR87 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x92);
+ save->CR92 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x93);
+ save->CR93 = VGAIN8(vgaCRReg);
+ }
+ if (ps3v->Chipset == S3_ViRGE_DXGX || S3_ViRGE_GX2_SERIES(ps3v->Chipset) ||
+ S3_ViRGE_MX_SERIES(ps3v->Chipset) || S3_TRIO_3D_SERIES(ps3v->Chipset)) {
+ VGAOUT8(vgaCRIndex, 0x90);
+ save->CR90 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x91);
+ save->CR91 = VGAIN8(vgaCRReg);
+ }
+
+ /* Extended mode timings regs */
+
+ VGAOUT8(vgaCRIndex, 0x3b);
+ save->CR3B = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x3c);
+ save->CR3C = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x43);
+ save->CR43 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x5d);
+ save->CR5D = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x5e);
+ save->CR5E = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x65);
+ save->CR65 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x6d);
+ save->CR6D = VGAIN8(vgaCRReg);
+
+
+ /* Save sequencer extended regs for DCLK PLL programming */
+
+ VGAOUT8(0x3c4, 0x10);
+ save->SR10 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x11);
+ save->SR11 = VGAIN8(0x3c5);
+
+ VGAOUT8(0x3c4, 0x12);
+ save->SR12 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x13);
+ save->SR13 = VGAIN8(0x3c5);
+ if (S3_ViRGE_GX2_SERIES(ps3v->Chipset) || S3_ViRGE_MX_SERIES(ps3v->Chipset)) {
+ VGAOUT8(0x3c4, 0x29);
+ save->SR29 = VGAIN8(0x3c5);
+ }
+ /* SR 54,55,56,57 undocumented for GX2. Was this supposed to be CR? */
+ /* (These used to be part of the above if() */
+ if (S3_ViRGE_MX_SERIES(ps3v->Chipset)) {
+ VGAOUT8(0x3c4, 0x54);
+ save->SR54 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x55);
+ save->SR55 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x56);
+ save->SR56 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x57);
+ save->SR57 = VGAIN8(0x3c5);
+ }
+
+ VGAOUT8(0x3c4, 0x15);
+ save->SR15 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x18);
+ save->SR18 = VGAIN8(0x3c5);
+ if (S3_TRIO_3D_SERIES(ps3v->Chipset)) {
+ VGAOUT8(0x3c4, 0x0a);
+ save->SR0A = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x0F);
+ save->SR0F = VGAIN8(0x3c5);
+ }
+
+ VGAOUT8(vgaCRIndex, 0x66);
+ cr66 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRReg, cr66 | 0x80);
+ VGAOUT8(vgaCRIndex, 0x3a);
+ cr3a = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRReg, cr3a | 0x80);
+
+ /* And if streams is to be used, save that as well */
+
+ if(ps3v->NeedSTREAMS) {
+ S3VSaveSTREAMS(pScrn, save->STREAMS);
+ }
+
+ /* Now save Memory Interface Unit registers */
+ if( S3_ViRGE_GX2_SERIES(ps3v->Chipset)
+ /* MXTESTME */ || S3_ViRGE_MX_SERIES(ps3v->Chipset) )
+ {
+ /* No MMPR regs on MX & GX2 */
+ }
+ else
+ {
+ save->MMPR0 = INREG(FIFO_CONTROL_REG);
+ save->MMPR1 = INREG(MIU_CONTROL_REG);
+ save->MMPR2 = INREG(STREAMS_TIMEOUT_REG);
+ save->MMPR3 = INREG(MISC_TIMEOUT_REG);
+ }
+
+ if (xf86GetVerbosity() > 1) {
+ /* Debug */
+ /* Which chipsets? */
+ if (
+ /* virge */
+ ps3v->Chipset == S3_ViRGE ||
+ /* VX */
+ S3_ViRGE_VX_SERIES(ps3v->Chipset) ||
+ /* DX & GX */
+ ps3v->Chipset == S3_ViRGE_DXGX ||
+ /* GX2 & Trio3D_2X */
+ /* S3_ViRGE_GX2_SERIES(ps3v->Chipset) || */
+ /* Trio3D_2X */
+ /* S3_TRIO_3D_2X_SERIES(ps3v->Chipset) */
+ /* MX & MX+ */
+ /* S3_ViRGE_MX_SERIES(ps3v->Chipset) || */
+ /* MX+ only */
+ /* S3_ViRGE_MXP_SERIES(ps3v->Chipset) || */
+ /* Trio3D */
+ ps3v->Chipset == S3_TRIO_3D
+ )
+ {
+
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
+ "MMPR regs: %08lx %08lx %08lx %08lx\n",
+ (unsigned long)INREG(FIFO_CONTROL_REG),
+ (unsigned long)INREG(MIU_CONTROL_REG),
+ (unsigned long)INREG(STREAMS_TIMEOUT_REG),
+ (unsigned long)INREG(MISC_TIMEOUT_REG));
+ }
+
+ PVERB5("\n\nViRGE driver: saved current video mode. Register dump:\n\n");
+ }
+
+ VGAOUT8(vgaCRIndex, 0x3a);
+ VGAOUT8(vgaCRReg, cr3a);
+ VGAOUT8(vgaCRIndex, 0x66);
+ VGAOUT8(vgaCRReg, cr66);
+ /* Dup the VGA & S3V state to the */
+ /* new mode state, but only first time. */
+ if( !ps3v->ModeStructInit ) {
+ /* XXX Should check the return value of vgaHWCopyReg() */
+ vgaHWCopyReg( &hwp->ModeReg, vgaSavePtr );
+ memcpy( &ps3v->ModeReg, save, sizeof(S3VRegRec) );
+ ps3v->ModeStructInit = TRUE;
+ }
+
+ if (xf86GetVerbosity() > 1) S3VPrintRegs(pScrn);
+
+ return;
+}
+
+
+/* This function saves the STREAMS registers to our private structure */
+
+static void
+S3VSaveSTREAMS(ScrnInfoPtr pScrn, unsigned int *streams)
+{
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ streams[0] = INREG(PSTREAM_CONTROL_REG);
+ streams[1] = INREG(COL_CHROMA_KEY_CONTROL_REG);
+ streams[2] = INREG(SSTREAM_CONTROL_REG);
+ streams[3] = INREG(CHROMA_KEY_UPPER_BOUND_REG);
+ streams[4] = INREG(SSTREAM_STRETCH_REG);
+ streams[5] = INREG(BLEND_CONTROL_REG);
+ streams[6] = INREG(PSTREAM_FBADDR0_REG);
+ streams[7] = INREG(PSTREAM_FBADDR1_REG);
+ streams[8] = INREG(PSTREAM_STRIDE_REG);
+ streams[9] = INREG(DOUBLE_BUFFER_REG);
+ streams[10] = INREG(SSTREAM_FBADDR0_REG);
+ streams[11] = INREG(SSTREAM_FBADDR1_REG);
+ streams[12] = INREG(SSTREAM_STRIDE_REG);
+ streams[13] = INREG(OPAQUE_OVERLAY_CONTROL_REG);
+ streams[14] = INREG(K1_VSCALE_REG);
+ streams[15] = INREG(K2_VSCALE_REG);
+ streams[16] = INREG(DDA_VERT_REG);
+ streams[17] = INREG(STREAMS_FIFO_REG);
+ streams[18] = INREG(PSTREAM_START_REG);
+ streams[19] = INREG(PSTREAM_WINDOW_SIZE_REG);
+ streams[20] = INREG(SSTREAM_START_REG);
+ streams[21] = INREG(SSTREAM_WINDOW_SIZE_REG);
+
+}
+
+
+/*
+ * This function is used to restore a video mode. It writes out all
+ * of the standard VGA and extended S3 registers needed to setup a
+ * video mode.
+ *
+ * Note that our life is made more difficult because of the STREAMS
+ * processor which must be used for 24bpp. We need to disable STREAMS
+ * before we switch video modes, or we risk locking up the machine.
+ * We also have to follow a certain order when reenabling it.
+ */
+/* let's try restoring in the same order as in the 3.3.2.3 driver */
+static void
+S3VWriteMode (ScrnInfoPtr pScrn, vgaRegPtr vgaSavePtr, S3VRegPtr restore)
+{
+ unsigned char tmp, cr3a=0, cr66, cr67;
+
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ S3VPtr ps3v = S3VPTR(pScrn);
+ int vgaCRIndex, vgaCRReg, vgaIOBase;
+ vgaIOBase = hwp->IOBase;
+ vgaCRIndex = vgaIOBase + 4;
+ vgaCRReg = vgaIOBase + 5;
+
+ PVERB5(" S3VWriteMode\n");
+
+ vgaHWProtect(pScrn, TRUE);
+
+ /* Are we going to reenable STREAMS in this new mode? */
+ ps3v->STREAMSRunning = restore->CR67 & 0x0c;
+
+ /* First reset GE to make sure nothing is going on */
+ if(ps3v->Chipset == S3_ViRGE_VX) {
+ VGAOUT8(vgaCRIndex, 0x63);
+ if(VGAIN8(vgaCRReg) & 0x01) S3VGEReset(pScrn,0,__LINE__,__FILE__);
+ }
+ else {
+ VGAOUT8(vgaCRIndex, 0x66);
+ if(VGAIN8(vgaCRReg) & 0x01) S3VGEReset(pScrn,0,__LINE__,__FILE__);
+ }
+
+ /* As per databook, always disable STREAMS before changing modes */
+ VGAOUT8(vgaCRIndex, 0x67);
+ cr67 = VGAIN8(vgaCRReg);
+ if ((cr67 & 0x0c) == 0x0c) {
+ S3VDisableSTREAMS(pScrn); /* If STREAMS was running, disable it */
+ }
+
+ /* Restore S3 extended regs */
+ VGAOUT8(vgaCRIndex, 0x63);
+ VGAOUT8(vgaCRReg, restore->CR63);
+ VGAOUT8(vgaCRIndex, 0x66);
+ VGAOUT8(vgaCRReg, restore->CR66);
+ VGAOUT8(vgaCRIndex, 0x3a);
+ VGAOUT8(vgaCRReg, restore->CR3A);
+ VGAOUT8(vgaCRIndex, 0x31);
+ VGAOUT8(vgaCRReg, restore->CR31);
+ VGAOUT8(vgaCRIndex, 0x58);
+ VGAOUT8(vgaCRReg, restore->CR58);
+ VGAOUT8(vgaCRIndex, 0x55);
+ VGAOUT8(vgaCRReg, restore->CR55);
+
+ /* Extended mode timings registers */
+ VGAOUT8(vgaCRIndex, 0x53);
+ VGAOUT8(vgaCRReg, restore->CR53);
+ VGAOUT8(vgaCRIndex, 0x5d);
+ VGAOUT8(vgaCRReg, restore->CR5D);
+ VGAOUT8(vgaCRIndex, 0x5e);
+ VGAOUT8(vgaCRReg, restore->CR5E);
+ VGAOUT8(vgaCRIndex, 0x3b);
+ VGAOUT8(vgaCRReg, restore->CR3B);
+ VGAOUT8(vgaCRIndex, 0x3c);
+ VGAOUT8(vgaCRReg, restore->CR3C);
+ VGAOUT8(vgaCRIndex, 0x43);
+ VGAOUT8(vgaCRReg, restore->CR43);
+ VGAOUT8(vgaCRIndex, 0x65);
+ VGAOUT8(vgaCRReg, restore->CR65);
+ VGAOUT8(vgaCRIndex, 0x6d);
+ VGAOUT8(vgaCRReg, restore->CR6D);
+
+ /* Restore the desired video mode with CR67 */
+
+ VGAOUT8(vgaCRIndex, 0x67);
+ cr67 = VGAIN8(vgaCRReg) & 0xf; /* Possible hardware bug on VX? */
+ VGAOUT8(vgaCRReg, 0x50 | cr67);
+ usleep(10000);
+ VGAOUT8(vgaCRIndex, 0x67);
+ VGAOUT8(vgaCRReg, restore->CR67 & ~0x0c); /* Don't enable STREAMS yet */
+
+ /* Other mode timing and extended regs */
+ VGAOUT8(vgaCRIndex, 0x34);
+ VGAOUT8(vgaCRReg, restore->CR34);
+ if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) ||
+ /* S3_ViRGE_MX_SERIES(ps3v->Chipset) || CR40 reserved on MX */
+ S3_ViRGE_MXP_SERIES(ps3v->Chipset) ||
+ S3_ViRGE_VX_SERIES(ps3v->Chipset) ||
+ /* S3_TRIO_3D_2X_SERIES(ps3v->Chipset) * included in GX2 series */
+ ps3v->Chipset == S3_ViRGE_DXGX ||
+ ps3v->Chipset == S3_ViRGE
+ )
+ {
+ VGAOUT8(vgaCRIndex, 0x40);
+ VGAOUT8(vgaCRReg, restore->CR40);
+ }
+ if (S3_ViRGE_MX_SERIES(ps3v->Chipset)) {
+ VGAOUT8(vgaCRIndex, 0x41);
+ VGAOUT8(vgaCRReg, restore->CR41);
+ }
+ VGAOUT8(vgaCRIndex, 0x42);
+ VGAOUT8(vgaCRReg, restore->CR42);
+ VGAOUT8(vgaCRIndex, 0x45);
+ VGAOUT8(vgaCRReg, restore->CR45);
+ VGAOUT8(vgaCRIndex, 0x51);
+ VGAOUT8(vgaCRReg, restore->CR51);
+ VGAOUT8(vgaCRIndex, 0x54);
+ VGAOUT8(vgaCRReg, restore->CR54);
+
+ /* Memory timings */
+ VGAOUT8(vgaCRIndex, 0x36);
+ VGAOUT8(vgaCRReg, restore->CR36);
+ VGAOUT8(vgaCRIndex, 0x68);
+ VGAOUT8(vgaCRReg, restore->CR68);
+ VGAOUT8(vgaCRIndex, 0x69);
+ VGAOUT8(vgaCRReg, restore->CR69);
+
+ VGAOUT8(vgaCRIndex, 0x33);
+ VGAOUT8(vgaCRReg, restore->CR33);
+ if (S3_TRIO_3D_2X_SERIES(ps3v->Chipset) || S3_ViRGE_GX2_SERIES(ps3v->Chipset)
+ /* MXTESTME */ || S3_ViRGE_MX_SERIES(ps3v->Chipset) )
+ {
+ VGAOUT8(vgaCRIndex, 0x85);
+ VGAOUT8(vgaCRReg, restore->CR85);
+ }
+ if (ps3v->Chipset == S3_ViRGE_DXGX) {
+ VGAOUT8(vgaCRIndex, 0x86);
+ VGAOUT8(vgaCRReg, restore->CR86);
+ }
+ if ( (ps3v->Chipset == S3_ViRGE_GX2) ||
+ S3_ViRGE_MX_SERIES(ps3v->Chipset) ) {
+ VGAOUT8(vgaCRIndex, 0x7B);
+ VGAOUT8(vgaCRReg, restore->CR7B);
+ VGAOUT8(vgaCRIndex, 0x7D);
+ VGAOUT8(vgaCRReg, restore->CR7D);
+ VGAOUT8(vgaCRIndex, 0x87);
+ VGAOUT8(vgaCRReg, restore->CR87);
+ VGAOUT8(vgaCRIndex, 0x92);
+ VGAOUT8(vgaCRReg, restore->CR92);
+ VGAOUT8(vgaCRIndex, 0x93);
+ VGAOUT8(vgaCRReg, restore->CR93);
+ }
+ if (ps3v->Chipset == S3_ViRGE_DXGX || S3_ViRGE_GX2_SERIES(ps3v->Chipset) ||
+ S3_ViRGE_MX_SERIES(ps3v->Chipset) || S3_TRIO_3D_SERIES(ps3v->Chipset)) {
+ VGAOUT8(vgaCRIndex, 0x90);
+ VGAOUT8(vgaCRReg, restore->CR90);
+ VGAOUT8(vgaCRIndex, 0x91);
+ VGAOUT8(vgaCRReg, restore->CR91);
+ }
+
+ /* Unlock extended sequencer regs */
+ VGAOUT8(0x3c4, 0x08);
+ VGAOUT8(0x3c5, 0x06);
+
+
+ /* Restore extended sequencer regs for MCLK. SR10 == 255 indicates that
+ * we should leave the default SR10 and SR11 values there.
+ */
+
+ if (restore->SR10 != 255) {
+ VGAOUT8(0x3c4, 0x10);
+ VGAOUT8(0x3c5, restore->SR10);
+ VGAOUT8(0x3c4, 0x11);
+ VGAOUT8(0x3c5, restore->SR11);
+ }
+
+ /* Restore extended sequencer regs for DCLK */
+ VGAOUT8(0x3c4, 0x12);
+ VGAOUT8(0x3c5, restore->SR12);
+ VGAOUT8(0x3c4, 0x13);
+ VGAOUT8(0x3c5, restore->SR13);
+ if (S3_ViRGE_GX2_SERIES(ps3v->Chipset) || S3_ViRGE_MX_SERIES(ps3v->Chipset)) {
+ VGAOUT8(0x3c4, 0x29);
+ VGAOUT8(0x3c5, restore->SR29);
+ }
+ if (S3_ViRGE_MX_SERIES(ps3v->Chipset)) {
+ VGAOUT8(0x3c4, 0x54);
+ VGAOUT8(0x3c5, restore->SR54);
+ VGAOUT8(0x3c4, 0x55);
+ VGAOUT8(0x3c5, restore->SR55);
+ VGAOUT8(0x3c4, 0x56);
+ VGAOUT8(0x3c5, restore->SR56);
+ VGAOUT8(0x3c4, 0x57);
+ VGAOUT8(0x3c5, restore->SR57);
+ }
+
+ VGAOUT8(0x3c4, 0x18);
+ VGAOUT8(0x3c5, restore->SR18);
+
+ /* Load new m,n PLL values for DCLK & MCLK */
+ VGAOUT8(0x3c4, 0x15);
+ tmp = VGAIN8(0x3c5) & ~0x21;
+
+ /* databook either 0x3 or 0x20, but not both?? */
+ VGAOUT8(0x3c5, tmp | 0x03);
+ VGAOUT8(0x3c5, tmp | 0x23);
+ VGAOUT8(0x3c5, tmp | 0x03);
+ VGAOUT8(0x3c5, restore->SR15);
+ if (S3_TRIO_3D_SERIES(ps3v->Chipset)) {
+ VGAOUT8(0x3c4, 0x0a);
+ VGAOUT8(0x3c5, restore->SR0A);
+ VGAOUT8(0x3c4, 0x0f);
+ VGAOUT8(0x3c5, restore->SR0F);
+ }
+
+ VGAOUT8(0x3c4, 0x08);
+ VGAOUT8(0x3c5, restore->SR08);
+
+
+ /* Now write out CR67 in full, possibly starting STREAMS */
+
+ VerticalRetraceWait();
+ VGAOUT8(vgaCRIndex, 0x67);
+ VGAOUT8(vgaCRReg, 0x50); /* For possible bug on VX?! */
+ usleep(10000);
+ VGAOUT8(vgaCRIndex, 0x67);
+ VGAOUT8(vgaCRReg, restore->CR67);
+
+ VGAOUT8(vgaCRIndex, 0x66);
+ cr66 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRReg, cr66 | 0x80);
+ VGAOUT8(vgaCRIndex, 0x3a);
+
+ /* workaround cr3a corruption */
+ if( ps3v->mx_cr3a_fix )
+ {
+ VGAOUT8(vgaCRReg, restore->CR3A | 0x80);
+ }
+ else
+ {
+ cr3a = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRReg, cr3a | 0x80);
+ }
+
+ /* And finally, we init the STREAMS processor if we have CR67 indicate 24bpp
+ * We also restore FIFO and TIMEOUT memory controller registers. (later...)
+ */
+
+ if (ps3v->NeedSTREAMS) {
+ if(ps3v->STREAMSRunning) S3VRestoreSTREAMS(pScrn, restore->STREAMS);
+ }
+
+ /* Now, before we continue, check if this mode has the graphic engine ON
+ * If yes, then we reset it.
+ * This fixes some problems with corruption at 24bpp with STREAMS
+ * Also restore the MIU registers.
+ */
+
+#ifndef MetroLink
+ if(ps3v->Chipset == S3_ViRGE_VX) {
+ if(restore->CR63 & 0x01) S3VGEReset(pScrn,0,__LINE__,__FILE__);
+ }
+ else {
+ if(restore->CR66 & 0x01) S3VGEReset(pScrn,0,__LINE__,__FILE__);
+ }
+#else
+ S3VGEReset(pScrn,0,__LINE__,__FILE__);
+#endif
+
+ VerticalRetraceWait();
+ if (S3_ViRGE_GX2_SERIES(ps3v->Chipset)
+ /* MXTESTME */ || S3_ViRGE_MX_SERIES(ps3v->Chipset) )
+ {
+ VGAOUT8(vgaCRIndex, 0x85);
+ /* primary stream threshold */
+ VGAOUT8(vgaCRReg, 0x1f );
+ }
+ else
+ {
+ OUTREG(FIFO_CONTROL_REG, restore->MMPR0);
+ }
+ if( !( S3_ViRGE_GX2_SERIES(ps3v->Chipset)
+ /* MXTESTME */ || S3_ViRGE_MX_SERIES(ps3v->Chipset) ))
+ {
+ WaitIdle(); /* Don't ask... */
+ OUTREG(MIU_CONTROL_REG, restore->MMPR1);
+ WaitIdle();
+ OUTREG(STREAMS_TIMEOUT_REG, restore->MMPR2);
+ WaitIdle();
+ OUTREG(MISC_TIMEOUT_REG, restore->MMPR3);
+ }
+
+ /* Restore the standard VGA registers */
+ /* False indicates no fontinfo restore. */
+ /* VGA_SR_MODE restores mode info only, no font, no colormap */
+ /* Do all for primary video */
+ if (xf86IsPrimaryPci(ps3v->PciInfo))
+ vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_ALL);
+ /* Mode only for non-primary? */
+ else
+ vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_MODE);
+ /* moved from before vgaHWRestore, to prevent segfault? */
+ VGAOUT8(vgaCRIndex, 0x66);
+ VGAOUT8(vgaCRReg, cr66);
+ VGAOUT8(vgaCRIndex, 0x3a);
+
+ /* workaround cr3a corruption */
+ if( ps3v->mx_cr3a_fix )
+ VGAOUT8(vgaCRReg, restore->CR3A);
+ else
+ VGAOUT8(vgaCRReg, cr3a);
+
+ if (xf86GetVerbosity() > 1) {
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
+ "ViRGE driver: done restoring mode, dumping CR registers:\n");
+ S3VPrintRegs(pScrn);
+ }
+
+ vgaHWProtect(pScrn, FALSE);
+
+ return;
+
+}
+
+
+/* This function restores the saved STREAMS registers */
+
+static void
+S3VRestoreSTREAMS(ScrnInfoPtr pScrn, unsigned int *streams)
+{
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+
+/* For now, set most regs to their default values for 24bpp
+ * Restore only those that are needed for width/height/stride
+ * Otherwise, we seem to get lockups because some registers
+ * when saved have some reserved bits set.
+ */
+
+ OUTREG(PSTREAM_CONTROL_REG, streams[0] & 0x77000000);
+ OUTREG(COL_CHROMA_KEY_CONTROL_REG, 0x00);
+ OUTREG(SSTREAM_CONTROL_REG, 0x03000000);
+ OUTREG(CHROMA_KEY_UPPER_BOUND_REG, 0x00);
+ OUTREG(SSTREAM_STRETCH_REG, 0x00);
+ OUTREG(BLEND_CONTROL_REG, 0x01000000);
+ OUTREG(PSTREAM_FBADDR0_REG, 0x00);
+ OUTREG(PSTREAM_FBADDR1_REG, 0x00);
+ OUTREG(PSTREAM_STRIDE_REG, streams[8] & 0x0fff);
+ OUTREG(DOUBLE_BUFFER_REG, 0x00);
+ OUTREG(SSTREAM_FBADDR0_REG, 0x00);
+ OUTREG(SSTREAM_FBADDR1_REG, 0x00);
+ OUTREG(SSTREAM_STRIDE_REG, 0x01);
+ OUTREG(OPAQUE_OVERLAY_CONTROL_REG, 0x40000000);
+ OUTREG(K1_VSCALE_REG, 0x00);
+ OUTREG(K2_VSCALE_REG, 0x00);
+ OUTREG(DDA_VERT_REG, 0x00);
+ OUTREG(PSTREAM_START_REG, 0x00010001);
+ OUTREG(PSTREAM_WINDOW_SIZE_REG, streams[19] & 0x07ff07ff);
+ OUTREG(SSTREAM_START_REG, 0x07ff07ff);
+ OUTREG(SSTREAM_WINDOW_SIZE_REG, 0x00010001);
+
+
+}
+
+
+
+
+/* And this function disables the STREAMS processor as per databook.
+ * This is usefull before we do a mode change
+ */
+
+static void
+S3VDisableSTREAMS(ScrnInfoPtr pScrn)
+{
+unsigned char tmp;
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ S3VPtr ps3v = S3VPTR(pScrn);
+ int vgaCRIndex, vgaCRReg, vgaIOBase;
+ vgaIOBase = hwp->IOBase;
+ vgaCRIndex = vgaIOBase + 4;
+ vgaCRReg = vgaIOBase + 5;
+
+ VerticalRetraceWait();
+ OUTREG(FIFO_CONTROL_REG, 0xC000);
+ VGAOUT8(vgaCRIndex, 0x67);
+ tmp = VGAIN8(vgaCRReg);
+ /* Disable STREAMS processor */
+ VGAOUT8( vgaCRReg, tmp & ~0x0C );
+
+ return;
+}
+
+
+
+/* MapMem - contains half of pre-4.0 EnterLeave function */
+/* The EnterLeave function which en/dis access to IO ports and ext. regs */
+ /********************************************************/
+ /* Aaagh... So many locations! On my machine (KJB) the*/
+ /* following is true. */
+ /* PciInfo->memBase[0] returns e400 0000 */
+ /* From my ViRGE manual, the memory map looks like */
+ /* Linear mem - 16M 000 0000 - 0ff ffff */
+ /* Image xfer - 32k 100 0000 - 100 7fff */
+ /* PCI cnfg 100 8000 - 100 8043 */
+ /* ... */
+ /* CRT VGA 3b? reg 100 83b0 - */
+ /* And S3_NEWMMIO_VGABASE = S3_NEWMMIO_REGBASE + 0x8000 */
+ /* where S3_NEWMMIO_REGBASE = 0x100 0000 ( 16MB ) */
+ /* S3_NEWMMIO_REGSIZE = 0x1 0000 ( 64KB ) */
+ /* S3V_MMIO_REGSIZE = 0x8000 ( 32KB ) - above includes */
+ /* the image transfer area, so this one is used instead.*/
+ /* ps3v->IOBase is assinged the virtual address returned*/
+ /* from MapPciMem, it is the address to base all */
+ /* register access. (It is a pointer.) */
+ /* hwp->MemBase is a CARD32, containing the register */
+ /* base. (It's a conversion from IOBase above.) */
+ /********************************************************/
+
+
+static Bool
+S3VMapMem(ScrnInfoPtr pScrn)
+{
+ S3VPtr ps3v;
+ vgaHWPtr hwp;
+
+ PVERB5(" S3VMapMem\n");
+
+ ps3v = S3VPTR(pScrn);
+
+ /* Map the ViRGE register space */
+ /* Starts with Image Transfer area */
+ /* so that we can use registers map */
+ /* structure - see newmmio.h */
+ /* around 0x10000 from MemBase */
+ ps3v->MapBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, ps3v->PciTag,
+ ps3v->PciInfo->memBase[0] + S3_NEWMMIO_REGBASE,
+ S3_NEWMMIO_REGSIZE);
+
+ ps3v->MapBaseDense = xf86MapPciMem(pScrn->scrnIndex,
+ VIDMEM_MMIO_32BIT,
+ ps3v->PciTag,
+ ps3v->PciInfo->memBase[0] + S3_NEWMMIO_REGBASE,
+ 0x8000);
+
+ if( !ps3v->MapBase ) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Internal error: could not map registers.\n");
+ return FALSE;
+ }
+ /* Map the framebuffer */
+ if (ps3v->videoRambytes) { /* not set in PreInit() */
+ ps3v->FBBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
+ ps3v->PciTag, ps3v->PciInfo->memBase[0],
+ ps3v->videoRambytes );
+
+ if( !ps3v->FBBase ) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Internal error: could not map framebuffer.\n");
+ return FALSE;
+ }
+ /* Initially the visual display start */
+ /* is the same as the mapped start. */
+ ps3v->FBStart = ps3v->FBBase;
+ }
+
+ pScrn->memPhysBase = ps3v->PciInfo->memBase[0];
+ pScrn->fbOffset = 0;
+
+ /* Set up offset to hwcursor memory area */
+ /* It's a 1K chunk at the end of the frame buffer */
+ ps3v->FBCursorOffset = ps3v->videoRambytes - 1024;
+ S3VEnableMmio( pScrn);
+ /* Assign hwp->MemBase & IOBase here */
+ hwp = VGAHWPTR(pScrn);
+ /* Sets MMIOBase and Offset, assigns */
+ /* functions. Offset from map area */
+ /* to VGA reg area is 0x8000. */
+ vgaHWSetMmioFuncs( hwp, ps3v->MapBase, S3V_MMIO_REGSIZE );
+ /* assigns hwp->IOBase to 3D0 or 3B0 */
+ /* needs hwp->MMIOBase to work */
+ vgaHWGetIOBase(hwp);
+
+ /* Map the VGA memory when the */
+ /* primary video */
+
+ if (xf86IsPrimaryPci(ps3v->PciInfo)) {
+ hwp->MapSize = 0x10000;
+ if (!vgaHWMapMem(pScrn))
+ return FALSE;
+ ps3v->PrimaryVidMapped = TRUE;
+ }
+
+ return TRUE;
+}
+
+
+
+/* UnMapMem - contains half of pre-4.0 EnterLeave function */
+/* The EnterLeave function which en/dis access to IO ports and ext. regs */
+
+static void
+S3VUnmapMem(ScrnInfoPtr pScrn)
+{
+ S3VPtr ps3v;
+
+ ps3v = S3VPTR(pScrn);
+ /* Unmap VGA mem if mapped. */
+ if( ps3v->PrimaryVidMapped ) {
+ vgaHWUnmapMem( pScrn );
+ ps3v->PrimaryVidMapped = FALSE;
+ }
+
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer)ps3v->MapBase,
+ S3_NEWMMIO_REGSIZE);
+ if (ps3v->FBBase)
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer)ps3v->FBBase,
+ ps3v->videoRambytes);
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer)ps3v->MapBaseDense,
+ 0x8000);
+
+ return;
+}
+
+
+
+/* Mandatory */
+
+/* This gets called at the start of each server generation */
+
+static Bool
+S3VScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
+{
+ ScrnInfoPtr pScrn;
+ S3VPtr ps3v;
+ int ret;
+
+ PVERB5(" S3VScreenInit\n");
+ /* First get the ScrnInfoRec */
+ pScrn = xf86Screens[pScreen->myNum];
+ /* Get S3V rec */
+ ps3v = S3VPTR(pScrn);
+ /* Make sure we have card access */
+/* xf86EnableAccess(pScrn);*/
+ /* Map MMIO regs and framebuffer */
+ if( !S3VMapMem(pScrn) )
+ return FALSE;
+ /* Save the chip/graphics state */
+ S3VSave(pScrn);
+ /* Blank the screen during init */
+ vgaHWBlankScreen(pScrn, TRUE );
+ /* Initialise the first mode */
+ if (!S3VModeInit(pScrn, pScrn->currentMode))
+ return FALSE;
+
+ /*
+ * The next step is to setup the screen's visuals, and initialise the
+ * framebuffer code. In cases where the framebuffer's default
+ * choices for things like visual layouts and bits per RGB are OK,
+ * this may be as simple as calling the framebuffer's ScreenInit()
+ * function. If not, the visuals will need to be setup before calling
+ * a fb ScreenInit() function and fixed up after.
+ *
+ * For most PC hardware at depths >= 8, the defaults that fb uses
+ * are not appropriate. In this driver, we fixup the visuals after.
+ */
+
+ /*
+ * Reset the visual list.
+ */
+ miClearVisualTypes();
+
+ /* Setup the visuals we support. */
+
+ /*
+ * For bpp > 8, the default visuals are not acceptable because we only
+ * support TrueColor and not DirectColor. To deal with this, call
+ * miSetVisualTypes with the appropriate visual mask.
+ */
+
+ if (pScrn->bitsPerPixel > 8) {
+ if (!miSetVisualTypes(pScrn->depth, TrueColorMask, pScrn->rgbBits,
+ pScrn->defaultVisual))
+ return FALSE;
+
+ if (!miSetPixmapDepths ())
+ return FALSE;
+ } else {
+ if (!miSetVisualTypes(pScrn->depth,
+ miGetDefaultVisualMask(pScrn->depth),
+ pScrn->rgbBits, pScrn->defaultVisual))
+ return FALSE;
+
+ if (!miSetPixmapDepths ())
+ return FALSE;
+ }
+
+ ret = S3VInternalScreenInit(scrnIndex, pScreen);
+
+ if (!ret)
+ return FALSE;
+
+ xf86SetBlackWhitePixels(pScreen);
+
+ if (pScrn->bitsPerPixel > 8) {
+ VisualPtr visual;
+ /* Fixup RGB ordering */
+ visual = pScreen->visuals + pScreen->numVisuals;
+ while (--visual >= pScreen->visuals) {
+ if ((visual->class | DynamicClass) == DirectColor) {
+ visual->offsetRed = pScrn->offset.red;
+ visual->offsetGreen = pScrn->offset.green;
+ visual->offsetBlue = pScrn->offset.blue;
+ visual->redMask = pScrn->mask.red;
+ visual->greenMask = pScrn->mask.green;
+ visual->blueMask = pScrn->mask.blue;
+ }
+ }
+ }
+
+ /* must be after RGB ordering fixed */
+ if (ps3v->UseFB)
+ fbPictureInit (pScreen, 0, 0);
+
+ /* Initialize acceleration layer */
+ if (!ps3v->NoAccel) {
+ if(pScrn->bitsPerPixel == 32) {
+ /* 32 bit Accel currently broken
+ if (!S3VAccelInit32(pScreen))
+ return FALSE;
+ */
+ ;
+ } else
+ if (!S3VAccelInit(pScreen))
+ return FALSE;
+ }
+
+ miInitializeBackingStore(pScreen);
+ xf86SetBackingStore(pScreen);
+ xf86SetSilkenMouse(pScreen);
+ /* hardware cursor needs to wrap this layer */
+ if ( !ps3v->shadowFB && !ps3v->useEXA )
+ S3VDGAInit(pScreen);
+
+ /* Initialise cursor functions */
+ miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
+
+ /* Initialize HW cursor layer.
+ Must follow software cursor initialization*/
+ if (ps3v->hwcursor) {
+ if(!S3VHWCursorInit(pScreen)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Hardware cursor initialization failed\n");
+ }
+ }
+
+ if (ps3v->shadowFB) {
+ RefreshAreaFuncPtr refreshArea = s3vRefreshArea;
+
+ if(ps3v->rotate) {
+ if (!ps3v->PointerMoved) {
+ ps3v->PointerMoved = pScrn->PointerMoved;
+ pScrn->PointerMoved = s3vPointerMoved;
+ }
+
+ switch(pScrn->bitsPerPixel) {
+ case 8: refreshArea = s3vRefreshArea8; break;
+ case 16: refreshArea = s3vRefreshArea16; break;
+ case 24: refreshArea = s3vRefreshArea24; break;
+ case 32: refreshArea = s3vRefreshArea32; break;
+ }
+ }
+
+ ShadowFBInit(pScreen, refreshArea);
+ }
+
+ /* Initialise default colourmap */
+ if (!miCreateDefColormap(pScreen))
+ return FALSE;
+ /* Initialize colormap layer. */
+ /* Must follow initialization */
+ /* of the default colormap. */
+ /* And SetGamma call, else it */
+ /* will load palette with solid */
+ /* white. */
+ if(!xf86HandleColormaps(pScreen, 256, 6, S3VLoadPalette, NULL,
+ CMAP_RELOAD_ON_MODE_SWITCH ))
+ return FALSE;
+ /* All the ugly stuff is done, */
+ /* so re-enable the screen. */
+ vgaHWBlankScreen(pScrn, FALSE );
+
+#if 0
+ pScrn->racMemFlags = RAC_COLORMAP | RAC_CURSOR | RAC_FB | RAC_VIEWPORT;
+#endif
+ pScreen->SaveScreen = S3VSaveScreen;
+
+ /* Wrap the current CloseScreen function */
+ ps3v->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = S3VCloseScreen;
+
+ if(xf86DPMSInit(pScreen, S3VDisplayPowerManagementSet, 0) == FALSE)
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DPMS initialization failed!\n");
+
+ S3VInitVideo(pScreen);
+
+ /* Report any unused options (only for the first generation) */
+ if (serverGeneration == 1) {
+ xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
+ }
+ /* Done */
+ return TRUE;
+}
+
+
+
+/* Common init routines needed in EnterVT and ScreenInit */
+
+static int
+S3VInternalScreenInit( int scrnIndex, ScreenPtr pScreen)
+{
+ int ret = TRUE;
+ ScrnInfoPtr pScrn;
+ S3VPtr ps3v;
+ int width, height, displayWidth;
+ unsigned char* FBStart;
+
+ /* First get the ScrnInfoRec */
+ pScrn = xf86Screens[pScreen->myNum];
+
+ ps3v = S3VPTR(pScrn);
+
+ displayWidth = pScrn->displayWidth;
+ if (ps3v->rotate) {
+ height = pScrn->virtualX;
+ width = pScrn->virtualY;
+ } else {
+ width = pScrn->virtualX;
+ height = pScrn->virtualY;
+ }
+
+ if(ps3v->shadowFB) {
+ ps3v->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width);
+ ps3v->ShadowPtr = xalloc(ps3v->ShadowPitch * height);
+ displayWidth = ps3v->ShadowPitch / (pScrn->bitsPerPixel >> 3);
+ FBStart = ps3v->ShadowPtr;
+ } else {
+ ps3v->ShadowPtr = NULL;
+ FBStart = ps3v->FBStart;
+ }
+
+ /*
+ * Call the framebuffer layer's ScreenInit function, and fill in other
+ * pScreen fields.
+ */
+
+ if( ps3v->UseFB )
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using FB\n");
+
+ switch (pScrn->bitsPerPixel)
+ {
+ case 8:
+ case 16:
+ case 24:
+ ret = fbScreenInit(pScreen, FBStart, pScrn->virtualX,
+ pScrn->virtualY, pScrn->xDpi, pScrn->yDpi,
+ displayWidth, pScrn->bitsPerPixel);
+ break;
+ default:
+ xf86DrvMsg(scrnIndex, X_ERROR,
+ "Internal error: invalid bpp (%d) in S3VScreenInit\n",
+ pScrn->bitsPerPixel);
+ ret = FALSE;
+ break;
+ }
+ }
+ return ret;
+}
+
+
+
+/* Checks if a mode is suitable for the selected chipset. */
+
+static ModeStatus
+S3VValidMode(int index, DisplayModePtr mode, Bool verbose, int flags)
+{
+
+ return MODE_OK;
+}
+
+
+
+static Bool
+S3VModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ S3VPtr ps3v = S3VPTR(pScrn);
+ int width, dclk;
+ int i, j;
+ unsigned char tmp = 0;
+
+ /* Store values to current mode register structs */
+ S3VRegPtr new = &ps3v->ModeReg;
+ vgaRegPtr vganew = &hwp->ModeReg;
+ int vgaCRIndex, vgaCRReg, vgaIOBase;
+
+ vgaIOBase = hwp->IOBase;
+ vgaCRIndex = vgaIOBase + 4;
+ vgaCRReg = vgaIOBase + 5;
+
+ PVERB5(" S3VModeInit\n");
+
+ /* Set scale factors for mode timings */
+
+ if (ps3v->Chipset == S3_ViRGE_VX || S3_ViRGE_GX2_SERIES(ps3v->Chipset) ||
+ S3_ViRGE_MX_SERIES(ps3v->Chipset)) {
+ ps3v->HorizScaleFactor = 1;
+ }
+ else if (pScrn->bitsPerPixel == 8) {
+ ps3v->HorizScaleFactor = 1;
+ }
+ else if (pScrn->bitsPerPixel == 16) {
+ if (S3_TRIO_3D_SERIES(ps3v->Chipset) && mode->Clock > 115000)
+ ps3v->HorizScaleFactor = 1;
+ else
+ ps3v->HorizScaleFactor = 2;
+ }
+ else {
+ ps3v->HorizScaleFactor = 1;
+ }
+
+
+ /* First we adjust the horizontal timings if needed */
+
+ if(ps3v->HorizScaleFactor != 1)
+ if (!mode->CrtcHAdjusted) {
+ mode->CrtcHDisplay *= ps3v->HorizScaleFactor;
+ mode->CrtcHSyncStart *= ps3v->HorizScaleFactor;
+ mode->CrtcHSyncEnd *= ps3v->HorizScaleFactor;
+ mode->CrtcHTotal *= ps3v->HorizScaleFactor;
+ mode->CrtcHSkew *= ps3v->HorizScaleFactor;
+ mode->CrtcHAdjusted = TRUE;
+ }
+
+ if(!vgaHWInit (pScrn, mode))
+ return FALSE;
+
+ /* Now we fill in the rest of the stuff we need for the virge */
+ /* Start with MMIO, linear addr. regs */
+
+ VGAOUT8(vgaCRIndex, 0x3a);
+ tmp = VGAIN8(vgaCRReg);
+ if( S3_ViRGE_GX2_SERIES(ps3v->Chipset)
+ /* MXTESTME */ || S3_ViRGE_MX_SERIES(ps3v->Chipset) )
+ {
+ if(ps3v->pci_burst)
+ /*new->CR3A = (tmp & 0x38) | 0x10; / ENH 256, PCI burst */
+ /* Don't clear reserved bits... */
+ new->CR3A = (tmp & 0x7f) | 0x10; /* ENH 256, PCI burst */
+ else
+ new->CR3A = tmp | 0x90; /* ENH 256, no PCI burst! */
+ }
+ else
+ {
+ if(ps3v->pci_burst)
+ new->CR3A = (tmp & 0x7f) | 0x15; /* ENH 256, PCI burst */
+ else
+ new->CR3A = tmp | 0x95; /* ENH 256, no PCI burst! */
+ }
+
+
+ VGAOUT8(vgaCRIndex, 0x55);
+ new->CR55 = VGAIN8(vgaCRReg);
+ if (ps3v->hwcursor)
+ new->CR55 |= 0x10; /* Enables X11 hw cursor mode */
+ if (S3_TRIO_3D_SERIES(ps3v->Chipset)) {
+ new->CR31 = 0x0c; /* [trio3d] page 54 */
+ } else {
+ new->CR53 = 0x08; /* Enables MMIO */
+ new->CR31 = 0x8c; /* Dis. 64k window, en. ENH maps */
+ }
+
+ /* Enables S3D graphic engine and PCI disconnects */
+ if(ps3v->Chipset == S3_ViRGE_VX){
+ new->CR66 = 0x90;
+ new->CR63 = 0x09;
+ }
+ else {
+ new->CR66 = 0x89;
+ /* Set display fifo */
+ if( S3_ViRGE_GX2_SERIES(ps3v->Chipset) ||
+ S3_ViRGE_MX_SERIES(ps3v->Chipset) )
+ {
+ /* Changed from 0x08 based on reports that this */
+ /* prevents MX from running properly below 1024x768 */
+ new->CR63 = 0x10;
+ }
+ else
+ {
+ new->CR63 = 0;
+ }
+ }
+
+ /* Now set linear addr. registers */
+ /* LAW size: we have 2 cases, 2MB, 4MB or >= 4MB for VX */
+ VGAOUT8(vgaCRIndex, 0x58);
+ new->CR58 = VGAIN8(vgaCRReg) & 0x80;
+ if(pScrn->videoRam == 2048){
+ new->CR58 |= 0x02 | 0x10;
+ }
+ else if (pScrn->videoRam == 1024) {
+ new->CR58 |= 0x01 | 0x10;
+ }
+ else {
+ if (S3_TRIO_3D_2X_SERIES(ps3v->Chipset) && pScrn->videoRam == 8192)
+ new->CR58 |= 0x07 | 0x10; /* 8MB window on Trio3D/2X */
+ else
+ new->CR58 |= 0x03 | 0x10; /* 4MB window on virge, 8MB on VX */
+ }
+ if(ps3v->Chipset == S3_ViRGE_VX)
+ new->CR58 |= 0x40;
+ if (ps3v->early_ras_precharge)
+ new->CR58 |= 0x80;
+ if (ps3v->late_ras_precharge)
+ new->CR58 &= 0x7f;
+
+ /* ** On PCI bus, no need to reprogram the linear window base address */
+
+ /* Now do clock PLL programming. Use the s3gendac function to get m,n */
+ /* Also determine if we need doubling etc. */
+
+ dclk = mode->Clock;
+ new->CR67 = 0x00; /* Defaults */
+
+ if (!S3_TRIO_3D_SERIES(ps3v->Chipset))
+ new->SR15 = 0x03 | 0x80;
+ else {
+ VGAOUT8(0x3c4, 0x15);
+ new->SR15 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x0a);
+ new->SR0A = VGAIN8(0x3c5);
+ if (ps3v->slow_dram) {
+ new->SR15 = 0x03; /* 3 CYC MWR */
+ new->SR0A &= 0x7F;
+ } else if (ps3v->fast_dram) {
+ new->SR15 = 0x03 | 0x80; /* 2 CYC MWR */
+ new->SR0A |= 0x80;
+ } else { /* keep BIOS init defaults */
+ new->SR15 = (new->SR15 & 0x80) | 0x03;
+ }
+ }
+ new->SR18 = 0x00;
+ new->CR43 = 0x00;
+ new->CR45 = 0x00;
+ /* Enable MMIO to RAMDAC registers */
+ new->CR65 = 0x00; /* CR65_2 must be zero, doc seems to be wrong */
+ new->CR54 = 0x00;
+
+ if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) ||
+ /* S3_ViRGE_MX_SERIES(ps3v->Chipset) || CR40 reserved on MX */
+ S3_ViRGE_MXP_SERIES(ps3v->Chipset) ||
+ S3_ViRGE_VX_SERIES(ps3v->Chipset) ||
+ /* S3_TRIO_3D_2X_SERIES(ps3v->Chipset) * included in GX2 series */
+ ps3v->Chipset == S3_ViRGE_DXGX ||
+ ps3v->Chipset == S3_ViRGE
+ ) {
+ VGAOUT8(vgaCRIndex, 0x40);
+ new->CR40 = VGAIN8(vgaCRReg) & ~0x01;
+ }
+
+ if (S3_ViRGE_MX_SERIES(ps3v->Chipset)) {
+ /* fix problems with APM suspend/resume trashing CR90/91 */
+ switch(pScrn->bitsPerPixel) {
+ case 8: new->CR41 = 0x38; break;
+ case 15: new->CR41 = 0x58; break;
+ case 16: new->CR41 = 0x48; break;
+ default: new->CR41 = 0x77;
+ }
+ }
+
+ xf86ErrorFVerb(VERBLEV, " S3VModeInit dclk=%i \n",
+ dclk
+ );
+
+ /* Memory controller registers. Optimize for better graphics engine
+ * performance. These settings are adjusted/overridden below for other bpp/
+ * XConfig options.The idea here is to give a longer number of contiguous
+ * MCLK's to both refresh and the graphics engine, to diminish the
+ * relative penalty of 3 or 4 mclk's needed to setup memory transfers.
+ */
+ new->MMPR0 = 0x010400; /* defaults */
+ new->MMPR1 = 0x00;
+ new->MMPR2 = 0x0808;
+ new->MMPR3 = 0x08080810;
+
+ /*
+ * These settings look like they ought to be better adjusted for depth,
+ * so for problem modes running without any fifo_ option should be
+ * usable. Note that these adjust some memory timings and relate to
+ * the boards MCLK setting.
+ * */
+ if( ps3v->fifo_aggressive || ps3v->fifo_moderate ||
+ ps3v->fifo_conservative ) {
+
+ new->MMPR1 = 0x0200; /* Low P. stream waits before filling */
+ new->MMPR2 = 0x1808; /* Let the FIFO refill itself */
+ new->MMPR3 = 0x08081810; /* And let the GE hold the bus for a while */
+ }
+
+ /* And setup here the new value for MCLK. We use the XConfig
+ * option "set_mclk", whose value gets stored in ps3v->MCLK.
+ * I'm not sure what the maximum "permitted" value should be, probably
+ * 100 MHz is more than enough for now.
+ */
+
+ if(ps3v->MCLK> 0) {
+ if (S3_ViRGE_MX_SERIES(ps3v->Chipset))
+ S3VCommonCalcClock(pScrn, mode,
+ (int)(ps3v->MCLK / ps3v->refclk_fact),
+ 1, 1, 31, 0, 3,
+ 135000, 270000, &new->SR11, &new->SR10);
+ else
+ S3VCommonCalcClock(pScrn, mode, ps3v->MCLK, 1, 1, 31, 0, 3,
+ 135000, 270000, &new->SR11, &new->SR10);
+ }
+ else {
+ new->SR10 = 255; /* This is a reserved value, so we use as flag */
+ new->SR11 = 255;
+ }
+
+ /* most modes don't need STREAMS */
+ /* processor, preset FALSE */
+ /* support for XVideo needs streams, so added it to some modes */
+ ps3v->NeedSTREAMS = FALSE;
+
+ if(ps3v->Chipset == S3_ViRGE_VX){
+ if (pScrn->bitsPerPixel == 8) {
+ if (dclk <= 110000) new->CR67 = 0x00; /* 8bpp, 135MHz */
+ else new->CR67 = 0x10; /* 8bpp, 220MHz */
+ }
+ else if ((pScrn->bitsPerPixel == 16) && (pScrn->weight.green == 5)) {
+ if (dclk <= 110000) new->CR67 = 0x20; /* 15bpp, 135MHz */
+ else new->CR67 = 0x30; /* 15bpp, 220MHz */
+ }
+ else if (pScrn->bitsPerPixel == 16) {
+ if (dclk <= 110000) new->CR67 = 0x40; /* 16bpp, 135MHz */
+ else new->CR67 = 0x50; /* 16bpp, 220MHz */
+ }
+ else if ((pScrn->bitsPerPixel == 24) || (pScrn->bitsPerPixel == 32)) {
+ new->CR67 = 0xd0 | 0x0c; /* 24bpp, 135MHz, STREAMS */
+ /* Flag STREAMS proc. required */
+ ps3v->NeedSTREAMS = TRUE;
+ S3VInitSTREAMS(pScrn, new->STREAMS, mode);
+ new->MMPR0 = 0xc098; /* Adjust FIFO slots */
+ }
+ S3VCommonCalcClock(pScrn, mode, dclk, 1, 1, 31, 0, 4,
+ 220000, 440000, &new->SR13, &new->SR12);
+
+ } /* end VX if() */
+ else if (S3_ViRGE_GX2_SERIES(ps3v->Chipset) || S3_ViRGE_MX_SERIES(ps3v->Chipset)) {
+ if (pScrn->bitsPerPixel == 8)
+ new->CR67 = 0x00;
+ else if (pScrn->bitsPerPixel == 16) {
+ /* XV support needs STREAMS in depth 16 */
+ ps3v->NeedSTREAMS = TRUE;
+ S3VInitSTREAMS(pScrn, new->STREAMS, mode);
+ if (pScrn->weight.green == 5)
+ new->CR67 = 0x30 | 0x4; /* 15bpp */
+ else
+ new->CR67 = 0x50 | 0x4; /* 16bpp */
+ }
+ else if ((pScrn->bitsPerPixel == 24) ) {
+ new->CR67 = 0x74; /* 24bpp, STREAMS */
+ /* Flag STREAMS proc. required */
+ ps3v->NeedSTREAMS = TRUE;
+ S3VInitSTREAMS(pScrn, new->STREAMS, mode);
+ }
+ else if (pScrn->bitsPerPixel == 32) {
+ new->CR67 = 0xd0; /* 32bpp */
+ /* Missing STREAMs and other stuff here? KJB */
+ /* new->MMPR0 = 0xc098; / Adjust FIFO slots */
+ }
+ {
+ unsigned char ndiv;
+ if (S3_ViRGE_MX_SERIES(ps3v->Chipset)) {
+ unsigned char sr8;
+ VGAOUT8(0x3c4, 0x08); /* unlock extended SEQ regs */
+ sr8 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c5, 0x06);
+ VGAOUT8(0x3c4, 0x31);
+ if (VGAIN8(0x3c5) & 0x10) { /* LCD on */
+ if (!ps3v->LCDClk) { /* entered only once for first mode */
+ int h_lcd, v_lcd;
+ VGAOUT8(0x3c4, 0x61);
+ h_lcd = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x66);
+ h_lcd |= ((VGAIN8(0x3c5) & 0x02) << 7);
+ h_lcd = (h_lcd+1) * 8;
+ VGAOUT8(0x3c4, 0x69);
+ v_lcd = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x6e);
+ v_lcd |= ((VGAIN8(0x3c5) & 0x70) << 4);
+ v_lcd++;
+
+ /* check if first mode has physical LCD resolution */
+ if (pScrn->modes->HDisplay == h_lcd && pScrn->modes->VDisplay == v_lcd)
+ ps3v->LCDClk = mode->Clock;
+ else {
+ int n1, n2, sr12, sr13, sr29;
+ VGAOUT8(0x3c4, 0x12);
+ sr12 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x13);
+ sr13 = VGAIN8(0x3c5) & 0x7f;
+ VGAOUT8(0x3c4, 0x29);
+ sr29 = VGAIN8(0x3c5);
+ n1 = sr12 & 0x1f;
+ n2 = ((sr12>>6) & 0x03) | ((sr29 & 0x01) << 2);
+ ps3v->LCDClk = ((int)(ps3v->refclk_fact * 1431818 * (sr13+2)) / (n1+2) / (1 << n2) + 50) / 100;
+ }
+ }
+ S3VCommonCalcClock(pScrn, mode,
+ (int)(ps3v->LCDClk / ps3v->refclk_fact),
+ 1, 1, 31, 0, 4,
+ 170000, 340000, &new->SR13, &ndiv);
+ }
+ else
+ S3VCommonCalcClock(pScrn, mode,
+ (int)(dclk / ps3v->refclk_fact),
+ 1, 1, 31, 0, 4,
+ 170000, 340000, &new->SR13, &ndiv);
+ VGAOUT8(0x3c4, 0x08);
+ VGAOUT8(0x3c5, sr8);
+ }
+ else /* S3_ViRGE_GX2 */
+ S3VCommonCalcClock(pScrn, mode, dclk, 1, 1, 31, 0, 4,
+ 170000, 340000, &new->SR13, &ndiv);
+ new->SR29 = ndiv >> 7;
+ new->SR12 = (ndiv & 0x1f) | ((ndiv & 0x60) << 1);
+ }
+ } /* end GX2 or MX if() */
+ else if(S3_TRIO_3D_SERIES(ps3v->Chipset)) {
+ new->SR0F = 0x00;
+ if (pScrn->bitsPerPixel == 8) {
+ if(dclk > 115000) { /* We need pixmux */
+ new->CR67 = 0x10;
+ new->SR15 |= 0x10; /* Set DCLK/2 bit */
+ new->SR18 = 0x80; /* Enable pixmux */
+ }
+ }
+ else if ((pScrn->bitsPerPixel == 16) && (pScrn->weight.green == 5)) {
+ if(dclk > 115000) {
+ new->CR67 = 0x20;
+ new->SR15 |= 0x10;
+ new->SR18 = 0x80;
+ new->SR0F = 0x10;
+ } else {
+ new->CR67 = 0x30; /* 15bpp */
+ }
+ }
+ else if (pScrn->bitsPerPixel == 16) {
+ if(dclk > 115000) {
+ new->CR67 = 0x40;
+ new->SR15 |= 0x10;
+ new->SR18 = 0x80;
+ new->SR0F = 0x10;
+ } else {
+ new->CR67 = 0x50;
+ }
+ }
+ else if (pScrn->bitsPerPixel == 24) {
+ new->CR67 = 0xd0 | 0x0c;
+ ps3v->NeedSTREAMS = TRUE;
+ S3VInitSTREAMS(pScrn, new->STREAMS, mode);
+ new->MMPR0 = 0xc000; /* Adjust FIFO slots */
+ }
+ else if (pScrn->bitsPerPixel == 32) {
+ new->CR67 = 0xd0 | 0x0c;
+ ps3v->NeedSTREAMS = TRUE;
+ S3VInitSTREAMS(pScrn, new->STREAMS, mode);
+ new->MMPR0 = 0x10000; /* Still more FIFO slots */
+ new->SR0F = 0x10;
+ }
+ S3VCommonCalcClock(pScrn, mode, dclk, 1, 1, 31, 0, 4,
+ 230000, 460000, &new->SR13, &new->SR12);
+ } /* end TRIO_3D if() */
+ else if(ps3v->Chipset == S3_ViRGE_DXGX) {
+ if (pScrn->bitsPerPixel == 8) {
+ if(dclk > 80000) { /* We need pixmux */
+ new->CR67 = 0x10;
+ new->SR15 |= 0x10; /* Set DCLK/2 bit */
+ new->SR18 = 0x80; /* Enable pixmux */
+ }
+ }
+ else if ((pScrn->bitsPerPixel == 16) && (pScrn->weight.green == 5)) {
+ new->CR67 = 0x30; /* 15bpp */
+ }
+ else if (pScrn->bitsPerPixel == 16) {
+ if(mode->Flags & V_DBLSCAN)
+ {
+ new->CR67 = 0x50;
+ }
+ else
+ {
+ new->CR67 = 0x50 | 0x0c;
+ /* Flag STREAMS proc. required */
+ /* XV support needs STREAMS in depth 16 */
+ ps3v->NeedSTREAMS = TRUE;
+ S3VInitSTREAMS(pScrn, new->STREAMS, mode);
+ }
+ if( ps3v->XVideo )
+ {
+ new->MMPR0 = 0x107c02; /* Adjust FIFO slots, overlay */
+ }
+ else
+ {
+ new->MMPR0 = 0xc000; /* Adjust FIFO slots */
+ }
+ }
+ else if (pScrn->bitsPerPixel == 24) {
+ new->CR67 = 0xd0 | 0x0c;
+ /* Flag STREAMS proc. required */
+ ps3v->NeedSTREAMS = TRUE;
+ S3VInitSTREAMS(pScrn, new->STREAMS, mode);
+ if( ps3v->XVideo )
+ {
+ new->MMPR0 = 0x107c02; /* Adjust FIFO slots, overlay */
+ }
+ else
+ {
+ new->MMPR0 = 0xc000; /* Adjust FIFO slots */
+ }
+ }
+ else if (pScrn->bitsPerPixel == 32) {
+ new->CR67 = 0xd0 | 0x0c;
+ /* Flag STREAMS proc. required */
+ ps3v->NeedSTREAMS = TRUE;
+ S3VInitSTREAMS(pScrn, new->STREAMS, mode);
+ new->MMPR0 = 0x10000; /* Still more FIFO slots */
+ }
+ S3VCommonCalcClock(pScrn, mode, dclk, 1, 1, 31, 0, 3,
+ 135000, 270000, &new->SR13, &new->SR12);
+ } /* end DXGX if() */
+ else { /* Everything else ... (only ViRGE) */
+ if (pScrn->bitsPerPixel == 8) {
+ if(dclk > 80000) { /* We need pixmux */
+ new->CR67 = 0x10;
+ new->SR15 |= 0x10; /* Set DCLK/2 bit */
+ new->SR18 = 0x80; /* Enable pixmux */
+ }
+ }
+ else if ((pScrn->bitsPerPixel == 16) && (pScrn->weight.green == 5)) {
+ new->CR67 = 0x30; /* 15bpp */
+ }
+ else if (pScrn->bitsPerPixel == 16) {
+ new->CR67 = 0x50;
+ }
+ else if (pScrn->bitsPerPixel == 24) {
+ new->CR67 = 0xd0 | 0x0c;
+ /* Flag STREAMS proc. required */
+ ps3v->NeedSTREAMS = TRUE;
+ S3VInitSTREAMS(pScrn, new->STREAMS, mode);
+ new->MMPR0 = 0xc000; /* Adjust FIFO slots */
+ }
+ else if (pScrn->bitsPerPixel == 32) {
+ new->CR67 = 0xd0 | 0x0c;
+ /* Flag STREAMS proc. required */
+ ps3v->NeedSTREAMS = TRUE;
+ S3VInitSTREAMS(pScrn, new->STREAMS, mode);
+ new->MMPR0 = 0x10000; /* Still more FIFO slots */
+ }
+ S3VCommonCalcClock(pScrn, mode, dclk, 1, 1, 31, 0, 3,
+ 135000, 270000, &new->SR13, &new->SR12);
+ } /* end great big if()... */
+
+
+ /* Now adjust the value of the FIFO based upon options specified */
+ if( ps3v->fifo_moderate ) {
+ if(pScrn->bitsPerPixel < 24)
+ new->MMPR0 -= 0x8000;
+ else
+ new->MMPR0 -= 0x4000;
+ }
+ else if( ps3v->fifo_aggressive ) {
+ if(pScrn->bitsPerPixel < 24)
+ new->MMPR0 -= 0xc000;
+ else
+ new->MMPR0 -= 0x6000;
+ }
+
+ /* If we have an interlace mode, set the interlace bit. Note that mode
+ * vertical timings are already adjusted by the standard VGA code
+ */
+ if(mode->Flags & V_INTERLACE) {
+ new->CR42 = 0x20; /* Set interlace mode */
+ }
+ else {
+ new->CR42 = 0x00;
+ }
+
+ if(S3_ViRGE_GX2_SERIES(ps3v->Chipset) ||
+ S3_ViRGE_MX_SERIES(ps3v->Chipset) )
+ {
+ new->CR34 = 0;
+ }
+ else
+ {
+ /* Set display fifo */
+ new->CR34 = 0x10;
+ }
+ /* Now we adjust registers for extended mode timings */
+ /* This is taken without change from the accel/s3_virge code */
+
+ i = ((((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8) |
+ ((((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) |
+ ((((mode->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) |
+ ((mode->CrtcHSyncStart & 0x800) >> 7);
+
+ if ((mode->CrtcHSyncEnd >> 3) - (mode->CrtcHSyncStart >> 3) > 64)
+ i |= 0x08; /* add another 64 DCLKs to blank pulse width */
+
+ if ((mode->CrtcHSyncEnd >> 3) - (mode->CrtcHSyncStart >> 3) > 32)
+ i |= 0x20; /* add another 32 DCLKs to hsync pulse width */
+
+ /* video playback chokes if sync start and display end are equal */
+ if (mode->CrtcHSyncStart - mode->CrtcHDisplay < ps3v->HorizScaleFactor) {
+ int tmp = vganew->CRTC[4] + ((i&0x10)<<4) + ps3v->HorizScaleFactor;
+ vganew->CRTC[4] = tmp & 0xff;
+ i |= ((tmp >> 4) & 0x10);
+ }
+
+ j = ( vganew->CRTC[0] + ((i&0x01)<<8)
+ + vganew->CRTC[4] + ((i&0x10)<<4) + 1) / 2;
+
+ if (j-(vganew->CRTC[4] + ((i&0x10)<<4)) < 4) {
+ if (vganew->CRTC[4] + ((i&0x10)<<4) + 4 <= vganew->CRTC[0]+ ((i&0x01)<<8))
+ j = vganew->CRTC[4] + ((i&0x10)<<4) + 4;
+ else
+ j = vganew->CRTC[0]+ ((i&0x01)<<8) + 1;
+ }
+ new->CR3B = j & 0xFF;
+ i |= (j & 0x100) >> 2;
+ new->CR3C = (vganew->CRTC[0] + ((i&0x01)<<8))/2;
+ new->CR5D = i;
+
+ new->CR5E = (((mode->CrtcVTotal - 2) & 0x400) >> 10) |
+ (((mode->CrtcVDisplay - 1) & 0x400) >> 9) |
+ (((mode->CrtcVSyncStart) & 0x400) >> 8) |
+ (((mode->CrtcVSyncStart) & 0x400) >> 6) | 0x40;
+
+
+ width = (pScrn->displayWidth * (pScrn->bitsPerPixel / 8))>> 3;
+ vganew->CRTC[19] = 0xFF & width;
+ new->CR51 = (0x300 & width) >> 4; /* Extension bits */
+
+ /* Set doublescan */
+ if( mode->Flags & V_DBLSCAN)
+ vganew->CRTC[9] |= 0x80;
+
+ /* And finally, select clock source 2 for programmable PLL */
+ vganew->MiscOutReg |= 0x0c;
+
+
+ new->CR33 = 0x20;
+ if (S3_TRIO_3D_2X_SERIES(ps3v->Chipset) || S3_ViRGE_GX2_SERIES(ps3v->Chipset)
+ /* MXTESTME */ || S3_ViRGE_MX_SERIES(ps3v->Chipset) )
+ {
+ new->CR85 = 0x12; /* avoid sreen flickering */
+ /* by increasing FIFO filling, larger # fills FIFO from memory earlier */
+ /* on GX2 this affects all depths, not just those running STREAMS. */
+ /* new, secondary stream settings. */
+ new->CR87 = 0x10;
+ /* gx2 - set up in XV init code */
+ new->CR92 = 0x00;
+ new->CR93 = 0x00;
+ /* gx2 primary mclk timeout, def=0xb */
+ new->CR7B = 0xb;
+ /* gx2 secondary mclk timeout, def=0xb */
+ new->CR7D = 0xb;
+ }
+ if (ps3v->Chipset == S3_ViRGE_DXGX || S3_TRIO_3D_SERIES(ps3v->Chipset)) {
+ new->CR86 = 0x80; /* disable DAC power saving to avoid bright left edge */
+ }
+ if (ps3v->Chipset == S3_ViRGE_DXGX || S3_ViRGE_GX2_SERIES(ps3v->Chipset) ||
+ S3_ViRGE_MX_SERIES(ps3v->Chipset) || S3_TRIO_3D_SERIES(ps3v->Chipset)) {
+ int dbytes = pScrn->displayWidth * ((pScrn->bitsPerPixel+7)/8);
+ new->CR91 = (dbytes + 7) / 8;
+ new->CR90 = (((dbytes + 7) / 8) >> 8) | 0x80;
+ }
+
+
+ /* Now we handle various XConfig memory options and others */
+
+ VGAOUT8(vgaCRIndex, 0x36);
+ new->CR36 = VGAIN8(vgaCRReg);
+ /* option "slow_edodram" sets EDO to 2 cycle mode on ViRGE */
+ if (ps3v->Chipset == S3_ViRGE) {
+ if( ps3v->slow_edodram )
+ new->CR36 = (new->CR36 & 0xf3) | 0x08;
+ else
+ new->CR36 &= 0xf3;
+ }
+
+ /* Option "fpm_vram" for ViRGE_VX sets memory in fast page mode */
+ if (ps3v->Chipset == S3_ViRGE_VX) {
+ if( ps3v->fpm_vram )
+ new->CR36 |= 0x0c;
+ else
+ new->CR36 &= ~0x0c;
+ }
+
+ /* S3_INVERT_VCLK was defaulted to 0 */
+ /* in 3.3.3 and never changed. */
+ /* Also, bit 0 is never set in 3.9Nm, */
+ /* so I left this out for 4.0. */
+#if 0
+ if (mode->Private[0] & (1 << S3_INVERT_VCLK)) {
+ if (mode->Private[S3_INVERT_VCLK])
+ new->CR67 |= 1;
+ else
+ new->CR67 &= ~1;
+ }
+#endif
+ /* S3_BLANK_DELAY settings based on */
+ /* defaults only. From 3.3.3 */
+ {
+ int blank_delay;
+
+ if(ps3v->Chipset == S3_ViRGE_VX)
+ /* these values need to be changed once CR67_1 is set
+ for gamma correction (see S3V server) ! */
+ if (pScrn->bitsPerPixel == 8)
+ blank_delay = 0x00;
+ else if (pScrn->bitsPerPixel == 16)
+ blank_delay = 0x00;
+ else
+ blank_delay = 0x51;
+ else
+ if (pScrn->bitsPerPixel == 8)
+ blank_delay = 0x00;
+ else if (pScrn->bitsPerPixel == 16)
+ blank_delay = 0x02;
+ else
+ blank_delay = 0x04;
+
+ if (ps3v->Chipset == S3_ViRGE_VX)
+ new->CR6D = blank_delay;
+ else {
+ new->CR65 = (new->CR65 & ~0x38)
+ | (blank_delay & 0x07) << 3;
+ VGAOUT8(vgaCRIndex, 0x6d);
+ new->CR6D = VGAIN8(vgaCRReg);
+ }
+ }
+ /* S3_EARLY_SC was defaulted to 0 */
+ /* in 3.3.3 and never changed. */
+ /* Also, bit 1 is never set in 3.9Nm, */
+ /* so I left this out for 4.0. */
+#if 0
+ if (mode->Private[0] & (1 << S3_EARLY_SC)) {
+ if (mode->Private[S3_EARLY_SC])
+ new->CR65 |= 2;
+ else
+ new->CR65 &= ~2;
+ }
+#endif
+
+ VGAOUT8(vgaCRIndex, 0x68);
+ new->CR68 = VGAIN8(vgaCRReg);
+ new->CR69 = 0;
+
+ /* Flat panel centering and expansion registers */
+ if (S3_ViRGE_MX_SERIES(ps3v->Chipset) && (ps3v->lcd_center)) {
+ new->SR54 = 0x10 ;
+ new->SR55 = 0x80 ;
+ new->SR56 = 0x10 ;
+ new->SR57 = 0x80 ;
+ } else {
+ new->SR54 = 0x1f ;
+ new->SR55 = 0x9f ;
+ new->SR56 = 0x1f ;
+ new->SR57 = 0xff ;
+ }
+
+ pScrn->vtSema = TRUE;
+
+ /* Do it! Write the mode registers */
+ /* to hardware, start STREAMS if */
+ /* needed, etc. */
+ S3VWriteMode( pScrn, vganew, new );
+ /* Adjust the viewport */
+ S3VAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+
+ return TRUE;
+}
+
+
+/*
+ * This is called at the end of each server generation. It restores the
+ * original (text) mode. It should also unmap the video memory, and free
+ * any per-generation data allocated by the driver. It should finish
+ * by unwrapping and calling the saved CloseScreen function.
+ */
+
+/* Mandatory */
+static Bool
+S3VCloseScreen(int scrnIndex, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ S3VPtr ps3v = S3VPTR(pScrn);
+ vgaRegPtr vgaSavePtr = &hwp->SavedReg;
+ S3VRegPtr S3VSavePtr = &ps3v->SavedReg;
+
+ /* Like S3VRestore, but uses passed */
+ /* mode registers. */
+ if (pScrn->vtSema) {
+ S3VWriteMode(pScrn, vgaSavePtr, S3VSavePtr);
+ vgaHWLock(hwp);
+ S3VDisableMmio(pScrn);
+ S3VUnmapMem(pScrn);
+ }
+
+ if (ps3v->EXADriverPtr) {
+ exaDriverFini(pScreen);
+ ps3v->EXADriverPtr = NULL;
+ }
+
+ if (ps3v->AccelInfoRec) {
+ XAADestroyInfoRec(ps3v->AccelInfoRec);
+ ps3v->AccelInfoRec = NULL;
+ }
+
+ if (ps3v->DGAModes)
+ xfree(ps3v->DGAModes);
+
+ pScrn->vtSema = FALSE;
+
+ pScreen->CloseScreen = ps3v->CloseScreen;
+
+ return (*pScreen->CloseScreen)(scrnIndex, pScreen);
+}
+
+
+
+
+/* Do screen blanking */
+
+/* Mandatory */
+static Bool
+S3VSaveScreen(ScreenPtr pScreen, int mode)
+{
+ return vgaHWSaveScreen(pScreen, mode);
+}
+
+
+
+
+
+/* This function inits the STREAMS processor variables.
+ * This has essentially been taken from the accel/s3_virge code and the databook.
+ */
+static void
+S3VInitSTREAMS(ScrnInfoPtr pScrn, unsigned int *streams, DisplayModePtr mode)
+{
+ PVERB5(" S3VInitSTREAMS\n");
+
+ switch (pScrn->bitsPerPixel)
+ {
+ case 16:
+ streams[0] = 0x05000000;
+ break;
+ case 24:
+ /* data format 8.8.8 (24 bpp) */
+ streams[0] = 0x06000000;
+ break;
+ case 32:
+ /* one more bit for X.8.8.8, 32 bpp */
+ streams[0] = 0x07000000;
+ break;
+ }
+ /* NO chroma keying... */
+ streams[1] = 0x0;
+ /* Secondary stream format KRGB-16 */
+ /* data book suggestion... */
+ streams[2] = 0x03000000;
+
+ streams[3] = 0x0;
+
+ streams[4] = 0x0;
+ /* use 0x01000000 for primary over second. */
+ /* use 0x0 for second over prim. */
+ streams[5] = 0x01000000;
+
+ streams[6] = 0x0;
+
+ streams[7] = 0x0;
+ /* Stride is 3 bytes for 24 bpp mode and */
+ /* 4 bytes for 32 bpp. */
+ switch(pScrn->bitsPerPixel)
+ {
+ case 16:
+ streams[8] =
+ pScrn->displayWidth * 2;
+ break;
+ case 24:
+ streams[8] =
+ pScrn->displayWidth * 3;
+ break;
+ case 32:
+ streams[8] =
+ pScrn->displayWidth * 4;
+ break;
+ }
+ /* Choose fbaddr0 as stream source. */
+ streams[9] = 0x0;
+ streams[10] = 0x0;
+ streams[11] = 0x0;
+ streams[12] = 0x1;
+
+ /* Set primary stream on top of secondary */
+ /* stream. */
+ streams[13] = 0xc0000000;
+ /* Vertical scale factor. */
+ streams[14] = 0x0;
+
+ streams[15] = 0x0;
+ /* Vertical accum. initial value. */
+ streams[16] = 0x0;
+ /* X and Y start coords + 1. */
+ streams[18] = 0x00010001;
+
+ /* Specify window Width -1 and Height of */
+ /* stream. */
+ streams[19] =
+ (mode->HDisplay - 1) << 16 |
+ (mode->VDisplay);
+
+ /* Book says 0x07ff07ff. */
+ streams[20] = 0x07ff07ff;
+
+ streams[21] = 0x00010001;
+
+}
+
+
+
+
+/* Used to adjust start address in frame buffer. We use the new
+ * CR69 reg for this purpose instead of the older CR31/CR51 combo.
+ * If STREAMS is running, we program the STREAMS start addr. registers.
+ */
+
+void
+S3VAdjustFrame(int scrnIndex, int x, int y, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ S3VPtr ps3v = S3VPTR(pScrn);
+ int Base;
+ int vgaCRIndex, vgaCRReg, vgaIOBase;
+ vgaIOBase = hwp->IOBase;
+ vgaCRIndex = vgaIOBase + 4;
+ vgaCRReg = vgaIOBase + 5;
+
+ if(ps3v->ShowCache && y)
+ y += pScrn->virtualY - 1;
+
+ if( (ps3v->STREAMSRunning == FALSE) ||
+ S3_ViRGE_GX2_SERIES(ps3v->Chipset) || S3_ViRGE_MX_SERIES(ps3v->Chipset)) {
+ Base = ((y * pScrn->displayWidth + x)
+ * (pScrn->bitsPerPixel / 8)) >> 2;
+ if (pScrn->bitsPerPixel == 24)
+ Base = Base+2 - (Base+2) % 3;
+ if (pScrn->bitsPerPixel == 16)
+ if (S3_TRIO_3D_SERIES(ps3v->Chipset) && pScrn->modes->Clock > 115000)
+ Base &= ~1;
+
+ /* Now program the start address registers */
+ VGAOUT16(vgaCRIndex, (Base & 0x00FF00) | 0x0C);
+ VGAOUT16(vgaCRIndex, ((Base & 0x00FF) << 8) | 0x0D);
+ VGAOUT8(vgaCRIndex, 0x69);
+ VGAOUT8(vgaCRReg, (Base & 0x0F0000) >> 16);
+ }
+ else { /* Change start address for STREAMS case */
+ VerticalRetraceWait();
+ if(ps3v->Chipset == S3_ViRGE_VX)
+ OUTREG(PSTREAM_FBADDR0_REG,
+ ((y * pScrn->displayWidth + (x & ~7)) *
+ pScrn->bitsPerPixel / 8));
+ else
+ OUTREG(PSTREAM_FBADDR0_REG,
+ ((y * pScrn->displayWidth + (x & ~3)) *
+ pScrn->bitsPerPixel / 8));
+ }
+
+ return;
+}
+
+
+
+
+/* Usually mandatory */
+Bool
+S3VSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
+{
+ return S3VModeInit(xf86Screens[scrnIndex], mode);
+}
+
+
+
+void S3VLoadPalette(
+ ScrnInfoPtr pScrn,
+ int numColors,
+ int *indicies,
+ LOCO *colors,
+ VisualPtr pVisual
+){
+ S3VPtr ps3v = S3VPTR(pScrn);
+ int i, index;
+
+ for(i = 0; i < numColors; i++) {
+ index = indicies[i];
+ VGAOUT8(0x3c8, index);
+ VGAOUT8(0x3c9, colors[index].red);
+ VGAOUT8(0x3c9, colors[index].green);
+ VGAOUT8(0x3c9, colors[index].blue);
+ }
+}
+
+
+/*
+ * Functions to support getting a ViRGE card into MMIO mode if it fails to
+ * default to MMIO enabled.
+ */
+
+void
+S3VEnableMmio(ScrnInfoPtr pScrn)
+{
+ vgaHWPtr hwp;
+ S3VPtr ps3v;
+ IOADDRESS vgaCRIndex, vgaCRReg;
+ unsigned char val;
+
+ PVERB5(" S3VEnableMmio\n");
+
+ hwp = VGAHWPTR(pScrn);
+ ps3v = S3VPTR(pScrn);
+ /*
+ * enable chipset (seen on uninitialized secondary cards)
+ * might not be needed once we use the VGA softbooter
+ * (EE 05/04/99)
+ */
+ vgaHWSetStdFuncs(hwp);
+ /*
+ * any access to the legacy VGA ports is done here.
+ * If legacy VGA is inaccessable the MMIO base _has_
+ * to be set correctly already and MMIO _has_ to be
+ * enabled.
+ */
+ val = inb(hwp->PIOOffset + 0x3C3); /*@@@EE*/
+ outb(hwp->PIOOffset + 0x3C3, val | 0x01);
+ /*
+ * set CR registers to color mode
+ * in mono mode extended CR registers
+ * are not accessible. (EE 05/04/99)
+ */
+ val = inb(hwp->PIOOffset + VGA_MISC_OUT_R); /*@@@EE*/
+ outb(hwp->PIOOffset + VGA_MISC_OUT_W, val | 0x01);
+ vgaHWGetIOBase(hwp); /* Get VGA I/O base */
+ vgaCRIndex = hwp->PIOOffset + hwp->IOBase + 4;
+ vgaCRReg = vgaCRIndex + 1;
+#if 1
+ /*
+ * set linear base register to the PCI register values
+ * some DX chipsets don't seem to do it automatically
+ * (EE 06/03/99)
+ */
+ outb(vgaCRIndex, 0x59); /*@@@EE*/
+ outb(vgaCRReg, ps3v->PciInfo->memBase[0] >> 24);
+ outb(vgaCRIndex, 0x5A);
+ outb(vgaCRReg, ps3v->PciInfo->memBase[0] >> 16);
+ outb(vgaCRIndex, 0x53);
+#endif
+ /* Save register for restore */
+ ps3v->EnableMmioCR53 = inb(vgaCRReg);
+ /* Enable new MMIO, if TRIO mmio is already */
+ /* enabled, then it stays enabled. */
+ outb(vgaCRReg, ps3v->EnableMmioCR53 | 0x08);
+ outb(hwp->PIOOffset + VGA_MISC_OUT_W, val);
+ if (S3_TRIO_3D_SERIES(ps3v->Chipset)) {
+ outb(vgaCRIndex, 0x40);
+ val = inb(vgaCRReg);
+ outb(vgaCRReg, val | 1);
+ }
+}
+
+
+
+void
+S3VDisableMmio(ScrnInfoPtr pScrn)
+{
+ vgaHWPtr hwp;
+ S3VPtr ps3v;
+ IOADDRESS vgaCRIndex, vgaCRReg;
+
+ PVERB5(" S3VDisableMmio\n");
+
+ hwp = VGAHWPTR(pScrn);
+ ps3v = S3VPTR(pScrn);
+
+ vgaCRIndex = hwp->PIOOffset + hwp->IOBase + 4;
+ vgaCRReg = vgaCRIndex + 1;
+ outb(vgaCRIndex, 0x53);
+ /* Restore register's original state */
+ outb(vgaCRReg, ps3v->EnableMmioCR53);
+ if (S3_TRIO_3D_SERIES(ps3v->Chipset)) {
+ unsigned char val;
+ outb(vgaCRIndex, 0x40);
+ val = inb(vgaCRReg);
+ outb(vgaCRReg, val | 1);
+ }
+}
+
+
+
+/* This function is used to debug, it prints out the contents of s3 regs */
+
+static void
+S3VPrintRegs(ScrnInfoPtr pScrn)
+{
+ unsigned char tmp1, tmp2;
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ S3VPtr ps3v = S3VPTR(pScrn);
+ int vgaCRIndex, vgaCRReg, vgaIOBase, vgaIR;
+ vgaIOBase = hwp->IOBase;
+ vgaCRIndex = vgaIOBase + 4;
+ vgaCRReg = vgaIOBase + 5;
+ vgaIR = vgaIOBase + 0xa;
+
+/* All registers */
+/* New formatted registers, matches s3rc (sort of) */
+ xf86DrvMsgVerb( pScrn->scrnIndex, X_INFO, VERBLEV, "START register dump ------------------\n");
+ xf86ErrorFVerb(VERBLEV, "Misc Out[3CC]\n ");
+ xf86ErrorFVerb(VERBLEV, "%02x\n",VGAIN8(0x3cc));
+
+ xf86ErrorFVerb(VERBLEV, "\nCR[00-2f]\n ");
+ for(tmp1=0x0;tmp1<=0x2f;tmp1++){
+ VGAOUT8(vgaCRIndex, tmp1);
+ xf86ErrorFVerb(VERBLEV, "%02x ",VGAIN8(vgaCRReg));
+ if((tmp1 & 0x3) == 0x3) xf86ErrorFVerb(VERBLEV, " ");
+ if((tmp1 & 0xf) == 0xf) xf86ErrorFVerb(VERBLEV, "\n ");
+ }
+
+ xf86ErrorFVerb(VERBLEV, "\nSR[00-27]\n ");
+ for(tmp1=0x0;tmp1<=0x27;tmp1++){
+ VGAOUT8(0x3c4, tmp1);
+ xf86ErrorFVerb(VERBLEV, "%02x ",VGAIN8(0x3c5));
+ if((tmp1 & 0x3) == 0x3) xf86ErrorFVerb(VERBLEV, " ");
+ if((tmp1 & 0xf) == 0xf) xf86ErrorFVerb(VERBLEV, "\n ");
+ }
+ xf86ErrorFVerb(VERBLEV, "\n"); /* odd hex number of digits... */
+
+ xf86ErrorFVerb(VERBLEV, "\nGr Cont GR[00-0f]\n ");
+ for(tmp1=0x0;tmp1<=0x0f;tmp1++){
+ VGAOUT8(0x3ce, tmp1);
+ xf86ErrorFVerb(VERBLEV, "%02x ",VGAIN8(0x3cf));
+ if((tmp1 & 0x3) == 0x3) xf86ErrorFVerb(VERBLEV, " ");
+ if((tmp1 & 0xf) == 0xf) xf86ErrorFVerb(VERBLEV, "\n ");
+ }
+
+ xf86ErrorFVerb(VERBLEV, "\nAtt Cont AR[00-1f]\n ");
+ VGAIN8(vgaIR); /* preset AR flip-flop by reading 3DA, ignore return value */
+ tmp2=VGAIN8(0x3c0) & 0x20;
+ for(tmp1=0x0;tmp1<=0x1f;tmp1++){
+ VGAIN8(vgaIR); /* preset AR flip-flop by reading 3DA, ignore return value */
+ VGAOUT8(0x3c0, (tmp1 & ~0x20) | tmp2);
+ xf86ErrorFVerb(VERBLEV, "%02x ",VGAIN8(0x3c1));
+ if((tmp1 & 0x3) == 0x3) xf86ErrorFVerb(VERBLEV, " ");
+ if((tmp1 & 0xf) == 0xf) xf86ErrorFVerb(VERBLEV, "\n ");
+ }
+
+ xf86ErrorFVerb(VERBLEV, "\nCR[30-6f]\n ");
+ for(tmp1=0x30;tmp1<=0x6f;tmp1++){
+ VGAOUT8(vgaCRIndex, tmp1);
+ xf86ErrorFVerb(VERBLEV, "%02x ",VGAIN8(vgaCRReg));
+ if((tmp1 & 0x3) == 0x3) xf86ErrorFVerb(VERBLEV, " ");
+ if((tmp1 & 0xf) == 0xf) xf86ErrorFVerb(VERBLEV, "\n ");
+ }
+
+ xf86ErrorFVerb(VERBLEV, "\n");
+ xf86DrvMsgVerb( pScrn->scrnIndex, X_INFO, VERBLEV, "END register dump --------------------\n");
+}
+
+/* this is just a debugger hook */
+/*
+void print_subsys_stat(void *s3vMmioMem);
+void
+print_subsys_stat(void *s3vMmioMem)
+{
+ ErrorF("IN_SUBSYS_STAT() = %x\n", IN_SUBSYS_STAT());
+ return;
+}
+*/
+
+/*
+ * S3VDisplayPowerManagementSet --
+ *
+ * Sets VESA Display Power Management Signaling (DPMS) Mode.
+ */
+static void
+S3VDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
+ int flags)
+{
+ S3VPtr ps3v;
+ unsigned char sr8 = 0x0, srd = 0x0;
+ char modestr[][40] = { "On","Standby","Suspend","Off" };
+
+ ps3v = S3VPTR(pScrn);
+
+ /* unlock extended sequence registers */
+
+ VGAOUT8(0x3c4, 0x08);
+ sr8 = VGAIN8(0x3c5);
+ sr8 |= 0x6;
+ VGAOUT8(0x3c5, sr8);
+
+ /* load SRD */
+ VGAOUT8(0x3c4, 0x0d);
+ srd = VGAIN8(0x3c5);
+
+ srd &= 0x03; /* clear the sync control bits of srd */
+
+ switch (PowerManagementMode) {
+ case DPMSModeOn:
+ /* Screen: On; HSync: On, VSync: On */
+ break;
+ case DPMSModeStandby:
+ /* Screen: Off; HSync: Off, VSync: On */
+ srd |= 0x10;
+ break;
+ case DPMSModeSuspend:
+ /* Screen: Off; HSync: On, VSync: Off */
+ srd |= 0x40;
+ break;
+ case DPMSModeOff:
+ /* Screen: Off; HSync: Off, VSync: Off */
+ srd |= 0x50;
+ break;
+ default:
+ xf86ErrorFVerb(VERBLEV, "Invalid PowerManagementMode %d passed to S3VDisplayPowerManagementSet\n", PowerManagementMode);
+ break;
+ }
+
+ VGAOUT8(0x3c4, 0x0d);
+ VGAOUT8(0x3c5, srd);
+
+ xf86ErrorFVerb(VERBLEV, "Power Manag: set:%s\n",
+ modestr[PowerManagementMode]);
+
+ return;
+}
+
+static unsigned int
+S3Vddc1Read(ScrnInfoPtr pScrn)
+{
+ register vgaHWPtr hwp = VGAHWPTR(pScrn);
+ register CARD32 tmp;
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ while (hwp->readST01(hwp)&0x8) {};
+ while (!(hwp->readST01(hwp)&0x8)) {};
+
+ tmp = (INREG(DDC_REG));
+ return ((unsigned int) (tmp & 0x08));
+}
+
+static Bool
+S3Vddc1(int scrnIndex)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ S3VPtr ps3v = S3VPTR(pScrn);
+ CARD32 tmp;
+ Bool success = FALSE;
+ xf86MonPtr pMon;
+
+ /* initialize chipset */
+ tmp = INREG(DDC_REG);
+ OUTREG(DDC_REG,(tmp | 0x12));
+
+ if ((pMon = xf86PrintEDID(
+ xf86DoEDID_DDC1(scrnIndex,vgaHWddc1SetSpeedWeak(),
+ S3Vddc1Read))) != NULL)
+ success = TRUE;
+ xf86SetDDCproperties(pScrn,pMon);
+
+ /* undo initialization */
+ OUTREG(DDC_REG,(tmp));
+ return success;
+}
+
+static Bool
+S3Vddc2(int scrnIndex)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ if ( xf86LoadSubModule(pScrn, "i2c") ) {
+ xf86LoaderReqSymLists(i2cSymbols,NULL);
+ if (S3V_I2CInit(pScrn)) {
+ CARD32 tmp = (INREG(DDC_REG));
+ OUTREG(DDC_REG,(tmp | 0x13));
+ xf86SetDDCproperties(pScrn,xf86PrintEDID(
+ xf86DoEDID_DDC2(pScrn->scrnIndex,ps3v->I2C)));
+ OUTREG(DDC_REG,tmp);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static void
+S3VProbeDDC(ScrnInfoPtr pScrn, int index)
+{
+ vbeInfoPtr pVbe;
+ if (xf86LoadSubModule(pScrn, "vbe")) {
+ pVbe = VBEInit(NULL,index);
+ ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
+ vbeFree(pVbe);
+ }
+}
+
+/*EOF*/
+
+
diff --git a/src/s3v_exa.c b/src/s3v_exa.c
new file mode 100644
index 0000000..c1df938
--- /dev/null
+++ b/src/s3v_exa.c
@@ -0,0 +1,326 @@
+/* The exa acceleration file for the S3 ViRGE driver. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "s3v.h"
+#include "regs3v.h"
+
+#include "miline.h"
+
+#include "servermd.h" /* LOG2_BYTES_PER_SCANLINE_PAD */
+
+static void S3VEXASync(
+ ScreenPtr pScreen,
+ int marker);
+
+static Bool S3VPrepareSolid(
+ PixmapPtr pPixmap,
+ int alu, Pixel planemask,
+ Pixel fg);
+
+static void S3VSolid(
+ PixmapPtr pPixmap,
+ int x1, int y1,
+ int x2, int y2);
+
+static void S3VDoneSolid(
+ PixmapPtr pPixmap);
+
+static Bool S3VPrepareCopy(
+ PixmapPtr pSrcPixmap,
+ PixmapPtr pDstPixmap,
+ int xdir, int ydir,
+ int alu, Pixel planemask);
+
+static void S3VCopy(
+ PixmapPtr pDstPixmap,
+ int srcX, int srcY,
+ int dstX, int dstY,
+ int width, int height);
+
+static void S3VDoneCopy(
+ PixmapPtr pDstPixmap);
+
+Bool S3VUploadToScreen(
+ PixmapPtr pDst,
+ int x, int y,
+ int w, int h,
+ char *src, int src_pitch);
+
+#if 1
+Bool S3VDownloadFromScreen(
+ PixmapPtr pSrc,
+ int x, int y,
+ int w, int h,
+ char *dst, int dst_pitch);
+#endif
+
+static int S3VGetCopyROP(int rop) {
+
+ int ALUCopyROP[16] =
+ {
+ 0x00, /*ROP_0 GXclear */
+ 0x88, /*ROP_DSa GXand */
+ 0x44, /*ROP_SDna GXandReverse */
+ 0xCC, /*ROP_S GXcopy */
+ 0x22, /*ROP_DSna GXandInverted */
+ 0xAA, /*ROP_D GXnoop */
+ 0x66, /*ROP_DSx GXxor */
+ 0xEE, /*ROP_DSo GXor */
+ 0x11, /*ROP_DSon GXnor */
+ 0x99, /*ROP_DSxn GXequiv */
+ 0x55, /*ROP_Dn GXinvert*/
+ 0xDD, /*ROP_SDno GXorReverse */
+ 0x33, /*ROP_Sn GXcopyInverted */
+ 0xBB, /*ROP_DSno GXorInverted */
+ 0x77, /*ROP_DSan GXnand */
+ 0xFF, /*ROP_1 GXset */
+ };
+
+ return (ALUCopyROP[rop]);
+
+}
+
+static int S3VGetCopyROP_PM(int rop) {
+
+ int ALUCopyROP_PM[16] =
+ {
+ 0x00, /*ROP_0*/ /* not used */
+ 0x75, /*ROP_DSPnoa*/
+ 0x45, /*ROP_DPSnaon*/
+ 0xCA, /*ROP_DPSDxax*/
+ 0xD5, /*ROP_DPSana*/
+ 0xAA, /*ROP_D*/ /* not used */
+ 0x6A, /*ROP_DPSax*/
+ 0xEA, /*ROP_DPSao*/
+ 0x15, /*ROP_DPSaon*/
+ 0x95, /*ROP_DPSaxn*/
+ 0x55, /*ROP_Dn*/ /* not used */
+ 0xD5, /*ROP_DPSanan*/
+ 0x2E, /*ROP_PSDPxox*/ /* is that correct ? */
+ 0xBA, /*ROP_DPSnao*/
+ 0x75, /*ROP_DSPnoan*/
+ 0xFF, /*ROP_1*/ /* not used */
+ };
+
+ return (ALUCopyROP_PM[rop]);
+
+}
+
+Bool
+S3VEXAInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ if (!(ps3v->EXADriverPtr = exaDriverAlloc())) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to allocate EXADriverRec.\n");
+ return FALSE;
+ }
+
+ ps3v->EXADriverPtr->exa_major = 2;
+ ps3v->EXADriverPtr->exa_minor = 0;
+
+ /* use the linear aperture */
+ ps3v->EXADriverPtr->memoryBase = ps3v->FBBase + pScrn->fbOffset;
+ ps3v->EXADriverPtr->memorySize = ps3v->EXAendfb;
+
+ /* No tile support ? */
+ ps3v->EXADriverPtr->offScreenBase = (pScrn->displayWidth * pScrn->bitsPerPixel >> 3) * pScrn->virtualY;
+
+ if (ps3v->EXADriverPtr->memorySize > ps3v->EXADriverPtr->offScreenBase) {
+ ps3v->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Not enough video RAM for EXA offscreen memory manager.\n");
+ }
+
+ /* No tile support ? */
+ ps3v->EXADriverPtr->pixmapPitchAlign = 32; /* ~31 */
+
+ if (ps3v->Chipset == S3_ViRGE_DXGX)
+ ps3v->EXADriverPtr->pixmapOffsetAlign = 64; /* quadword */
+
+ /* engine has 12 bit coordinates */
+ ps3v->EXADriverPtr->maxX = 1023;
+ ps3v->EXADriverPtr->maxY = 1023;
+
+ /* Sync */
+ ps3v->EXADriverPtr->WaitMarker = S3VEXASync;
+
+#if 1
+ /* Solid fill */
+ ps3v->EXADriverPtr->PrepareSolid = S3VPrepareSolid;
+ ps3v->EXADriverPtr->Solid = S3VSolid;
+ ps3v->EXADriverPtr->DoneSolid = S3VDoneSolid;
+
+ /* Copy */
+ ps3v->EXADriverPtr->PrepareCopy = S3VPrepareCopy;
+ ps3v->EXADriverPtr->Copy = S3VCopy;
+ ps3v->EXADriverPtr->DoneCopy = S3VDoneCopy;
+
+ /* Composite not implemented yet */
+ /* virge series only have one tmu */
+
+#endif
+
+#if 0
+ /* host data blit */
+ ps3v->EXADriverPtr->UploadToScreen = S3VUploadToScreen;
+#endif
+#if 0
+ ps3v->EXADriverPtr->DownloadFromScreen = S3VDownloadFromScreen;
+#endif
+
+ if(!exaDriverInit(pScreen, ps3v->EXADriverPtr)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "exaDriverinit failed.\n");
+ return FALSE;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "S3ViRGE EXA Acceleration enabled.\n");
+ return TRUE;
+ }
+
+}
+
+static void
+S3VEXASync(ScreenPtr pScreen, int marker)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ S3VPtr ps3v = S3VPTR(pScrn);
+ WaitIdleEmpty();
+}
+
+static Bool
+S3VPrepareSolid (PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ return FALSE;
+}
+
+static void
+S3VSolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ int w = x2 - x1;
+ int h = y2 - y1;
+
+ if ( !w || !h )
+ return;
+
+ WAITFIFO(2);
+ OUTREG(RWIDTH_HEIGHT, ((w -1) << 16) | h);
+ WAITCMD();
+ OUTREG(RDEST_XY, (x1 << 16) | y1);
+}
+
+static void
+S3VDoneSolid(PixmapPtr pPixmap)
+{
+}
+
+static Bool
+S3VPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, int ydir, int alu, Pixel Planemask)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ switch (pDstPixmap->drawable.bitsPerPixel) {
+ case 8: ps3v->CommonCmd = DRAW | DST_8BPP;
+ break;
+ case 16: ps3v->CommonCmd = DRAW | DST_16BPP;
+ break;
+ case 24: ps3v->CommonCmd = DRAW | DST_24BPP;
+ break;
+ }
+
+ ps3v->AccelCmd = ps3v->CommonCmd | S3VGetCopyROP(alu) | CMD_AUTOEXEC | CMD_BITBLT;
+ if(xdir > 0) ps3v->AccelCmd |= CMD_XP;
+ if(ydir > 0) ps3v->AccelCmd |= CMD_YP;
+
+ ps3v->dst_offset = exaGetPixmapOffset(pDstPixmap);
+ ps3v->dst_stride = exaGetPixmapPitch(pDstPixmap);
+
+ ps3v->src_offset = exaGetPixmapOffset(pSrcPixmap);
+ ps3v->src_stride = exaGetPixmapPitch(pSrcPixmap);
+
+ WAITFIFO(4); // wait for 4 registers to become free.
+ OUTREG(SRC_BASE, ps3v->src_offset);
+ OUTREG(DEST_BASE, ps3v->dst_offset);
+ OUTREG(DEST_SRC_STR, ps3v->src_stride | (ps3v->dst_stride << 16));
+ OUTREG(CMD_SET, ps3v->AccelCmd);
+ return TRUE;
+}
+
+static void
+S3VCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int width, int height)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ if (!width || !height) return;
+
+ width--;
+ if (!(ps3v->AccelCmd & CMD_XP)) {
+ srcX += width;
+ dstX += width;
+ }
+
+ if (!(ps3v->AccelCmd & CMD_YP)) {
+ srcY += height -1;
+ dstY += height -1;
+ }
+
+ WAITFIFO(3); // wait for 3 registers
+ OUTREG(RWIDTH_HEIGHT, (width << 16) | height);
+ OUTREG(RSRC_XY, (srcX << 16) | srcY);
+ WAITCMD();
+ OUTREG(RDEST_XY, (dstX << 16) | dstY);
+
+}
+
+static void
+S3VDoneCopy(PixmapPtr pDstPixmap)
+{
+}
+
+Bool
+S3VUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, int src_pitch)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ int i, j, dwords, Bpp;
+
+ Bpp = pDst->drawable.bitsPerPixel / 8;
+ dwords = ((w * Bpp) + 3) >> 2;
+
+ ps3v->src_offset = exaGetPixmapOffset(pDst);
+ ps3v->src_stride = exaGetPixmapPitch(pDst);
+
+ switch (pDst->drawable.bitsPerPixel) {
+ case 8: ps3v->CommonCmd = DRAW | DST_8BPP;
+ break;
+ case 16: ps3v->CommonCmd = DRAW | DST_16BPP;
+ break;
+ case 24: ps3v->CommonCmd = DRAW | DST_24BPP;
+ break;
+ }
+
+ ps3v->AccelCmd = ps3v->CommonCmd | 0xCC | CMD_XP | CMD_YP | CMD_BITBLT;
+ WAITFIFO(3);
+ OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16 | h));
+ OUTREG(RSRC_XY, (ps3v->src_offset << 16)| ps3v->src_stride);
+ WAITCMD();
+ OUTREG(CMD_SET, ps3v->AccelCmd);
+
+ return TRUE;
+}
diff --git a/src/s3v_hwcurs.c b/src/s3v_hwcurs.c
new file mode 100644
index 0000000..8ea3eeb
--- /dev/null
+++ b/src/s3v_hwcurs.c
@@ -0,0 +1,266 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/s3v_hwcurs.c,v 1.7 2003/02/04 02:20:50 dawes Exp $ */
+
+/*
+Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the XFree86 Project shall not
+be used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the XFree86 Project.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * s3v_hwcurs.c
+ * HW Cursor support for 4.0 design level
+ *
+ * S3 ViRGE driver
+ *
+ *
+ */
+
+
+#include "s3v.h"
+
+/* protos */
+
+static void S3VLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src);
+static void S3VShowCursor(ScrnInfoPtr pScrn);
+static void S3VHideCursor(ScrnInfoPtr pScrn);
+static void S3VSetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
+static void S3VSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg);
+
+
+/*
+ * Read/write to the DAC via MMIO
+ */
+
+#define inCRReg(reg) (VGAHWPTR(pScrn))->readCrtc( VGAHWPTR(pScrn), reg )
+#define outCRReg(reg, val) (VGAHWPTR(pScrn))->writeCrtc( VGAHWPTR(pScrn), reg, val )
+
+
+
+/****
+ *** HW Cursor
+ */
+static void
+S3VLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
+{
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ /*PVERB5(" S3VLoadCursorImage\n");*/
+
+ /* Load storage location. */
+ outCRReg( HWCURSOR_ADDR_LOW_CR4D, 0xff & (ps3v->FBCursorOffset/1024));
+ outCRReg( HWCURSOR_ADDR_HIGH_CR4C, (0x0f00 & (ps3v->FBCursorOffset/1024)) >> 8);
+
+ /* Copy cursor image to framebuffer storage */
+ memcpy( (ps3v->FBBase + ps3v->FBCursorOffset), src, 1024);
+
+}
+
+
+static void
+S3VShowCursor(ScrnInfoPtr pScrn)
+{
+ char tmp;
+
+ tmp = inCRReg(HWCURSOR_MODE_CR45);
+ /* Enable cursor */
+ outCRReg(HWCURSOR_MODE_CR45, tmp | 1 );
+}
+
+
+static void
+S3VHideCursor(ScrnInfoPtr pScrn)
+{
+ char tmp;
+
+ tmp = inCRReg(HWCURSOR_MODE_CR45);
+ /* Disable cursor */
+ outCRReg(HWCURSOR_MODE_CR45, tmp & ~1 );
+}
+
+
+static void
+S3VSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
+{
+ unsigned char xoff = 0, yoff = 0;
+
+ /*
+ if (!xf86VTSema)
+ return;
+ */
+
+ /*
+ x -= s3vHotX;
+ y -= s3vHotY;
+ */
+
+ /*
+ * Make these even when used. There is a bug/feature on at least
+ * some chipsets that causes a "shadow" of the cursor in interlaced
+ * mode. Making this even seems to have no visible effect, so just
+ * do it for the generic case.
+ * note - xoff & yoff are used for displaying partial cursors on screen
+ * edges.
+ */
+
+ if (x < 0) {
+ xoff = ((-x) & 0xFE);
+ x = 0;
+ }
+
+ if (y < 0) {
+ yoff = ((-y) & 0xFE);
+ y = 0;
+ }
+
+ /* Double y position for a doublescan mode */
+ if(pScrn->currentMode->Flags & V_DBLSCAN) y <<= 1;
+
+ /* This is the recommended order to move the cursor */
+
+ outCRReg( 0x46, (x & 0xff00)>>8 );
+ outCRReg( 0x47, (x & 0xff) );
+ outCRReg( 0x49, (y & 0xff) );
+ outCRReg( 0x4e, xoff );
+ outCRReg( 0x4f, yoff );
+ outCRReg( 0x48, (y & 0xff00)>>8 );
+}
+
+
+static void
+S3VSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
+{
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ /*PVERB5(" S3VSetCursorColors\n");*/
+
+ switch( pScrn->bitsPerPixel) {
+ case 8:
+ if (!(S3_ViRGE_GX2_SERIES(ps3v->Chipset) || S3_ViRGE_MX_SERIES(ps3v->Chipset))) {
+ /* Reset the cursor color stack pointer */
+ inCRReg(0x45);
+ /* Write foreground */
+ outCRReg(0x4a, fg);
+ outCRReg(0x4a, fg);
+ /* Reset the cursor color stack pointer */
+ inCRReg(0x45);
+ /* Write background */
+ outCRReg(0x4b, bg);
+ outCRReg(0x4b, bg);
+ break;
+ } /* else fall through for ViRGE/MX... */
+ case 16:
+ if (!(S3_ViRGE_GX2_SERIES(ps3v->Chipset) || S3_ViRGE_MX_SERIES(ps3v->Chipset))) {
+ /* adjust colors to 16 bits */
+ if (pScrn->weight.green == 5 && ps3v->Chipset != S3_ViRGE_VX) {
+ fg = ((fg & 0xf80000) >> 9) |
+ ((fg & 0xf800) >> 6) |
+ ((fg & 0xf8) >> 3);
+ bg = ((bg & 0xf80000) >> 9) |
+ ((bg & 0xf800) >> 6) |
+ ((bg & 0xf8) >> 3);
+ } else {
+ fg = ((fg & 0xf80000) >> 8) |
+ ((fg & 0xfc00) >> 5) |
+ ((fg & 0xf8) >> 3);
+ bg = ((bg & 0xf80000) >> 8) |
+ ((bg & 0xfc00) >> 5) |
+ ((bg & 0xf8) >> 3);
+ }
+
+ inCRReg(0x45);
+ /* Write foreground */
+ outCRReg(0x4a, fg);
+ outCRReg(0x4a, fg >> 8);
+ /* needed for 2nd pixel in double-clock modes */
+ outCRReg(0x4a, fg);
+ outCRReg(0x4a, fg >> 8);
+ /* Reset the cursor color stack pointer */
+ inCRReg(0x45);
+ /* Write background */
+ outCRReg(0x4b, bg);
+ outCRReg(0x4b, bg >> 8);
+ /* needed for 2nd pixel in double-clock modes */
+ outCRReg(0x4b, bg);
+ outCRReg(0x4b, bg >> 8);
+ break;
+ } /* else fall through for ViRGE/MX... */
+
+ case 24:
+ case 32:
+ /* Do it straight, full 24 bit color. */
+
+ /* Reset the cursor color stack pointer */
+ inCRReg(0x45);
+ /* Write low, mid, high bytes - foreground */
+ outCRReg(0x4a, fg);
+ outCRReg(0x4a, fg >> 8);
+ outCRReg(0x4a, fg >> 16);
+ /* Reset the cursor color stack pointer */
+ inCRReg(0x45);
+ /* Write low, mid, high bytes - background */
+ outCRReg(0x4b, bg);
+ outCRReg(0x4b, bg >> 8);
+ outCRReg(0x4b, bg >> 16);
+ break;
+ }
+}
+
+
+Bool
+S3VHWCursorInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ S3VPtr ps3v = S3VPTR(pScrn);
+ xf86CursorInfoPtr infoPtr;
+
+ PVERB5(" S3VHWCursorInit\n");
+
+ infoPtr = xf86CreateCursorInfoRec();
+ if(!infoPtr) return FALSE;
+
+ ps3v->CursorInfoRec = infoPtr;
+
+ infoPtr->MaxWidth = 64;
+ infoPtr->MaxHeight = 64;
+ infoPtr->Flags = HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16 |
+ HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
+ HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
+ HARDWARE_CURSOR_BIT_ORDER_MSBFIRST;
+ if (S3_ViRGE_GX2_SERIES(ps3v->Chipset) || S3_ViRGE_MX_SERIES(ps3v->Chipset))
+ infoPtr->Flags |= HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
+ HARDWARE_CURSOR_INVERT_MASK;
+
+ infoPtr->SetCursorColors = S3VSetCursorColors;
+ infoPtr->SetCursorPosition = S3VSetCursorPosition;
+ infoPtr->LoadCursorImage = S3VLoadCursorImage;
+ infoPtr->HideCursor = S3VHideCursor;
+ infoPtr->ShowCursor = S3VShowCursor;
+ infoPtr->UseHWCursor = NULL;
+
+ return(xf86InitCursor(pScreen, infoPtr));
+}
+
+/*EOF*/
diff --git a/src/s3v_i2c.c b/src/s3v_i2c.c
new file mode 100644
index 0000000..6ae29c4
--- /dev/null
+++ b/src/s3v_i2c.c
@@ -0,0 +1,120 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/s3v_i2c.c,v 1.4 2000/03/31 20:13:32 dawes Exp $ */
+
+/*
+Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the XFree86 Project shall not
+be used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the XFree86 Project.
+*/
+
+/*
+Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the XFree86 Project shall not
+be used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the XFree86 Project.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "compiler.h"
+
+#include "xf86Pci.h"
+#include "xf86PciInfo.h"
+
+#include "vgaHW.h"
+
+#include "s3v.h"
+
+static void
+s3v_I2CPutBits(I2CBusPtr b, int clock, int data)
+{
+ S3VPtr ps3v = S3VPTR(xf86Screens[b->scrnIndex]);
+ unsigned int reg = 0x10;
+
+ if(clock) reg |= 0x1;
+ if(data) reg |= 0x2;
+
+ OUTREG(DDC_REG,reg);
+ /*ErrorF("s3v_I2CPutBits: %d %d\n", clock, data); */
+}
+
+static void
+s3v_I2CGetBits(I2CBusPtr b, int *clock, int *data)
+{
+ S3VPtr ps3v = S3VPTR(xf86Screens[b->scrnIndex]);
+ unsigned int reg;
+
+ reg = (INREG(DDC_REG));
+
+ *clock = reg & 0x4;
+ *data = reg & 0x8;
+
+ /*ErrorF("s3v_I2CGetBits: %d %d\n", *clock, *data);*/
+}
+
+Bool
+S3V_I2CInit(ScrnInfoPtr pScrn)
+{
+ S3VPtr ps3v = S3VPTR(pScrn);
+ I2CBusPtr I2CPtr;
+
+
+ I2CPtr = xf86CreateI2CBusRec();
+ if(!I2CPtr) return FALSE;
+
+ ps3v->I2C = I2CPtr;
+
+ I2CPtr->BusName = "I2C bus";
+ I2CPtr->scrnIndex = pScrn->scrnIndex;
+ I2CPtr->I2CPutBits = s3v_I2CPutBits;
+ I2CPtr->I2CGetBits = s3v_I2CGetBits;
+
+ if (!xf86I2CBusInit(I2CPtr))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+
diff --git a/src/s3v_macros.h b/src/s3v_macros.h
new file mode 100644
index 0000000..c8d1ef8
--- /dev/null
+++ b/src/s3v_macros.h
@@ -0,0 +1,127 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/s3v_macros.h,v 1.11 2000/11/28 20:59:18 dawes Exp $ */
+
+/*
+Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the XFree86 Project shall not
+be used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the XFree86 Project.
+*/
+
+#ifndef _S3V_MACROS_H
+#define _S3V_MACROS_H
+
+/* use these macros and INREG/OUTREG to access the extended registers
+ of s3 virge -- add any others you need here */
+
+/* miscellaneous registers */
+#define SUBSYS_STAT_REG 0x8504
+#define ADV_FUNC_CNTR 0x850c
+
+/* memory port controller registers */
+#define FIFO_CONTROL_REG 0x8200
+#define MIU_CONTROL_REG 0x8204
+#define STREAMS_TIMEOUT_REG 0x8208
+#define MISC_TIMEOUT_REG 0x820c
+
+/* Cursor Registers */
+#define HWCURSOR_MODE_CR45 0x45
+#define HWCURSOR_ADDR_LOW_CR4D 0x4d
+#define HWCURSOR_ADDR_HIGH_CR4C 0x4c
+
+/* streams registers */
+#define PSTREAM_CONTROL_REG 0x8180
+#define COL_CHROMA_KEY_CONTROL_REG 0x8184
+#define SSTREAM_CONTROL_REG 0x8190
+#define CHROMA_KEY_UPPER_BOUND_REG 0x8194
+#define SSTREAM_STRETCH_REG 0x8198
+#define BLEND_CONTROL_REG 0x81A0
+#define PSTREAM_FBADDR0_REG 0x81C0
+#define PSTREAM_FBADDR1_REG 0x81C4
+#define PSTREAM_STRIDE_REG 0x81C8
+#define DOUBLE_BUFFER_REG 0x81CC
+#define SSTREAM_FBADDR0_REG 0x81D0
+#define SSTREAM_FBADDR1_REG 0x81D4
+#define SSTREAM_STRIDE_REG 0x81D8
+#define OPAQUE_OVERLAY_CONTROL_REG 0x81DC
+#define K1_VSCALE_REG 0x81E0
+#define K2_VSCALE_REG 0x81E4
+#define DDA_VERT_REG 0x81E8
+#define STREAMS_FIFO_REG 0x81EC
+#define PSTREAM_START_REG 0x81F0
+#define PSTREAM_WINDOW_SIZE_REG 0x81F4
+#define SSTREAM_START_REG 0x81F8
+#define SSTREAM_WINDOW_SIZE_REG 0x81FC
+
+/* image write stuff */
+#define SRC_BASE 0xA4D4
+#define DEST_BASE 0xA4D8
+#define CLIP_L_R 0xA4DC
+#define CLIP_T_B 0xA4E0
+#define DEST_SRC_STR 0xA4E4
+#define MONO_PAT_0 0xA4E8
+#define MONO_PAT_1 0xA4EC
+#define PAT_BG_CLR 0xA4F0
+#define PAT_FG_CLR 0xA4F4
+#define SRC_BG_CLR 0xA4F8
+#define SRC_FG_CLR 0xA4FC
+#define CMD_SET 0xA500
+#define RWIDTH_HEIGHT 0xA504
+#define RSRC_XY 0xA508
+#define RDEST_XY 0xA50C
+
+/* Local Periperal Bus Registers */
+
+#define DDC_REG 0xFF20
+#define BLT_BUG 0x00000001
+#define MONO_TRANS_BUG 0x00000002
+
+
+#define MAXLOOP 0x0fffff /* timeout value for engine waits, 0.5 secs */
+
+/* Switchable per chipset, must be initialized prior to a mode */
+/* switch! */
+#define WAITFIFO(n) ((*ps3v->pWaitFifo)(ps3v,n))
+#define WAITCMD() ((*ps3v->pWaitCmd)(ps3v))
+
+#define WAITIDLE()\
+ do { int loop=0; mem_barrier(); \
+ while(((INREG(SUBSYS_STAT_REG) & 0x3f00) < 0x3000) && (loop++<MAXLOOP)) \
+ if (loop >= MAXLOOP) S3VGEReset(pScrn,1,__LINE__,__FILE__); \
+ } while (0)
+
+#define CHECK_DEST_BASE(y,h)\
+ if((y < ps3v->DestBaseY) || ((y + h) > (ps3v->DestBaseY + 2048))) {\
+ ps3v->DestBaseY = ((y + h) <= 2048) ? 0 : y;\
+ WAITFIFO(1);\
+ OUTREG(DEST_BASE, ps3v->DestBaseY * ps3v->Stride);\
+ }\
+ y -= ps3v->DestBaseY
+
+#define CHECK_SRC_BASE(y,h)\
+ if((y < ps3v->SrcBaseY) || ((y + h) > (ps3v->SrcBaseY + 2048))) {\
+ ps3v->SrcBaseY = ((y + h) <= 2048) ? 0 : y;\
+ WAITFIFO(1);\
+ OUTREG(SRC_BASE, ps3v->SrcBaseY * ps3v->Stride);\
+ }\
+ y -= ps3v->SrcBaseY
+
+
+#endif /* _S3V_MACROS_H */
diff --git a/src/s3v_rop.h b/src/s3v_rop.h
new file mode 100644
index 0000000..e4b393a
--- /dev/null
+++ b/src/s3v_rop.h
@@ -0,0 +1,207 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/s3v_rop.h,v 1.2 1998/11/28 10:43:16 dawes Exp $ */
+
+/*
+Copyright (C) 1994-1998 The XFree86 Project, Inc. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the XFree86 Project shall not
+be used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the XFree86 Project.
+*/
+
+/* This file contains the data structures which map the X ROPs to the
+ * ViRGE ROPs. It also contains other mappings which are used when supporting
+ * planemasks and transparency.
+ *
+ * Created by Sebastien Marineau, 29/03/97.
+ * This file should be included only from s3v_accel.c to avoid
+ * duplicate symbols.
+ *
+ */
+
+#include "regs3v.h"
+
+static int s3vAlu[16] =
+{
+ ROP_0, /* GXclear */
+ ROP_DSa, /* GXand */
+ ROP_SDna, /* GXandReverse */
+ ROP_S, /* GXcopy */
+ ROP_DSna, /* GXandInverted */
+ ROP_D, /* GXnoop */
+ ROP_DSx, /* GXxor */
+ ROP_DSo, /* GXor */
+ ROP_DSon, /* GXnor */
+ ROP_DSxn, /* GXequiv */
+ ROP_Dn, /* GXinvert*/
+ ROP_SDno, /* GXorReverse */
+ ROP_Sn, /* GXcopyInverted */
+ ROP_DSno, /* GXorInverted */
+ ROP_DSan, /* GXnand */
+ ROP_1 /* GXset */
+};
+
+/* S -> P, for solid and pattern fills. */
+static int s3vAlu_sp[16]=
+{
+ ROP_0,
+ ROP_DPa,
+ ROP_PDna,
+ ROP_P,
+ ROP_DPna,
+ ROP_D,
+ ROP_DPx,
+ ROP_DPo,
+ ROP_DPon,
+ ROP_DPxn,
+ ROP_Dn,
+ ROP_PDno,
+ ROP_Pn,
+ ROP_DPno,
+ ROP_DPan,
+ ROP_1
+};
+
+/* ROP -> (ROP & P) | (D & ~P) */
+/* These are used to support a planemask for S->D ops */
+static int s3vAlu_pat[16] =
+{
+ ROP_0_PaDPnao,
+ ROP_DSa_PaDPnao,
+ ROP_SDna_PaDPnao,
+ ROP_S_PaDPnao,
+ ROP_DSna_PaDPnao,
+ ROP_D_PaDPnao,
+ ROP_DSx_PaDPnao,
+ ROP_DSo_PaDPnao,
+ ROP_DSon_PaDPnao,
+ ROP_DSxn_PaDPnao,
+ ROP_Dn_PaDPnao,
+ ROP_SDno_PaDPnao,
+ ROP_Sn_PaDPnao,
+ ROP_DSno_PaDPnao,
+ ROP_DSan_PaDPnao,
+ ROP_1_PaDPnao
+};
+
+/* ROP_sp -> (ROP_sp & S) | (D & ~S) */
+/* This is used for our transparent mono pattern fills to support trans/plane*/
+static int s3vAlu_MonoTrans[16] =
+{
+ ROP_0_SaDSnao,
+ ROP_DPa_SaDSnao,
+ ROP_PDna_SaDSnao,
+ ROP_P_SaDSnao,
+ ROP_DPna_SaDSnao,
+ ROP_D_SaDSnao,
+ ROP_DPx_SaDSnao,
+ ROP_DPo_SaDSnao,
+ ROP_DPon_SaDSnao,
+ ROP_DPxn_SaDSnao,
+ ROP_Dn_SaDSnao,
+ ROP_PDno_SaDSnao,
+ ROP_Pn_SaDSnao,
+ ROP_DPno_SaDSnao,
+ ROP_DPan_SaDSnao,
+ ROP_1_SaDSnao
+};
+
+
+
+/* This function was taken from accel/s3v.h. It adjusts the width
+ * of transfers for mono images to works around some bugs.
+ */
+
+static __inline__ int S3VCheckLSPN(S3VPtr ps3v, int w, int dir)
+{
+ int lspn = (w * ps3v->Bpp) & 63; /* scanline width in bytes modulo 64*/
+
+ if (ps3v->Bpp == 1) {
+ if (lspn <= 8*1)
+ w += 16;
+ else if (lspn <= 16*1)
+ w += 8;
+ } else if (ps3v->Bpp == 2) {
+ if (lspn <= 4*2)
+ w += 8;
+ else if (lspn <= 8*2)
+ w += 4;
+ } else { /* ps3v->Bpp == 3 */
+ if (lspn <= 3*3)
+ w += 6;
+ else if (lspn <= 6*3)
+ w += 3;
+ }
+ if (dir && w >= ps3v->bltbug_width1 && w <= ps3v->bltbug_width2) {
+ w = ps3v->bltbug_width2 + 1;
+ }
+
+ return w;
+}
+
+/* And this adjusts color bitblts widths to work around GE bugs */
+
+static __inline__ int S3VCheckBltWidth(S3VPtr ps3v, int w)
+{
+ if (w >= ps3v->bltbug_width1 && w <= ps3v->bltbug_width2) {
+ w = ps3v->bltbug_width2 + 1;
+ }
+ return w;
+}
+
+/* This next function determines if the Source operand is present in the
+ * given ROP. The rule is that both the lower and upper nibble of the rop
+ * have to be neither 0x00, 0x05, 0x0a or 0x0f. If a CPU-Screen blit is done
+ * with a ROP which does not contain the source, the virge will hang when
+ * data is written to the image transfer area.
+ */
+
+static __inline__ Bool S3VROPHasSrc(int shifted_rop)
+{
+ int rop = (shifted_rop & (0xff << 17)) >> 17;
+
+ if ((((rop & 0x0f) == 0x0a) | ((rop & 0x0f) == 0x0f)
+ | ((rop & 0x0f) == 0x05) | ((rop & 0x0f) == 0x00)) &
+ (((rop & 0xf0) == 0xa0) | ((rop & 0xf0) == 0xf0)
+ | ((rop & 0xf0) == 0x50) | ((rop & 0xf0) == 0x00)))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+/* This next function determines if the Destination operand is present in the
+ * given ROP. The rule is that both the lower and upper nibble of the rop
+ * have to be neither 0x00, 0x03, 0x0c or 0x0f.
+ */
+
+static __inline__ Bool S3VROPHasDst(int shifted_rop)
+{
+ int rop = (shifted_rop & (0xff << 17)) >> 17;
+
+ if ((((rop & 0x0f) == 0x0c) | ((rop & 0x0f) == 0x0f)
+ | ((rop & 0x0f) == 0x03) | ((rop & 0x0f) == 0x00)) &
+ (((rop & 0xf0) == 0xc0) | ((rop & 0xf0) == 0xf0)
+ | ((rop & 0xf0) == 0x30) | ((rop & 0xf0) == 0x00)))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+
+
diff --git a/src/s3v_shadow.c b/src/s3v_shadow.c
new file mode 100644
index 0000000..253f295
--- /dev/null
+++ b/src/s3v_shadow.c
@@ -0,0 +1,305 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/s3v_shadow.c,v 1.2 2000/03/06 22:59:30 dawes Exp $ */
+
+/*
+Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the XFree86 Project shall not
+be used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the XFree86 Project.
+*/
+
+/*
+Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the XFree86 Project shall not
+be used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the XFree86 Project.
+*/
+
+/*
+ Copyright (c) 1999,2000 The XFree86 Project Inc.
+ based on code written by Mark Vojkovich <markv@valinux.com>
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "xf86_ansic.h"
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+#include "shadowfb.h"
+#include "servermd.h"
+#include "s3v.h"
+
+
+void
+s3vRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+ S3VPtr ps3v = S3VPTR(pScrn);
+ int width, height, Bpp, FBPitch;
+ unsigned char *src, *dst;
+
+ Bpp = pScrn->bitsPerPixel >> 3;
+ FBPitch = BitmapBytePad(pScrn->displayWidth * pScrn->bitsPerPixel);
+
+ while(num--) {
+ width = (pbox->x2 - pbox->x1) * Bpp;
+ height = pbox->y2 - pbox->y1;
+ src = ps3v->ShadowPtr + (pbox->y1 * ps3v->ShadowPitch) +
+ (pbox->x1 * Bpp);
+ dst = ps3v->FBStart + (pbox->y1 * FBPitch) + (pbox->x1 * Bpp);
+
+ while(height--) {
+ memcpy(dst, src, width);
+ dst += FBPitch;
+ src += ps3v->ShadowPitch;
+ }
+
+ pbox++;
+ }
+}
+
+void
+s3vPointerMoved(int index, int x, int y)
+{
+ ScrnInfoPtr pScrn = xf86Screens[index];
+ S3VPtr ps3v = S3VPTR(pScrn);
+ int newX, newY;
+
+ if(ps3v->rotate == 1) {
+ newX = pScrn->pScreen->height - y - 1;
+ newY = x;
+ } else {
+ newX = y;
+ newY = pScrn->pScreen->width - x - 1;
+ }
+
+ (*ps3v->PointerMoved)(index, newX, newY);
+}
+
+void
+s3vRefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+ S3VPtr ps3v = S3VPTR(pScrn);
+ int count, width, height, y1, y2, dstPitch, srcPitch;
+ CARD8 *dstPtr, *srcPtr, *src;
+ CARD32 *dst;
+
+ dstPitch = pScrn->displayWidth;
+ srcPitch = -ps3v->rotate * ps3v->ShadowPitch;
+
+ while(num--) {
+ width = pbox->x2 - pbox->x1;
+ y1 = pbox->y1 & ~3;
+ y2 = (pbox->y2 + 3) & ~3;
+ height = (y2 - y1) >> 2; /* in dwords */
+
+ if(ps3v->rotate == 1) {
+ dstPtr = ps3v->FBStart +
+ (pbox->x1 * dstPitch) + pScrn->virtualX - y2;
+ srcPtr = ps3v->ShadowPtr + ((1 - y2) * srcPitch) + pbox->x1;
+ } else {
+ dstPtr = ps3v->FBStart +
+ ((pScrn->virtualY - pbox->x2) * dstPitch) + y1;
+ srcPtr = ps3v->ShadowPtr + (y1 * srcPitch) + pbox->x2 - 1;
+ }
+
+ while(width--) {
+ src = srcPtr;
+ dst = (CARD32*)dstPtr;
+ count = height;
+ while(count--) {
+ *(dst++) = src[0] | (src[srcPitch] << 8) |
+ (src[srcPitch * 2] << 16) |
+ (src[srcPitch * 3] << 24);
+ src += srcPitch * 4;
+ }
+ srcPtr += ps3v->rotate;
+ dstPtr += dstPitch;
+ }
+
+ pbox++;
+ }
+}
+
+
+void
+s3vRefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+ S3VPtr ps3v = S3VPTR(pScrn);
+ int count, width, height, y1, y2, dstPitch, srcPitch;
+ CARD16 *dstPtr, *srcPtr, *src;
+ CARD32 *dst;
+
+ dstPitch = pScrn->displayWidth;
+ srcPitch = -ps3v->rotate * ps3v->ShadowPitch >> 1;
+
+ while(num--) {
+ width = pbox->x2 - pbox->x1;
+ y1 = pbox->y1 & ~1;
+ y2 = (pbox->y2 + 1) & ~1;
+ height = (y2 - y1) >> 1; /* in dwords */
+
+ if(ps3v->rotate == 1) {
+ dstPtr = (CARD16*)ps3v->FBStart +
+ (pbox->x1 * dstPitch) + pScrn->virtualX - y2;
+ srcPtr = (CARD16*)ps3v->ShadowPtr +
+ ((1 - y2) * srcPitch) + pbox->x1;
+ } else {
+ dstPtr = (CARD16*)ps3v->FBStart +
+ ((pScrn->virtualY - pbox->x2) * dstPitch) + y1;
+ srcPtr = (CARD16*)ps3v->ShadowPtr +
+ (y1 * srcPitch) + pbox->x2 - 1;
+ }
+
+ while(width--) {
+ src = srcPtr;
+ dst = (CARD32*)dstPtr;
+ count = height;
+ while(count--) {
+ *(dst++) = src[0] | (src[srcPitch] << 16);
+ src += srcPitch * 2;
+ }
+ srcPtr += ps3v->rotate;
+ dstPtr += dstPitch;
+ }
+
+ pbox++;
+ }
+}
+
+
+/* this one could be faster */
+void
+s3vRefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+ S3VPtr ps3v = S3VPTR(pScrn);
+ int count, width, height, y1, y2, dstPitch, srcPitch;
+ CARD8 *dstPtr, *srcPtr, *src;
+ CARD32 *dst;
+
+ dstPitch = BitmapBytePad(pScrn->displayWidth * 24);
+ srcPitch = -ps3v->rotate * ps3v->ShadowPitch;
+
+ while(num--) {
+ width = pbox->x2 - pbox->x1;
+ y1 = pbox->y1 & ~3;
+ y2 = (pbox->y2 + 3) & ~3;
+ height = (y2 - y1) >> 2; /* blocks of 3 dwords */
+
+ if(ps3v->rotate == 1) {
+ dstPtr = ps3v->FBStart +
+ (pbox->x1 * dstPitch) + ((pScrn->virtualX - y2) * 3);
+ srcPtr = ps3v->ShadowPtr + ((1 - y2) * srcPitch) + (pbox->x1 * 3);
+ } else {
+ dstPtr = ps3v->FBStart +
+ ((pScrn->virtualY - pbox->x2) * dstPitch) + (y1 * 3);
+ srcPtr = ps3v->ShadowPtr + (y1 * srcPitch) + (pbox->x2 * 3) - 3;
+ }
+
+ while(width--) {
+ src = srcPtr;
+ dst = (CARD32*)dstPtr;
+ count = height;
+ while(count--) {
+ dst[0] = src[0] | (src[1] << 8) | (src[2] << 16) |
+ (src[srcPitch] << 24);
+ dst[1] = src[srcPitch + 1] | (src[srcPitch + 2] << 8) |
+ (src[srcPitch * 2] << 16) |
+ (src[(srcPitch * 2) + 1] << 24);
+ dst[2] = src[(srcPitch * 2) + 2] | (src[srcPitch * 3] << 8) |
+ (src[(srcPitch * 3) + 1] << 16) |
+ (src[(srcPitch * 3) + 2] << 24);
+ dst += 3;
+ src += srcPitch * 4;
+ }
+ srcPtr += ps3v->rotate * 3;
+ dstPtr += dstPitch;
+ }
+
+ pbox++;
+ }
+}
+
+void
+s3vRefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+ S3VPtr ps3v = S3VPTR(pScrn);
+ int count, width, height, dstPitch, srcPitch;
+ CARD32 *dstPtr, *srcPtr, *src, *dst;
+
+ dstPitch = pScrn->displayWidth;
+ srcPitch = -ps3v->rotate * ps3v->ShadowPitch >> 2;
+
+ while(num--) {
+ width = pbox->x2 - pbox->x1;
+ height = pbox->y2 - pbox->y1;
+
+ if(ps3v->rotate == 1) {
+ dstPtr = (CARD32*)ps3v->FBStart +
+ (pbox->x1 * dstPitch) + pScrn->virtualX - pbox->y2;
+ srcPtr = (CARD32*)ps3v->ShadowPtr +
+ ((1 - pbox->y2) * srcPitch) + pbox->x1;
+ } else {
+ dstPtr = (CARD32*)ps3v->FBStart +
+ ((pScrn->virtualY - pbox->x2) * dstPitch) + pbox->y1;
+ srcPtr = (CARD32*)ps3v->ShadowPtr +
+ (pbox->y1 * srcPitch) + pbox->x2 - 1;
+ }
+
+ while(width--) {
+ src = srcPtr;
+ dst = dstPtr;
+ count = height;
+ while(count--) {
+ *(dst++) = *src;
+ src += srcPitch;
+ }
+ srcPtr += ps3v->rotate;
+ dstPtr += dstPitch;
+ }
+
+ pbox++;
+ }
+}
+
+
+
diff --git a/src/s3v_xaa.c b/src/s3v_xaa.c
new file mode 100644
index 0000000..3983650
--- /dev/null
+++ b/src/s3v_xaa.c
@@ -0,0 +1,757 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/s3v_accel.c,v 1.25 2003/11/06 18:38:05 tsi Exp $ */
+
+/*
+Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the XFree86 Project shall not
+be used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the XFree86 Project.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "s3v.h"
+
+#include "miline.h"
+ /* fb includes are in s3v.h */
+#include "xaalocal.h"
+#include "xaarop.h"
+
+#include "servermd.h" /* LOG2_BYTES_PER_SCANLINE_PAD */
+
+static void S3VSetupForSolidFill(
+ ScrnInfoPtr pScrn,
+ int color, int rop,
+ unsigned int planemask);
+
+static void S3VSubsequentSolidFillRect(
+ ScrnInfoPtr pScrn,
+ int x, int y,
+ int w, int h);
+
+static void S3VSubsequentSolidFillRectPlaneMask(
+ ScrnInfoPtr pScrn,
+ int x, int y,
+ int w, int h);
+
+static void S3VSetupForMono8x8PatternFill(
+ ScrnInfoPtr pScrn,
+ int patx, int paty,
+ int fg, int bg,
+ int rop, unsigned int planemask);
+
+static void S3VSubsequentMono8x8PatternFillRect(
+ ScrnInfoPtr pScrn,
+ int patx, int paty,
+ int x, int y,
+ int w, int h);
+
+static void S3VSubsequentMono8x8PatternFillRectPlaneMask(
+ ScrnInfoPtr pScrn,
+ int patx, int paty,
+ int x, int y,
+ int w, int h);
+
+static void S3VSetupForScreenToScreenCopy(
+ ScrnInfoPtr pScrn,
+ int xdir, int ydir,
+ int rop,
+ unsigned int planemask,
+ int trans);
+
+static void S3VSubsequentScreenToScreenCopy(
+ ScrnInfoPtr pScrn,
+ int x1, int y1,
+ int x2, int y2,
+ int w, int h);
+
+static void S3VSetupForCPUToScreenColorExpand(
+ ScrnInfoPtr pScrn,
+ int fg, int bg,
+ int rop,
+ unsigned int planemask);
+
+static void S3VSubsequentCPUToScreenColorExpand(
+ ScrnInfoPtr pScrn,
+ int x, int y,
+ int w, int h,
+ int skipleft);
+
+static void S3VSetupForImageWrite(
+ ScrnInfoPtr pScrn,
+ int rop, unsigned int planemask,
+ int trans_color, int bpp,
+ int depth);
+
+static void S3VSubsequentImageWriteRect(
+ ScrnInfoPtr pScrn,
+ int x, int y,
+ int w, int h,
+ int skipleft);
+
+static void S3VSubsequentSolidHorVertLine(
+ ScrnInfoPtr pScrn,
+ int x, int y,
+ int len, int dir);
+
+static void S3VSubsequentSolidHorVertLinePlaneMask(
+ ScrnInfoPtr pScrn,
+ int x, int y,
+ int len, int dir);
+
+#if 0
+static void S3VSubsequentSolidBresenhamLine(ScrnInfoPtr, int, int, int,
+ int, int, int, int);
+static void S3VPolylinesThinSolidWrapper(DrawablePtr, GCPtr, int, int,
+ DDXPointPtr);
+static void S3VPolySegmentThinSolidWrapper(DrawablePtr, GCPtr, int, xSegment*);
+#endif
+
+
+Bool
+S3VXAAInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ S3VPtr ps3v = S3VPTR(pScrn);
+ XAAInfoRecPtr xaaptr;
+ BoxRec AvailFBArea;
+
+ /* General acceleration flags */
+ if (!(xaaptr = ps3v->AccelInfoRec = XAACreateInfoRec())) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to allocate XAAInfoRec.\n");
+ return FALSE;
+ }
+
+ xaaptr->Flags = 0
+ | PIXMAP_CACHE
+ | OFFSCREEN_PIXMAPS
+ | LINEAR_FRAMEBUFFER
+ ;
+
+ xaaptr->Sync = S3VAccelSync;
+
+ /* Problem reports with solid fill on trio3d */
+ if(!S3_TRIO_3D_SERIES(ps3v->Chipset))
+ {
+ /* Solid filled rects */
+ xaaptr->SetupForSolidFill =
+ S3VSetupForSolidFill;
+ xaaptr->SubsequentSolidFillRect =
+ S3VSubsequentSolidFillRect;
+ }
+
+ /* Screen to screen copies */
+ xaaptr->SetupForScreenToScreenCopy =
+ S3VSetupForScreenToScreenCopy;
+ xaaptr->SubsequentScreenToScreenCopy =
+ S3VSubsequentScreenToScreenCopy;
+ xaaptr->ScreenToScreenCopyFlags = 0
+ | NO_TRANSPARENCY;
+
+ /* Mono 8x8 patterns */
+ xaaptr->SetupForMono8x8PatternFill =
+ S3VSetupForMono8x8PatternFill;
+ xaaptr->SubsequentMono8x8PatternFillRect =
+ S3VSubsequentMono8x8PatternFillRect;
+ xaaptr->Mono8x8PatternFillFlags = 0
+ | NO_TRANSPARENCY
+ | HARDWARE_PATTERN_PROGRAMMED_BITS
+ | HARDWARE_PATTERN_SCREEN_ORIGIN
+ | BIT_ORDER_IN_BYTE_MSBFIRST
+ ;
+
+#ifndef __alpha__
+
+ /* disable color expand on GX2 until we trace down */
+ /* lockups. locate 'html' in an xterm is a good */
+ /* test case for an AGP GX2. */
+ if (!S3_ViRGE_GX2_SERIES(ps3v->Chipset))
+ {
+
+ /* CPU to screen color expansion */
+ xaaptr->CPUToScreenColorExpandFillFlags = 0
+ | ROP_NEEDS_SOURCE
+ | CPU_TRANSFER_PAD_DWORD
+ | SCANLINE_PAD_DWORD
+ | BIT_ORDER_IN_BYTE_MSBFIRST
+ | LEFT_EDGE_CLIPPING
+ ;
+
+ if(ps3v->AccelFlags & MONO_TRANS_BUG)
+ xaaptr->CPUToScreenColorExpandFillFlags |= NO_TRANSPARENCY;
+
+ xaaptr->ColorExpandRange = 0x8000;
+ xaaptr->ColorExpandBase = ps3v->MapBaseDense;
+ xaaptr->SetupForCPUToScreenColorExpandFill =
+ S3VSetupForCPUToScreenColorExpand;
+ xaaptr->SubsequentCPUToScreenColorExpandFill =
+ S3VSubsequentCPUToScreenColorExpand;
+
+ } /* if(!GX2...) */
+
+
+ /* Image Writes */
+ xaaptr->ImageWriteFlags = 0
+ | ROP_NEEDS_SOURCE
+ | NO_TRANSPARENCY
+ | CPU_TRANSFER_PAD_DWORD
+ | SCANLINE_PAD_DWORD
+ | NO_GXCOPY /* added - kjb */
+ | LEFT_EDGE_CLIPPING
+ ;
+
+ xaaptr->ImageWriteRange = 0x8000;
+ xaaptr->ImageWriteBase = ps3v->MapBaseDense;
+ xaaptr->SetupForImageWrite = S3VSetupForImageWrite;
+ xaaptr->SubsequentImageWriteRect = S3VSubsequentImageWriteRect;
+
+ /* on alpha, I see corruption in the xscreensaver program "hypercube"
+ as the line acceleration is just stubs, it loses us nothing to
+ disable it on alphas */
+
+ /* Lines */
+#if 0
+ /* Bresenham lines are broken when passed through fb to xaa
+ so I pulled all the line functions. This shouldn't hurt us
+ a whole lot, since the Subsequent..Bresen stuff doesn't have
+ any hardware accel yet anyway... And xaa will do horiz/vert
+ lines with the rect fill (like we are doing here) anyway.
+ KJB 9/11/00
+ */
+ infoPtr->SetupForSolidLine = S3VSetupForSolidFill;
+ infoPtr->SubsequentSolidHorVertLine = S3VSubsequentSolidHorVertLine;
+ infoPtr->SubsequentSolidBresenhamLine = S3VSubsequentSolidBresenhamLine;
+ infoPtr->PolySegmentThinSolid = S3VPolySegmentThinSolidWrapper;
+ infoPtr->PolylinesThinSolid = S3VPolylinesThinSolidWrapper;
+#endif
+
+#endif /* !__alpha__ */
+
+ /* And these are screen parameters used to setup the Graphics Engine */
+
+ /* Bytes per pixel */
+ ps3v->Bpp = pScrn->bitsPerPixel / 8;
+ ps3v->Width = pScrn->displayWidth;
+ /* Bytes per line */
+ ps3v->Bpl = ps3v->Width * ps3v->Bpp;
+ /* ScissB is max height, minus 1k */
+ /* for hwcursor?, then limited by */
+ /* ViRGE max height register of */
+ /* 2047 */
+ ps3v->ScissB = (pScrn->videoRam * 1024 - 1024) / ps3v->Bpl;
+ if (ps3v->ScissB > 2047)
+ ps3v->ScissB = 2047;
+
+ S3VEngineReset(pScrn);
+
+ AvailFBArea.x1 = 0;
+ AvailFBArea.y1 = 0;
+ AvailFBArea.x2 = pScrn->displayWidth;
+ AvailFBArea.y2 = (pScrn->videoRam * 1024 - 1024) /
+ (pScrn->displayWidth * pScrn->bitsPerPixel / 8);
+
+ xf86InitFBManager(pScreen, &AvailFBArea);
+
+ /* make sure offscreen pixmaps aren't bigger than our address space */
+ xaaptr->maxOffPixWidth = 2048;
+ xaaptr->maxOffPixHeight = 2048;
+
+ return XAAInit(pScreen, xaaptr);
+}
+
+/* The sync function for the GE */
+void
+S3VAccelSync(ScrnInfoPtr pScrn)
+{
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ WAITIDLE();
+}
+
+static void
+S3VWriteMask(
+ CARD32 *dstBase,
+ int dwords
+){
+ /* on alphas, be sure to call this with MapBaseDense, not MapBase! */
+ int numLeft;
+ CARD32 *dst = dstBase;
+
+ while(dwords >= 8192) {
+ numLeft = 8192;
+ while(numLeft) {
+ dst[0] = ~0; dst[1] = ~0;
+ dst[2] = ~0; dst[3] = ~0;
+ dst += 4;
+ numLeft -= 4;
+ }
+ dwords -= 8192;
+ dst = dstBase;
+ }
+ while(dwords >= 4) {
+ dst[0] = ~0; dst[1] = ~0;
+ dst[2] = ~0; dst[3] = ~0;
+ dst += 4;
+ dwords -= 4;
+ }
+ if(!dwords) return;
+ dst[0] = ~0;
+ if(dwords == 1) return;
+ dst[1] = ~0;
+ if(dwords == 2) return;
+ dst[2] = ~0;
+
+ return;
+}
+
+
+ /************************\
+ | Solid Filled Rects |
+ \************************/
+
+static void
+S3VSetupForSolidFill(
+ ScrnInfoPtr pScrn,
+ int color, int rop,
+ unsigned int planemask
+){
+ S3VPtr ps3v = S3VPTR(pScrn);
+ int mix;
+
+ mix = XAAHelpSolidROP(pScrn, &color, planemask, &rop);
+
+ ps3v->AccelCmd = ps3v->CommonCmd | (rop << 17) |
+ CMD_XP | CMD_YP | CMD_AUTOEXEC | CMD_BITBLT;
+
+ if(mix & ROP_SRC) {
+ ps3v->AccelCmd |= MIX_CPUDATA | CMD_ITA_DWORD | MIX_MONO_SRC;
+ ps3v->AccelInfoRec->SubsequentSolidFillRect =
+ S3VSubsequentSolidFillRectPlaneMask;
+ ps3v->AccelInfoRec->SubsequentSolidHorVertLine =
+ S3VSubsequentSolidHorVertLinePlaneMask;
+ WAITFIFO(5);
+ OUTREG(SRC_FG_CLR, planemask);
+ } else {
+ ps3v->AccelInfoRec->SubsequentSolidFillRect =
+ S3VSubsequentSolidFillRect;
+ ps3v->AccelInfoRec->SubsequentSolidHorVertLine =
+ S3VSubsequentSolidHorVertLine;
+ WAITFIFO(4);
+ }
+
+ if(mix & ROP_PAT) {
+ ps3v->AccelCmd |= MIX_MONO_PATT;
+ OUTREG(PAT_FG_CLR, color);
+ OUTREG(MONO_PAT_0, ~0);
+ OUTREG(MONO_PAT_1, ~0);
+ }
+
+ OUTREG(CMD_SET, ps3v->AccelCmd);
+}
+
+
+void
+S3VSubsequentSolidFillRect(
+ ScrnInfoPtr pScrn,
+ int x, int y,
+ int w, int h
+){
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ CHECK_DEST_BASE(y,h);
+
+ WAITFIFO(2);
+ OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
+ WAITCMD();
+ OUTREG(RDEST_XY, (x << 16) | y);
+}
+
+
+void
+S3VSubsequentSolidFillRectPlaneMask(
+ ScrnInfoPtr pScrn,
+ int x, int y,
+ int w, int h
+){
+ S3VPtr ps3v = S3VPTR(pScrn);
+ int dwords;
+
+ CHECK_DEST_BASE(y,h);
+
+ dwords = ((w + 31) >> 5) * h;
+
+ WAITFIFO(2);
+ OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
+ WAITCMD();
+ OUTREG(RDEST_XY, (x << 16) | y);
+ S3VWriteMask((CARD32*)ps3v->MapBaseDense, dwords);
+}
+
+
+ /**************************\
+ | Screen to Screen Copies |
+ \**************************/
+
+static void
+S3VSetupForScreenToScreenCopy(
+ ScrnInfoPtr pScrn,
+ int xdir, int ydir,
+ int rop,
+ unsigned int planemask,
+ int trans
+){
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ planemask &= ps3v->FullPlaneMask;
+ ps3v->AccelCmd = ps3v->CommonCmd | CMD_AUTOEXEC | CMD_BITBLT;
+
+ if(planemask != ps3v->FullPlaneMask) {
+ ps3v->AccelCmd |= (XAAGetCopyROP_PM(rop) << 17) | MIX_MONO_PATT;
+ WAITFIFO(4);
+ OUTREG(PAT_FG_CLR, planemask);
+ OUTREG(MONO_PAT_0, ~0);
+ OUTREG(MONO_PAT_1, ~0);
+ }
+ else {
+ ps3v->AccelCmd |= XAAGetCopyROP(rop) << 17;
+ WAITFIFO(1);
+ }
+ if(xdir == 1) ps3v->AccelCmd |= CMD_XP;
+ if(ydir == 1) ps3v->AccelCmd |= CMD_YP;
+
+ OUTREG(CMD_SET, ps3v->AccelCmd);
+}
+
+
+static void
+S3VSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
+ int x2, int y2, int w, int h)
+{
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ CHECK_SRC_BASE(y1,h);
+ CHECK_DEST_BASE(y2,h);
+
+ w--;
+
+ if(!(ps3v->AccelCmd & CMD_YP)) {
+ y1 += h - 1; y2 += h - 1;
+ }
+
+ if(!(ps3v->AccelCmd & CMD_XP)) {
+ x1 += w; x2 += w;
+ }
+
+ WAITFIFO(3);
+ OUTREG(RWIDTH_HEIGHT, (w << 16) | h);
+ OUTREG(RSRC_XY, (x1 << 16) | y1);
+ WAITCMD();
+ OUTREG(RDEST_XY, (x2 << 16) | y2);
+}
+
+
+ /*********************\
+ | 8x8 Pattern fills |
+ \*********************/
+
+
+static void
+S3VSetupForMono8x8PatternFill(
+ ScrnInfoPtr pScrn,
+ int patx, int paty,
+ int fg, int bg,
+ int rop, unsigned int planemask
+){
+ S3VPtr ps3v = S3VPTR(pScrn);
+ int mix;
+
+ mix = XAAHelpPatternROP(pScrn, &fg, &bg, planemask, &rop);
+
+ ps3v->AccelCmd = ps3v->CommonCmd | (rop << 17) |
+ CMD_XP | CMD_YP | CMD_AUTOEXEC | CMD_BITBLT;
+
+ if(mix & ROP_SRC) {
+ ps3v->AccelCmd |= MIX_CPUDATA | CMD_ITA_DWORD | MIX_MONO_SRC;
+ ps3v->AccelInfoRec->SubsequentMono8x8PatternFillRect =
+ S3VSubsequentMono8x8PatternFillRectPlaneMask;
+ WAITFIFO(6);
+ OUTREG(SRC_FG_CLR, planemask);
+ } else {
+ ps3v->AccelInfoRec->SubsequentMono8x8PatternFillRect =
+ S3VSubsequentMono8x8PatternFillRect;
+ WAITFIFO(5);
+ }
+
+ if(mix & ROP_PAT) {
+ ps3v->AccelCmd |= MIX_MONO_PATT;
+ OUTREG(PAT_FG_CLR, fg);
+ OUTREG(PAT_BG_CLR, bg);
+ OUTREG(MONO_PAT_0, patx);
+ OUTREG(MONO_PAT_1, paty);
+ }
+
+ OUTREG(CMD_SET, ps3v->AccelCmd);
+}
+
+
+static void
+S3VSubsequentMono8x8PatternFillRect(
+ ScrnInfoPtr pScrn,
+ int patx, int paty,
+ int x, int y, int w, int h
+){
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ CHECK_DEST_BASE(y,h);
+
+ WAITFIFO(2);
+ OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
+ WAITCMD();
+ OUTREG(RDEST_XY, (x << 16) | y);
+}
+
+
+static void
+S3VSubsequentMono8x8PatternFillRectPlaneMask(
+ ScrnInfoPtr pScrn,
+ int patx, int paty,
+ int x, int y, int w, int h
+){
+ S3VPtr ps3v = S3VPTR(pScrn);
+ int dwords;
+
+ CHECK_DEST_BASE(y,h);
+
+ dwords = ((w + 31) >> 5) * h;
+
+ WAITFIFO(2);
+ OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
+ WAITCMD();
+ OUTREG(RDEST_XY, (x << 16) | y);
+
+ S3VWriteMask((CARD32*)ps3v->MapBaseDense, dwords);
+}
+
+ /*********************************\
+ | CPU to Screen Color Expansion |
+ \*********************************/
+
+
+static void
+S3VSetupForCPUToScreenColorExpand(
+ ScrnInfoPtr pScrn,
+ int fg, int bg,
+ int rop,
+ unsigned int planemask
+){
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ planemask &= ps3v->FullPlaneMask;
+ ps3v->AccelCmd = ps3v->CommonCmd | CMD_AUTOEXEC | CMD_BITBLT |
+ CMD_XP | CMD_YP | CMD_ITA_DWORD | CMD_HWCLIP |
+ MIX_CPUDATA | MIX_MONO_SRC;
+
+
+ if(planemask == ps3v->FullPlaneMask) {
+ ps3v->AccelCmd |= XAAGetCopyROP(rop) << 17;
+ WAITFIFO(3);
+ } else {
+ ps3v->AccelCmd |= (XAAGetCopyROP_PM(rop) << 17) | MIX_MONO_PATT;
+ WAITFIFO(6);
+ OUTREG(MONO_PAT_0, ~0);
+ OUTREG(MONO_PAT_1, ~0);
+ OUTREG(PAT_FG_CLR, planemask);
+ }
+
+ if(bg == -1)
+ ps3v->AccelCmd |= MIX_MONO_TRANSP;
+ else
+ OUTREG(SRC_BG_CLR, bg);
+
+ OUTREG(SRC_FG_CLR, fg);
+ OUTREG(CMD_SET, ps3v->AccelCmd);
+}
+
+
+void
+S3VSubsequentCPUToScreenColorExpand(
+ ScrnInfoPtr pScrn,
+ int x, int y,
+ int w, int h,
+ int skipleft
+){
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ CHECK_DEST_BASE(y,h);
+ WAITFIFO(3);
+ OUTREG(CLIP_L_R, ((x + skipleft) << 16) | 0xffff);
+ OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
+ WAITCMD();
+ OUTREG(RDEST_XY, (x << 16) | y);
+}
+
+
+ /****************\
+ | Image Writes |
+ \****************/
+
+
+static void
+S3VSetupForImageWrite(
+ ScrnInfoPtr pScrn,
+ int rop, unsigned int planemask,
+ int trans_color, int bpp, int depth
+){
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ planemask &= ps3v->FullPlaneMask;
+ ps3v->AccelCmd = ps3v->CommonCmd | CMD_AUTOEXEC | CMD_BITBLT |
+ MIX_CPUDATA | CMD_ITA_DWORD | CMD_HWCLIP | CMD_XP | CMD_YP;
+
+ if(planemask != ps3v->FullPlaneMask) {
+ ps3v->AccelCmd |= (XAAGetCopyROP_PM(rop) << 17) | MIX_MONO_PATT;
+ WAITFIFO(4);
+ OUTREG(PAT_FG_CLR, planemask);
+ OUTREG(MONO_PAT_0, ~0);
+ OUTREG(MONO_PAT_1, ~0);
+ } else {
+ ps3v->AccelCmd |= XAAGetCopyROP(rop) << 17;
+ WAITFIFO(1);
+ }
+
+ OUTREG(CMD_SET, ps3v->AccelCmd);
+}
+
+
+static void
+S3VSubsequentImageWriteRect(
+ ScrnInfoPtr pScrn,
+ int x, int y,
+ int w, int h,
+ int skipleft
+){
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ CHECK_DEST_BASE(y,h);
+
+ WAITFIFO(3);
+ OUTREG(CLIP_L_R, ((x + skipleft) << 16) | 0xffff);
+ OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
+ WAITCMD();
+ OUTREG(RDEST_XY, (x << 16) | y);
+}
+
+
+ /***********\
+ | Lines |
+ \***********/
+
+
+#if 0 /* Some line funcs are disabled at the moment */
+
+static void
+S3VPolylinesThinSolidWrapper(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int mode,
+ int npt,
+ DDXPointPtr pPts
+){
+ XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
+ S3VPtr ps3v = S3VPTR(infoRec->pScrn);
+ ps3v->CurrentGC = pGC;
+ /* fb support */
+ ps3v->CurrentDrawable = pDraw;
+ if(infoRec->NeedToSync)
+ S3VAccelSync(infoRec->pScrn);
+ XAAPolyLines(pDraw, pGC, mode, npt, pPts);
+}
+
+static void
+S3VPolySegmentThinSolidWrapper(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int nseg,
+ xSegment *pSeg
+){
+ XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
+ S3VPtr ps3v = S3VPTR(infoRec->pScrn);
+ ps3v->CurrentGC = pGC;
+ /* fb support */
+ ps3v->CurrentDrawable = pDraw;
+ if(infoRec->NeedToSync)
+ S3VAccelSync(infoRec->pScrn);
+ XAAPolySegment(pDraw, pGC, nseg, pSeg);
+}
+
+#endif
+
+static void
+S3VSubsequentSolidHorVertLine(
+ ScrnInfoPtr pScrn,
+ int x, int y,
+ int len, int dir
+){
+ S3VPtr ps3v = S3VPTR(pScrn);
+ int w, h;
+
+ if(dir == DEGREES_0) {
+ w = len; h = 1;
+ } else {
+ w = 1; h = len;
+ }
+
+ CHECK_DEST_BASE(y,h);
+
+ WAITFIFO(2);
+ OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
+ WAITCMD();
+ OUTREG(RDEST_XY, (x << 16) | y);
+}
+
+static void
+S3VSubsequentSolidHorVertLinePlaneMask(
+ ScrnInfoPtr pScrn,
+ int x, int y,
+ int len, int dir
+){
+ S3VPtr ps3v = S3VPTR(pScrn);
+ int w, h, dwords;
+
+ if(dir == DEGREES_0) {
+ w = len; h = 1; dwords = (len + 31) >> 5;
+ } else {
+ w = 1; h = len; dwords = len;
+ }
+
+ CHECK_DEST_BASE(y,h);
+
+ WAITFIFO(2);
+ OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
+ WAITCMD();
+ OUTREG(RDEST_XY, (x << 16) | y);
+
+ S3VWriteMask((CARD32*)ps3v->MapBaseDense, dwords);
+}
+
+/*EOF*/
diff --git a/src/s3v_xv.c b/src/s3v_xv.c
new file mode 100644
index 0000000..f756283
--- /dev/null
+++ b/src/s3v_xv.c
@@ -0,0 +1,981 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/s3v_xv.c,v 1.10tsi Exp $ */
+/*
+Copyright (C) 2000 The XFree86 Project, Inc. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the XFree86 Project shall not
+be used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the XFree86 Project.
+*/
+
+/*
+ * s3v_xv.c
+ * X Video Extension support
+ *
+ * S3 ViRGE driver
+ *
+ * 7/2000 Kevin Brosius
+ *
+ * Useful references:
+ * X Video extension support -> xc/programs/hw/xfree86/common/xf86xv.c
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+ /* Most xf86 commons are already in s3v.h */
+#include "s3v.h"
+
+#if 0
+#define OFF_DELAY 250 /* milliseconds */
+#define FREE_DELAY 15000
+
+#define OFF_TIMER 0x01
+#define FREE_TIMER 0x02
+#endif
+#define CLIENT_VIDEO_ON 0x04
+
+#define S3V_MAX_PORTS 1
+
+#if 0
+static void S3VInitOffscreenImages(ScreenPtr);
+#endif
+
+static XF86VideoAdaptorPtr S3VAllocAdaptor(ScrnInfoPtr pScrn);
+static XF86VideoAdaptorPtr S3VSetupImageVideoOverlay(ScreenPtr);
+static int S3VSetPortAttributeOverlay(ScrnInfoPtr, Atom, INT32, pointer);
+static int S3VGetPortAttributeOverlay(ScrnInfoPtr, Atom ,INT32 *, pointer);
+
+#if 0
+static XF86VideoAdaptorPtr MGASetupImageVideoTexture(ScreenPtr);
+static int MGASetPortAttributeTexture(ScrnInfoPtr, Atom, INT32, pointer);
+static int MGAGetPortAttributeTexture(ScrnInfoPtr, Atom ,INT32 *, pointer);
+#endif
+static void S3VStopVideo(ScrnInfoPtr, pointer, Bool);
+static void S3VQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short,
+ unsigned int *, unsigned int *, pointer);
+static int S3VPutImage(ScrnInfoPtr, short, short, short, short, short,
+ short, short, short, int, unsigned char*, short,
+ short, Bool, RegionPtr, pointer);
+static int S3VQueryImageAttributes(ScrnInfoPtr, int, unsigned short *,
+ unsigned short *, int *, int *);
+
+#if 0
+static void MGABlockHandler(int, pointer, pointer, pointer);
+#endif
+
+static void S3VResetVideoOverlay(ScrnInfoPtr);
+
+#if 0
+#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
+
+static Atom xvBrightness, xvContrast, xvColorKey;
+
+#endif /* 0 */
+
+int S3VQueryXvCapable(ScrnInfoPtr pScrn)
+{
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ if(
+ ((pScrn->bitsPerPixel == 24) ||
+ (pScrn->bitsPerPixel == 16)
+ )
+ &&
+ ((ps3v->Chipset == S3_ViRGE_DXGX) ||
+ S3_ViRGE_MX_SERIES(ps3v->Chipset) ||
+ S3_ViRGE_GX2_SERIES(ps3v->Chipset)
+ ))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+void S3VInitVideo(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
+ XF86VideoAdaptorPtr newAdaptor = NULL;
+ S3VPtr ps3v = S3VPTR(pScrn);
+ int num_adaptors;
+
+ if(
+ ((pScrn->bitsPerPixel == 24) ||
+ (pScrn->bitsPerPixel == 16)
+ )
+ &&
+ ((ps3v->Chipset == S3_ViRGE_DXGX) ||
+ S3_ViRGE_MX_SERIES(ps3v->Chipset) ||
+ S3_ViRGE_GX2_SERIES(ps3v->Chipset) /* || */
+ /* (ps3v->Chipset == S3_ViRGE) */
+ )
+ && !ps3v->NoAccel
+ && ps3v->XVideo
+ )
+ {
+#if 0
+ if((pMga->Overlay8Plus24 /* || dualhead */ || pMga->TexturedVideo) &&
+ (pScrn->bitsPerPixel != 24))
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using texture video\n");
+ newAdaptor = MGASetupImageVideoTexture(pScreen);
+ pMga->TexturedVideo = TRUE;
+ } else {
+#endif
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using overlay video\n");
+ newAdaptor = S3VSetupImageVideoOverlay(pScreen);
+
+#if 0
+ pMga->TexturedVideo = FALSE;
+ }*/
+
+ if(!pMga->Overlay8Plus24 /* && !dualhead */)
+ S3VInitOffscreenImages(pScreen);
+ pMga->BlockHandler = pScreen->BlockHandler;
+ pScreen->BlockHandler = MGABlockHandler;
+#endif
+ }
+
+
+ num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
+
+ if(newAdaptor) {
+ if(!num_adaptors) {
+ num_adaptors = 1;
+ adaptors = &newAdaptor;
+ } else {
+ newAdaptors = /* need to free this someplace */
+ xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
+ if(newAdaptors) {
+ memcpy(newAdaptors, adaptors, num_adaptors *
+ sizeof(XF86VideoAdaptorPtr));
+ newAdaptors[num_adaptors] = newAdaptor;
+ adaptors = newAdaptors;
+ num_adaptors++;
+ }
+ }
+ }
+
+ if(num_adaptors)
+ xf86XVScreenInit(pScreen, adaptors, num_adaptors);
+
+ if(newAdaptors)
+ xfree(newAdaptors);
+}
+
+/* client libraries expect an encoding */
+static XF86VideoEncodingRec DummyEncoding[2] =
+{
+ { /* overlay limit */
+ 0,
+ "XV_IMAGE",
+ 1024, 1024,
+ {1, 1}
+ },
+ { /* texture limit */
+ 0,
+ "XV_IMAGE",
+ 2046, 2046,
+ {1, 1}
+ }
+};
+
+#define NUM_FORMATS_OVERLAY 4
+#define NUM_FORMATS_TEXTURE 4
+
+static XF86VideoFormatRec Formats[NUM_FORMATS_TEXTURE] =
+{
+ /*{15, TrueColor},*/ {16, TrueColor}, {24, TrueColor} /* ,
+ {15, DirectColor}*/, {16, DirectColor}, {24, DirectColor}
+};
+
+#if 0
+#define NUM_ATTRIBUTES_OVERLAY 3
+
+static XF86AttributeRec Attributes[NUM_ATTRIBUTES_OVERLAY] =
+{
+ {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
+ {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
+ {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}
+};
+#endif
+
+#define NUM_IMAGES 3
+
+static XF86ImageRec Images[NUM_IMAGES] =
+{
+ XVIMAGE_YUY2,
+ /* As in mga, YV12 & I420 are converted to YUY2 on the fly by */
+ /* copy over conversion. */
+ XVIMAGE_YV12,
+ XVIMAGE_I420
+ /* XVIMAGE_UYVY */
+};
+
+
+
+static int
+S3VSetPortAttributeOverlay(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 value,
+ pointer data
+){
+#if 0
+ MGAPtr pMga = MGAPTR(pScrn);
+ MGAPortPrivPtr pPriv = pMga->portPrivate;
+
+ CHECK_DMA_QUIESCENT(pMga, pScrn);
+
+ if(attribute == xvBrightness) {
+ if((value < -128) || (value > 127))
+ return BadValue;
+ pPriv->brightness = value;
+ OUTREG(MGAREG_BESLUMACTL, ((pPriv->brightness & 0xff) << 16) |
+ (pPriv->contrast & 0xff));
+ } else
+ if(attribute == xvContrast) {
+ if((value < 0) || (value > 255))
+ return BadValue;
+ pPriv->contrast = value;
+ OUTREG(MGAREG_BESLUMACTL, ((pPriv->brightness & 0xff) << 16) |
+ (pPriv->contrast & 0xff));
+ } else
+ if(attribute == xvColorKey) {
+ pPriv->colorKey = value;
+ outMGAdac(0x55, (pPriv->colorKey & pScrn->mask.red) >>
+ pScrn->offset.red);
+ outMGAdac(0x56, (pPriv->colorKey & pScrn->mask.green) >>
+ pScrn->offset.green);
+ outMGAdac(0x57, (pPriv->colorKey & pScrn->mask.blue) >>
+ pScrn->offset.blue);
+ REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
+ } else
+#endif
+
+return BadMatch;
+
+#if 0
+ return Success;
+#endif
+}
+
+static int
+S3VGetPortAttributeOverlay(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 *value,
+ pointer data
+){
+#if 0
+ MGAPtr pMga = MGAPTR(pScrn);
+ MGAPortPrivPtr pPriv = pMga->portPrivate;
+
+ if(attribute == xvBrightness) {
+ *value = pPriv->brightness;
+ } else
+ if(attribute == xvContrast) {
+ *value = pPriv->contrast;
+ } else
+ if(attribute == xvColorKey) {
+ *value = pPriv->colorKey;
+ } else
+#endif
+
+return BadMatch;
+
+#if 0
+ return Success;
+#endif
+}
+
+
+
+static void
+S3VQueryBestSize(
+ ScrnInfoPtr pScrn,
+ Bool motion,
+ short vid_w, short vid_h,
+ short drw_w, short drw_h,
+ unsigned int *p_w, unsigned int *p_h,
+ pointer data
+){
+ *p_w = drw_w;
+ *p_h = drw_h;
+
+#if 0
+ /* Only support scaling up, no down scaling. */
+ /* This doesn't seem to work (at least for XMovie) */
+ /* and the DESIGN doc says this is illegal anyway... */
+ if( drw_w < vid_w ) *p_w = vid_w;
+ if( drw_h < vid_h ) *p_h = vid_h;
+#endif
+}
+
+
+
+static void
+S3VResetVideoOverlay(ScrnInfoPtr pScrn)
+{
+ /* empty for ViRGE at the moment... */
+#if 0
+ S3VPtr ps3v = S3VPTR(pScrn);
+ S3VPortPrivPtr pPriv = ps3v->portPrivate;
+
+ MGAPtr pMga = MGAPTR(pScrn);
+ MGAPortPrivPtr pPriv = pMga->portPrivate;
+
+ CHECK_DMA_QUIESCENT(pMga, pScrn);
+
+ outMGAdac(0x51, 0x01); /* keying on */
+ outMGAdac(0x52, 0xff); /* full mask */
+ outMGAdac(0x53, 0xff);
+ outMGAdac(0x54, 0xff);
+
+ outMGAdac(0x55, (pPriv->colorKey & pScrn->mask.red) >>
+ pScrn->offset.red);
+ outMGAdac(0x56, (pPriv->colorKey & pScrn->mask.green) >>
+ pScrn->offset.green);
+ outMGAdac(0x57, (pPriv->colorKey & pScrn->mask.blue) >>
+ pScrn->offset.blue);
+#endif
+
+#if 0
+ OUTREG(MGAREG_BESLUMACTL, ((pPriv->brightness & 0xff) << 16) |
+ (pPriv->contrast & 0xff));
+#endif /*0*/
+}
+
+
+
+static XF86VideoAdaptorPtr
+S3VAllocAdaptor(ScrnInfoPtr pScrn)
+{
+ XF86VideoAdaptorPtr adapt;
+ S3VPtr ps3v = S3VPTR(pScrn);
+ S3VPortPrivPtr pPriv;
+ int i;
+
+ if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn)))
+ return NULL;
+
+ if(!(pPriv = xcalloc(1, sizeof(S3VPortPrivRec) +
+ (sizeof(DevUnion) * S3V_MAX_PORTS))))
+ {
+ xfree(adapt);
+ return NULL;
+ }
+
+ adapt->pPortPrivates = (DevUnion*)(&pPriv[1]);
+
+ for(i = 0; i < S3V_MAX_PORTS; i++)
+ adapt->pPortPrivates[i].val = i;
+
+#if 0
+ xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
+ xvContrast = MAKE_ATOM("XV_CONTRAST");
+ xvColorKey = MAKE_ATOM("XV_COLORKEY");
+#endif
+
+ pPriv->colorKey =
+ (1 << pScrn->offset.red) |
+ (1 << pScrn->offset.green) |
+ (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue);
+
+#if 0
+ pPriv->brightness = 0;
+ pPriv->contrast = 128;
+#endif
+
+ pPriv->videoStatus = 0;
+ pPriv->lastPort = -1;
+
+ ps3v->adaptor = adapt;
+ ps3v->portPrivate = pPriv;
+
+ return adapt;
+}
+
+
+
+
+
+static XF86VideoAdaptorPtr
+S3VSetupImageVideoOverlay(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ S3VPtr ps3v = S3VPTR(pScrn);
+ XF86VideoAdaptorPtr adapt;
+
+ adapt = S3VAllocAdaptor(pScrn);
+
+ adapt->type = XvWindowMask | XvInputMask | XvImageMask;
+ adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
+ adapt->name = "S3 ViRGE Backend Scaler";
+ adapt->nEncodings = 1;
+ adapt->pEncodings = &DummyEncoding[0];
+ adapt->nFormats = NUM_FORMATS_OVERLAY;
+ adapt->pFormats = Formats;
+ adapt->nPorts = 1;
+ adapt->pAttributes = NULL /*Attributes*/;
+#if 0
+ if (pMga->Chipset == PCI_CHIP_MGAG400) {
+ adapt->nImages = 4;
+ adapt->nAttributes = 3;
+ } else {
+#endif
+ adapt->nImages = 3;
+ adapt->nAttributes = 0;
+ /* }*/
+ adapt->pImages = Images;
+ adapt->PutVideo = NULL;
+ adapt->PutStill = NULL;
+ adapt->GetVideo = NULL;
+ adapt->GetStill = NULL;
+ adapt->StopVideo = S3VStopVideo;
+ /* Empty Attrib functions - required anyway */
+ adapt->SetPortAttribute = S3VSetPortAttributeOverlay;
+ adapt->GetPortAttribute = S3VGetPortAttributeOverlay;
+ adapt->QueryBestSize = S3VQueryBestSize;
+ adapt->PutImage = S3VPutImage;
+ adapt->QueryImageAttributes = S3VQueryImageAttributes;
+
+ /* gotta uninit this someplace */
+ REGION_NULL(pScreen, &(ps3v->portPrivate->clip));
+
+ S3VResetVideoOverlay(pScrn);
+
+ return adapt;
+}
+
+
+static void
+S3VStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
+{
+ S3VPtr ps3v = S3VPTR(pScrn);
+ S3VPortPrivPtr pPriv = ps3v->portPrivate;
+
+#if 0
+ MGAPtr pMga = MGAPTR(pScrn);
+ MGAPortPrivPtr pPriv = pMga->portPrivate;
+
+ if(pMga->TexturedVideo) return;
+#endif
+
+ REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
+
+ if(shutdown) {
+ if(pPriv->videoStatus & CLIENT_VIDEO_ON)
+ {
+ if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) ||
+ S3_ViRGE_MX_SERIES(ps3v->Chipset)
+ )
+ {
+ /* Aaarg... It .. won't.. go .. away! */
+ /* So let's be creative, make the overlay really */
+ /* small and near an edge. */
+ /* Size of 0 leaves a window sized vertical stripe */
+ /* Size of 1 leaves a single pixel.. */
+ OUTREG(SSTREAM_WINDOW_SIZE_REG, 1);
+ /* And hide it at 0,0 */
+ OUTREG(SSTREAM_START_REG, 0 );
+ }
+ else
+ {
+ /* Primary over secondary */
+ OUTREG(BLEND_CONTROL_REG, 0x01000000);
+ }
+ }
+
+ if(pPriv->area) {
+ xf86FreeOffscreenArea(pPriv->area);
+ pPriv->area = NULL;
+ }
+ pPriv->videoStatus = 0;
+#if 0
+ } else {
+ if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
+ pPriv->videoStatus |= OFF_TIMER;
+ pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
+ }
+#endif
+ }
+}
+
+
+
+static FBAreaPtr
+S3VAllocateMemory(
+ ScrnInfoPtr pScrn,
+ FBAreaPtr area,
+ int numlines
+){
+ ScreenPtr pScreen;
+ FBAreaPtr new_area;
+
+ if(area) {
+ if((area->box.y2 - area->box.y1) >= numlines)
+ return area;
+
+ if(xf86ResizeOffscreenArea(area, pScrn->displayWidth, numlines))
+ return area;
+
+ xf86FreeOffscreenArea(area);
+ }
+
+ pScreen = screenInfo.screens[pScrn->scrnIndex];
+
+ new_area = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth,
+ numlines, 0, NULL, NULL, NULL);
+
+ if(!new_area) {
+ int max_w, max_h;
+
+ xf86QueryLargestOffscreenArea(pScreen, &max_w, &max_h, 0,
+ FAVOR_WIDTH_THEN_AREA, PRIORITY_EXTREME);
+
+ if((max_w < pScrn->displayWidth) || (max_h < numlines))
+ return NULL;
+
+ xf86PurgeUnlockedOffscreenAreas(pScreen);
+ new_area = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth,
+ numlines, 0, NULL, NULL, NULL);
+ }
+
+ return new_area;
+}
+
+
+
+static void
+S3VDisplayVideoOverlay(
+ ScrnInfoPtr pScrn,
+ int id,
+ int offset,
+ short width, short height,
+ int pitch,
+ /* x,y src co-ordinates */
+ int x1, int y1, int x2, int y2,
+ /* dst in BoxPtr format */
+ BoxPtr dstBox,
+ /* src width and height */
+ short src_w, short src_h,
+ /* dst width and height */
+ short drw_w, short drw_h
+){
+ int tmp;
+
+#if 0
+ CHECK_DMA_QUIESCENT(pMga, pScrn);
+#endif
+ S3VPtr ps3v = S3VPTR(pScrn);
+ S3VPortPrivPtr pPriv = ps3v->portPrivate;
+
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ /* S3VPtr ps3v = S3VPTR(pScrn);*/
+ int vgaCRIndex, vgaCRReg, vgaIOBase;
+ vgaIOBase = hwp->IOBase;
+ vgaCRIndex = vgaIOBase + 4;
+ vgaCRReg = vgaIOBase + 5;
+
+ /* If streams aren't enabled, do nothing */
+ if(!ps3v->NeedSTREAMS)
+ return;
+
+#if 0
+ /* got 64 scanlines to do it in */
+ tmp = INREG(MGAREG_VCOUNT) + 64;
+ if(tmp > pScrn->currentMode->VDisplay)
+ tmp -= pScrn->currentMode->VDisplay;
+#endif
+
+ /* Reference at http://www.webartz.com/fourcc/ */
+ /* Looks like ViRGE only supports YUY2 and Y211?, */
+ /* listed as YUV-16 (4.2.2) and YUV (2.1.1) in manual. */
+
+#if 0
+ /* Only supporting modes we listed for the time being, */
+ /* No, switching required... #if 0'd this out */
+
+ switch(id) {
+ case FOURCC_UYVY:
+ /*
+ FOURCC=0x59565955
+ bpp=16
+ YUV 4:2:2 (Y sample at every
+ pixel, U and V sampled at
+ every second pixel
+ horizontally on each line). A
+ macropixel contains 2 pixels
+ in 1 u_int32.
+ */
+
+ /* OUTREG(MGAREG_BESGLOBCTL, 0x000000c3 | (tmp << 16));*/
+ break;
+ case FOURCC_YUY2:
+ /*
+ FOURCC=0x32595559
+ bpp=16
+ YUV 4:2:2 as for UYVY but
+ with different component
+ ordering within the u_int32
+ macropixel.
+
+ Supports YV12 & I420 by copy over conversion of formats to YUY2,
+ copied from mga driver. Thanks Mark!
+ */
+ default:
+ /*OUTREG(MGAREG_BESGLOBCTL, 0x00000083 | (tmp << 16));*/
+ /* YUV-16 (4.2.2) Secondary stream */
+ /* temp ... add DDA Horiz Accum. */
+ /*OUTREG(SSTREAM_CONTROL_REG, 0x02000000); / YUV-16 */
+ /* works for xvtest and suzi */
+ /* OUTREG(SSTREAM_CONTROL_REG, 0x01000000); * YCbCr-16 * no scaling */
+
+ /* calc horizontal scale factor */
+ tmp = drw_w / src_w;
+ if (drw_w == src_w) tmp = 0;
+ else if (tmp>=4) tmp =3;
+ else if (tmp>=2) tmp =2;
+ else tmp =1;
+
+ /* YCbCr-16 */
+ OUTREG(SSTREAM_CONTROL_REG,
+ tmp << 28 | 0x01000000 |
+ ((((src_w-1)<<1)-(drw_w-1)) & 0xfff)
+ );
+ break;
+ }
+#endif
+
+ /* calc horizontal scale factor */
+ if (drw_w == src_w)
+ tmp = 0;
+ else
+ tmp =2;
+ /* YCbCr-16 */
+ OUTREG(SSTREAM_CONTROL_REG,
+ tmp << 28 | 0x01000000 |
+ ((((src_w-1)<<1)-(drw_w-1)) & 0xfff)
+ );
+
+ OUTREG(SSTREAM_STRETCH_REG,
+ ((src_w - 1) & 0x7ff) | (((src_w-drw_w-1) & 0x7ff) << 16)
+ );
+
+ /* Color key on primary */
+ if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) ||
+ S3_ViRGE_MX_SERIES(ps3v->Chipset)
+ )
+ {
+ /* 100% of secondary, no primary */
+ /* gx2/mx can both blend while keying, need to */
+ /* select secondary here, otherwise all you'll get */
+ /* from the primary is the color key. (And setting */
+ /* 0 here gives you black... no primary or secondary. */
+ /* Discovered that the hard way!) */
+ OUTREG(BLEND_CONTROL_REG, 0x20 );
+ }
+ else
+ {
+ OUTREG(BLEND_CONTROL_REG, 0x05000000);
+ }
+
+ OUTREG(SSTREAM_FBADDR0_REG, offset & 0x3fffff );
+ OUTREG(SSTREAM_STRIDE_REG, pitch & 0xfff );
+
+ OUTREG(K1_VSCALE_REG, src_h-1 );
+ OUTREG(K2_VSCALE_REG, (src_h - drw_h) & 0x7ff );
+
+ if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) ||
+ S3_ViRGE_MX_SERIES(ps3v->Chipset) )
+ {
+ /* enable vert interp. & bandwidth saving - gx2 */
+ OUTREG(DDA_VERT_REG, (((~drw_h)-1) & 0xfff ) |
+ /* bw & vert interp */
+ 0xc000
+ /* no bw save 0x8000*/
+ );
+ }
+ else
+ {
+ OUTREG(DDA_VERT_REG, (((~drw_h)-1)) & 0xfff );
+ }
+
+ OUTREG(SSTREAM_START_REG, ((dstBox->x1 +1) << 16) | (dstBox->y1 +1));
+ OUTREG(SSTREAM_WINDOW_SIZE_REG,
+ ( ((drw_w-1) << 16) | (drw_h ) ) & 0x7ff07ff
+ );
+
+ if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) ||
+ S3_ViRGE_MX_SERIES(ps3v->Chipset)
+ )
+ {
+ OUTREG(COL_CHROMA_KEY_CONTROL_REG,
+ /* color key ON - keying on primary */
+ 0x40000000 |
+ /* # bits to compare */
+ ((pScrn->weight.red-1) << 24) |
+
+ ((pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red) <<
+ (16 + 8-pScrn->weight.red) |
+
+ ((pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green) <<
+ (8 + 8-pScrn->weight.green) |
+
+ ((pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue) <<
+ (8-pScrn->weight.blue)
+ );
+ }
+ else
+ {
+ OUTREG(COL_CHROMA_KEY_CONTROL_REG,
+ /* color key ON */
+ 0x10000000 |
+ /* # bits to compare */
+ ((pScrn->weight.red-1) << 24) |
+
+ ((pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red) <<
+ (16 + 8-pScrn->weight.red) |
+
+ ((pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green) <<
+ (8 + 8-pScrn->weight.green) |
+
+ ((pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue) <<
+ (8-pScrn->weight.blue)
+ );
+ }
+
+ if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) ||
+ S3_ViRGE_MX_SERIES(ps3v->Chipset) )
+ {
+ VGAOUT8(vgaCRIndex, 0x92);
+ VGAOUT8(vgaCRReg, (((pitch + 7) / 8) >> 8) | 0x80);
+ VGAOUT8(vgaCRIndex, 0x93);
+ VGAOUT8(vgaCRReg, (pitch + 7) / 8);
+ }
+
+}
+
+
+static int
+S3VPutImage(
+ ScrnInfoPtr pScrn,
+ short src_x, short src_y,
+ short drw_x, short drw_y,
+ short src_w, short src_h,
+ short drw_w, short drw_h,
+ int id, unsigned char* buf,
+ short width, short height,
+ Bool sync,
+ RegionPtr clipBoxes, pointer data
+){
+ S3VPtr ps3v = S3VPTR(pScrn);
+ S3VPortPrivPtr pPriv = ps3v->portPrivate;
+ INT32 x1, x2, y1, y2;
+ unsigned char *dst_start;
+ int pitch, new_h, offset, offset2=0, offset3=0;
+ int srcPitch, srcPitch2=0, dstPitch;
+ int top, left, npixels, nlines;
+ BoxRec dstBox;
+ CARD32 tmp;
+
+ /* If streams aren't enabled, do nothing */
+ if(!ps3v->NeedSTREAMS)
+ return Success;
+
+ /* Clip */
+ x1 = src_x;
+ x2 = src_x + src_w;
+ y1 = src_y;
+ y2 = src_y + src_h;
+
+ dstBox.x1 = drw_x;
+ dstBox.x2 = drw_x + drw_w;
+ dstBox.y1 = drw_y;
+ dstBox.y2 = drw_y + drw_h;
+
+ if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2,
+ clipBoxes, width, height))
+ return Success;
+
+ /*if(!pMga->TexturedVideo) {*/
+ dstBox.x1 -= pScrn->frameX0;
+ dstBox.x2 -= pScrn->frameX0;
+ dstBox.y1 -= pScrn->frameY0;
+ dstBox.y2 -= pScrn->frameY0;
+ /*}*/
+
+ pitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3;
+
+ dstPitch = ((width << 1) + 15) & ~15;
+ new_h = ((dstPitch * height) + pitch - 1) / pitch;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ srcPitch = (width + 3) & ~3;
+ offset2 = srcPitch * height;
+ srcPitch2 = ((width >> 1) + 3) & ~3;
+ offset3 = (srcPitch2 * (height >> 1)) + offset2;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ srcPitch = (width << 1);
+ break;
+ }
+
+ if(!(pPriv->area = S3VAllocateMemory(pScrn, pPriv->area, new_h)))
+ return BadAlloc;
+
+ /* copy data */
+ top = y1 >> 16;
+ left = (x1 >> 16) & ~1;
+ npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
+ left <<= 1;
+
+ offset = pPriv->area->box.y1 * pitch;
+ dst_start = ps3v->FBStart + offset + left + (top * dstPitch);
+ /*dst_start = pMga->FbStart + offset + left + (top * dstPitch);*/
+
+#if 0
+ if(pMga->TexturedVideo && pMga->AccelInfoRec->NeedToSync &&
+ ((long)data != pPriv->lastPort))
+ {
+ MGAStormSync(pScrn);
+ pMga->AccelInfoRec->NeedToSync = FALSE;
+ }
+#endif
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ top &= ~1;
+ tmp = ((top >> 1) * srcPitch2) + (left >> 2);
+ offset2 += tmp;
+ offset3 += tmp;
+ if(id == FOURCC_I420) {
+ tmp = offset2;
+ offset2 = offset3;
+ offset3 = tmp;
+ }
+ nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
+ xf86XVCopyYUV12ToPacked(buf + (top * srcPitch) + (left >> 1),
+ buf + offset2, buf + offset3, dst_start,
+ srcPitch, srcPitch2, dstPitch, nlines, npixels);
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ buf += (top * srcPitch) + left;
+ nlines = ((y2 + 0xffff) >> 16) - top;
+ xf86XVCopyPacked(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
+ break;
+ }
+
+#if 0
+ if(pMga->TexturedVideo) {
+ pPriv->lastPort = (long)data;
+ MGADisplayVideoTexture(pScrn, id, offset,
+ REGION_NUM_RECTS(clipBoxes), REGION_RECTS(clipBoxes),
+ width, height, dstPitch, src_x, src_y, src_w, src_h,
+ drw_x, drw_y, drw_w, drw_h);
+ pPriv->videoStatus = FREE_TIMER;
+ pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
+ } else {
+#endif
+ /* update cliplist */
+ if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
+ REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
+ /* draw these */
+ xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
+ }
+
+ offset += left + (top * dstPitch);
+ S3VDisplayVideoOverlay(pScrn, id, offset, width, height, dstPitch,
+ x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
+
+ pPriv->videoStatus = CLIENT_VIDEO_ON;
+#if 0
+ }
+ pMga->VideoTimerCallback = MGAVideoTimerCallback;
+#endif
+
+ return Success;
+}
+
+
+static int
+S3VQueryImageAttributes(
+ ScrnInfoPtr pScrn,
+ int id,
+ unsigned short *w, unsigned short *h,
+ int *pitches, int *offsets
+){
+#if 0
+ MGAPtr pMga = MGAPTR(pScrn);
+#endif
+ int size, tmp;
+
+#if 0
+ if(pMga->TexturedVideo) {
+ if(*w > 2046) *w = 2046;
+ if(*h > 2046) *h = 2046;
+ } else {
+#endif
+ if(*w > 1024) *w = 1024;
+ if(*h > 1024) *h = 1024;
+#if 0
+ }
+#endif
+
+ *w = (*w + 1) & ~1;
+ if(offsets) offsets[0] = 0;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ *h = (*h + 1) & ~1;
+ size = (*w + 3) & ~3;
+ if(pitches) pitches[0] = size;
+ size *= *h;
+ if(offsets) offsets[1] = size;
+ tmp = ((*w >> 1) + 3) & ~3;
+ if(pitches) pitches[1] = pitches[2] = tmp;
+ tmp *= (*h >> 1);
+ size += tmp;
+ if(offsets) offsets[2] = size;
+ size += tmp;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ size = *w << 1;
+ if(pitches) pitches[0] = size;
+ size *= *h;
+ break;
+ }
+
+ return size;
+}