diff options
author | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2006-11-26 20:11:22 +0000 |
---|---|---|
committer | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2006-11-26 20:11:22 +0000 |
commit | c242f9427187ed63205b55ff46c6d406095c130f (patch) | |
tree | 052d75a483a93468ba181335f693cc8dbfe0da4a /driver/xf86-video-s3virge/src | |
parent | 8449938b3156c2e835519154c19f2d80bb39e531 (diff) |
Importing xf86-video-s3virge 1.9.1
Diffstat (limited to 'driver/xf86-video-s3virge/src')
-rw-r--r-- | driver/xf86-video-s3virge/src/Makefile.am | 44 | ||||
-rw-r--r-- | driver/xf86-video-s3virge/src/Makefile.in | 530 | ||||
-rw-r--r-- | driver/xf86-video-s3virge/src/newmmio.h | 619 | ||||
-rw-r--r-- | driver/xf86-video-s3virge/src/regs3v.h | 310 | ||||
-rw-r--r-- | driver/xf86-video-s3virge/src/s3v.h | 418 | ||||
-rw-r--r-- | driver/xf86-video-s3virge/src/s3v_accel.c | 1001 | ||||
-rw-r--r-- | driver/xf86-video-s3virge/src/s3v_dac.c | 125 | ||||
-rw-r--r-- | driver/xf86-video-s3virge/src/s3v_dga.c | 361 | ||||
-rw-r--r-- | driver/xf86-video-s3virge/src/s3v_driver.c | 3891 | ||||
-rw-r--r-- | driver/xf86-video-s3virge/src/s3v_hwcurs.c | 266 | ||||
-rw-r--r-- | driver/xf86-video-s3virge/src/s3v_i2c.c | 119 | ||||
-rw-r--r-- | driver/xf86-video-s3virge/src/s3v_macros.h | 127 | ||||
-rw-r--r-- | driver/xf86-video-s3virge/src/s3v_rop.h | 207 | ||||
-rw-r--r-- | driver/xf86-video-s3virge/src/s3v_shadow.c | 304 | ||||
-rw-r--r-- | driver/xf86-video-s3virge/src/s3v_xv.c | 982 |
15 files changed, 9304 insertions, 0 deletions
diff --git a/driver/xf86-video-s3virge/src/Makefile.am b/driver/xf86-video-s3virge/src/Makefile.am new file mode 100644 index 000000000..41d21773e --- /dev/null +++ b/driver/xf86-video-s3virge/src/Makefile.am @@ -0,0 +1,44 @@ +# 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_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/driver/xf86-video-s3virge/src/Makefile.in b/driver/xf86-video-s3virge/src/Makefile.in new file mode 100644 index 000000000..8907da760 --- /dev/null +++ b/driver/xf86-video-s3virge/src/Makefile.in @@ -0,0 +1,530 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# 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. + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(s3virge_drv_ladir)" +s3virge_drv_laLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(s3virge_drv_la_LTLIBRARIES) +s3virge_drv_la_LIBADD = +am_s3virge_drv_la_OBJECTS = s3v_accel.lo s3v_dac.lo s3v_dga.lo \ + s3v_driver.lo s3v_hwcurs.lo s3v_i2c.lo s3v_shadow.lo s3v_xv.lo +s3virge_drv_la_OBJECTS = $(am_s3virge_drv_la_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(s3virge_drv_la_SOURCES) +DIST_SOURCES = $(s3virge_drv_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ADMIN_MAN_DIR = @ADMIN_MAN_DIR@ +ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +APP_MAN_DIR = @APP_MAN_DIR@ +APP_MAN_SUFFIX = @APP_MAN_SUFFIX@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_LINUXDOC_FALSE = @BUILD_LINUXDOC_FALSE@ +BUILD_LINUXDOC_TRUE = @BUILD_LINUXDOC_TRUE@ +BUILD_PDFDOC_FALSE = @BUILD_PDFDOC_FALSE@ +BUILD_PDFDOC_TRUE = @BUILD_PDFDOC_TRUE@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DRIVER_MAN_DIR = @DRIVER_MAN_DIR@ +DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@ +DRIVER_NAME = @DRIVER_NAME@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +FILE_MAN_DIR = @FILE_MAN_DIR@ +FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIB_MAN_DIR = @LIB_MAN_DIR@ +LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@ +LINUXDOC = @LINUXDOC@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ +MAKEINFO = @MAKEINFO@ +MAKE_HTML = @MAKE_HTML@ +MAKE_PDF = @MAKE_PDF@ +MAKE_PS = @MAKE_PS@ +MAKE_TEXT = @MAKE_TEXT@ +MISC_MAN_DIR = @MISC_MAN_DIR@ +MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PS2PDF = @PS2PDF@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +XORG_CFLAGS = @XORG_CFLAGS@ +XORG_LIBS = @XORG_LIBS@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ + +# 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_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 + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-s3virge_drv_laLTLIBRARIES: $(s3virge_drv_la_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(s3virge_drv_ladir)" || $(mkdir_p) "$(DESTDIR)$(s3virge_drv_ladir)" + @list='$(s3virge_drv_la_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=install $(s3virge_drv_laLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(s3virge_drv_ladir)/$$f'"; \ + $(LIBTOOL) --mode=install $(s3virge_drv_laLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(s3virge_drv_ladir)/$$f"; \ + else :; fi; \ + done + +uninstall-s3virge_drv_laLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @set -x; list='$(s3virge_drv_la_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(s3virge_drv_ladir)/$$p'"; \ + $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(s3virge_drv_ladir)/$$p"; \ + done + +clean-s3virge_drv_laLTLIBRARIES: + -test -z "$(s3virge_drv_la_LTLIBRARIES)" || rm -f $(s3virge_drv_la_LTLIBRARIES) + @list='$(s3virge_drv_la_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +s3virge_drv.la: $(s3virge_drv_la_OBJECTS) $(s3virge_drv_la_DEPENDENCIES) + $(LINK) -rpath $(s3virge_drv_ladir) $(s3virge_drv_la_LDFLAGS) $(s3virge_drv_la_OBJECTS) $(s3virge_drv_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/s3v_accel.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/s3v_dac.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/s3v_dga.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/s3v_driver.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/s3v_hwcurs.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/s3v_i2c.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/s3v_shadow.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/s3v_xv.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(s3virge_drv_ladir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-s3virge_drv_laLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-s3virge_drv_laLTLIBRARIES + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am uninstall-s3virge_drv_laLTLIBRARIES + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-s3virge_drv_laLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-s3virge_drv_laLTLIBRARIES install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-info-am \ + uninstall-s3virge_drv_laLTLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/driver/xf86-video-s3virge/src/newmmio.h b/driver/xf86-video-s3virge/src/newmmio.h new file mode 100644 index 000000000..59ba57571 --- /dev/null +++ b/driver/xf86-video-s3virge/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/driver/xf86-video-s3virge/src/regs3v.h b/driver/xf86-video-s3virge/src/regs3v.h new file mode 100644 index 000000000..60530545f --- /dev/null +++ b/driver/xf86-video-s3virge/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/driver/xf86-video-s3virge/src/s3v.h b/driver/xf86-video-s3virge/src/s3v.h new file mode 100644 index 000000000..a20630db8 --- /dev/null +++ b/driver/xf86-video-s3virge/src/s3v.h @@ -0,0 +1,418 @@ +/* $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 + +#include <string.h> + +/* All drivers should typically include these */ +#include "xf86.h" +#include "xf86_OSproc.h" + +/* All drivers need this */ + +/* 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" + +#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 tagS3VRec { + /* 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; + + /* 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; + /* Compatibility variables */ + int vgaCRIndex, vgaCRReg; + int Width, Bpp,Bpl, ScissB; + /* XAA */ + unsigned PlaneMask; + int bltbug_width1, bltbug_width2; + /* In units as noted, set in PreInit */ + int videoRambytes; + int videoRamKbytes; + /* In Kbytes, set in PreInit */ + int MemOffScreen; + /* Holds the virtual memory address */ + /* returned when the MMIO registers */ + /* are mapped with xf86MapPciMem */ + unsigned char * MapBase; + unsigned char * MapBaseDense; + + /* Same as MapBase, except framebuffer*/ + unsigned char * FBBase; + /* Current visual FB starting location */ + unsigned char * FBStart; + /* Cursor storage location */ + CARD32 FBCursorOffset; + /* Saved CR53 value */ + unsigned char EnableMmioCR53; + /* Extended reg unlock storage */ + unsigned char CR38,CR39,CR40; + /* Flag indicating if vgaHWMapMem was */ + /* used successfully for this screen */ + Bool PrimaryVidMapped; + int HorizScaleFactor; + Bool bankedMono; + /* Memory Clock */ + int MCLK; + /* input reference Clock */ + int REFCLK; + /* MX LCD clock */ + int LCDClk; + /* MX reference clock scale */ + double refclk_fact; + /* Limit the number of errors */ + /* printed using a counter */ + int GEResetCnt; + /* Accel WaitFifo function */ + void (*pWaitFifo)(struct tagS3VRec *, int); + /* Accel WaitCmd function */ + void (*pWaitCmd)(struct tagS3VRec *); + + /*************************/ + /* ViRGE options -start- */ + /*************************/ + 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; + /* ViRGE options -end- */ + /***********************/ + /* ViRGE specifics -end- */ + + /* Used by ViRGE driver, but generic */ + + /* Pointer used to save wrapped */ + /* CloseScreen function. */ + CloseScreenProcPtr CloseScreen; + /* XAA info Rec */ + XAAInfoRecPtr AccelInfoRec; + /* PCI info vars. */ + pciVideoPtr PciInfo; + PCITAG PciTag; + /* Chip info, set using PCI */ + /* above. */ + int Chipset; + int ChipRev; + /* DGA2 */ + DGAModePtr DGAModes; + int numDGAModes; + Bool DGAactive; + int DGAViewportStatus; + I2CBusPtr I2C; + vbeInfoPtr pVbe; + Bool shadowFB; + int rotate; + unsigned char * ShadowPtr; + int ShadowPitch; + void (*PointerMoved)(int index, int x, int y); + + /* Used by ViRGE driver, but generic -end- */ + + +} 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); + +/* 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/driver/xf86-video-s3virge/src/s3v_accel.c b/driver/xf86-video-s3virge/src/s3v_accel.c new file mode 100644 index 000000000..faed1bdad --- /dev/null +++ b/driver/xf86-video-s3virge/src/s3v_accel.c @@ -0,0 +1,1001 @@ +/* $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 S3VWriteMask(CARD32*, int); + +static void S3VEngineReset(ScrnInfoPtr pScrn); +/* s3v.h - static void S3VAccelSync(ScrnInfoPtr); */ +static void S3VSetupForSolidFill(ScrnInfoPtr, int, int, unsigned); +static void S3VSubsequentSolidFillRect(ScrnInfoPtr, int, int, int, int); +static void S3VSubsequentSolidFillRectPlaneMask(ScrnInfoPtr, int, int, + int, int); +static void S3VSetupForMono8x8PatternFill(ScrnInfoPtr,int, int, int, int, + int, unsigned int); +static void S3VSubsequentMono8x8PatternFillRect(ScrnInfoPtr,int, int, + int, int, int, int); +static void S3VSubsequentMono8x8PatternFillRectPlaneMask(ScrnInfoPtr,int, int, + int, int, int, int); +static void S3VSetupForScreenToScreenCopy(ScrnInfoPtr, int, int, int, + unsigned int, int); +static void S3VSubsequentScreenToScreenCopy(ScrnInfoPtr, int, int, int, int, + int, int); +static void S3VSetupForCPUToScreenColorExpand(ScrnInfoPtr, int, int, int, + unsigned int); +static void S3VSubsequentCPUToScreenColorExpand(ScrnInfoPtr, int, int, int, + int, int); +static void S3VSetupForImageWrite(ScrnInfoPtr, int, unsigned int, int, + int, int); +static void S3VSubsequentImageWriteRect(ScrnInfoPtr, int, int, int, int, int); +static void S3VSubsequentSolidHorVertLine(ScrnInfoPtr, int, int, int, int); +static void S3VSubsequentSolidHorVertLinePlaneMask(ScrnInfoPtr, int, int, + int, int); +#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 +static void S3VNopAllCmdSets(ScrnInfoPtr pScrn); + + +Bool +S3VAccelInit(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoPtr; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + S3VPtr ps3v = S3VPTR(pScrn); + BoxRec AvailFBArea; + + ps3v->AccelInfoRec = infoPtr = XAACreateInfoRec(); + if(!infoPtr) return FALSE; + + 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 ? */ + + + infoPtr->Flags = PIXMAP_CACHE | + LINEAR_FRAMEBUFFER | + OFFSCREEN_PIXMAPS; + + infoPtr->Sync = S3VAccelSync; + + /* Problem reports with solid fill on trio3d */ + if(!S3_TRIO_3D_SERIES(ps3v->Chipset)) + { + /* Solid filled rects */ + infoPtr->SetupForSolidFill = + S3VSetupForSolidFill; + infoPtr->SubsequentSolidFillRect = + S3VSubsequentSolidFillRect; + } + + /* Screen to screen copies */ + infoPtr->SetupForScreenToScreenCopy = + S3VSetupForScreenToScreenCopy; + infoPtr->SubsequentScreenToScreenCopy = + S3VSubsequentScreenToScreenCopy; + infoPtr->ScreenToScreenCopyFlags = NO_TRANSPARENCY; + + /* Mono 8x8 patterns */ + infoPtr->SetupForMono8x8PatternFill = + S3VSetupForMono8x8PatternFill; + infoPtr->SubsequentMono8x8PatternFillRect = + S3VSubsequentMono8x8PatternFillRect; + infoPtr->Mono8x8PatternFillFlags = 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 */ + infoPtr->CPUToScreenColorExpandFillFlags = ROP_NEEDS_SOURCE | + CPU_TRANSFER_PAD_DWORD | + SCANLINE_PAD_DWORD | + BIT_ORDER_IN_BYTE_MSBFIRST | + LEFT_EDGE_CLIPPING; + + if(ps3v->AccelFlags & MONO_TRANS_BUG) + infoPtr->CPUToScreenColorExpandFillFlags |= NO_TRANSPARENCY; + + infoPtr->ColorExpandRange = 0x8000; + infoPtr->ColorExpandBase = ps3v->MapBaseDense; + infoPtr->SetupForCPUToScreenColorExpandFill = + S3VSetupForCPUToScreenColorExpand; + infoPtr->SubsequentCPUToScreenColorExpandFill = + S3VSubsequentCPUToScreenColorExpand; + + } /* if(!GX2...) */ + + + /* Image Writes */ + infoPtr->ImageWriteFlags = ROP_NEEDS_SOURCE | + NO_TRANSPARENCY | + CPU_TRANSFER_PAD_DWORD | + SCANLINE_PAD_DWORD | + NO_GXCOPY | /* added - kjb */ + LEFT_EDGE_CLIPPING; + + infoPtr->ImageWriteRange = 0x8000; + infoPtr->ImageWriteBase = ps3v->MapBaseDense; + infoPtr->SetupForImageWrite = S3VSetupForImageWrite; + infoPtr->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 GE */ + + ps3v->Width = pScrn->displayWidth; + /* Bytes per pixel */ + ps3v->Bpp = pScrn->bitsPerPixel / 8; + /* 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 */ + infoPtr->maxOffPixWidth = 2048; + infoPtr->maxOffPixHeight = 2048; + + return (XAAInit(pScreen, infoPtr)); +} + + +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); +} + +/* The sync function for the GE */ +void +S3VAccelSync(ScrnInfoPtr pScrn) +{ + S3VPtr ps3v = S3VPTR(pScrn); + + WAITIDLE(); +} + + +static 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; +} + + + /************************\ + | 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); +} + + +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/driver/xf86-video-s3virge/src/s3v_dac.c b/driver/xf86-video-s3virge/src/s3v_dac.c new file mode 100644 index 000000000..180b7f46c --- /dev/null +++ b/driver/xf86-video-s3virge/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/driver/xf86-video-s3virge/src/s3v_dga.c b/driver/xf86-video-s3virge/src/s3v_dga.c new file mode 100644 index 000000000..4449a67df --- /dev/null +++ b/driver/xf86-video-s3virge/src/s3v_dga.c @@ -0,0 +1,361 @@ +/* $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 "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/driver/xf86-video-s3virge/src/s3v_driver.c b/driver/xf86-video-s3virge/src/s3v_driver.c new file mode 100644 index 000000000..49f87afed --- /dev/null +++ b/driver/xf86-video-s3virge/src/s3v_driver.c @@ -0,0 +1,3891 @@ +/* $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.9.1" +#define S3VIRGE_VERSION_MAJOR 1 +#define S3VIRGE_VERSION_MINOR 9 +#define S3VIRGE_PATCHLEVEL 1 +#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_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_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 *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, 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->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 ) { + if (!xf86LoadSubModule(pScrn, "xaa")) { + S3VFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(xaaSymbols, 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 */ + 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->AccelInfoRec) + XAADestroyInfoRec(ps3v->AccelInfoRec); + 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/driver/xf86-video-s3virge/src/s3v_hwcurs.c b/driver/xf86-video-s3virge/src/s3v_hwcurs.c new file mode 100644 index 000000000..8ea3eeb99 --- /dev/null +++ b/driver/xf86-video-s3virge/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/driver/xf86-video-s3virge/src/s3v_i2c.c b/driver/xf86-video-s3virge/src/s3v_i2c.c new file mode 100644 index 000000000..2dd812bbf --- /dev/null +++ b/driver/xf86-video-s3virge/src/s3v_i2c.c @@ -0,0 +1,119 @@ +/* $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 "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/driver/xf86-video-s3virge/src/s3v_macros.h b/driver/xf86-video-s3virge/src/s3v_macros.h new file mode 100644 index 000000000..c8d1ef8c8 --- /dev/null +++ b/driver/xf86-video-s3virge/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/driver/xf86-video-s3virge/src/s3v_rop.h b/driver/xf86-video-s3virge/src/s3v_rop.h new file mode 100644 index 000000000..e4b393a6d --- /dev/null +++ b/driver/xf86-video-s3virge/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/driver/xf86-video-s3virge/src/s3v_shadow.c b/driver/xf86-video-s3virge/src/s3v_shadow.c new file mode 100644 index 000000000..b2cdf9d5a --- /dev/null +++ b/driver/xf86-video-s3virge/src/s3v_shadow.c @@ -0,0 +1,304 @@ +/* $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 "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/driver/xf86-video-s3virge/src/s3v_xv.c b/driver/xf86-video-s3virge/src/s3v_xv.c new file mode 100644 index 000000000..5e5476d1a --- /dev/null +++ b/driver/xf86-video-s3virge/src/s3v_xv.c @@ -0,0 +1,982 @@ +/* $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, DrawablePtr); +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, + DrawablePtr pDraw +){ + 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; +} |