diff options
Diffstat (limited to 'hw/xfree86/common')
60 files changed, 33275 insertions, 0 deletions
diff --git a/hw/xfree86/common/Makefile.am b/hw/xfree86/common/Makefile.am new file mode 100644 index 0000000..c031d4b --- /dev/null +++ b/hw/xfree86/common/Makefile.am @@ -0,0 +1,92 @@ +noinst_LTLIBRARIES = libcommon.la + +if XORG_BUS_SPARC +SBUS_SOURCES = xf86sbusBus.c +endif + +if XV +XVSOURCES = xf86xv.c xf86xvmc.c +XVSDKINCS = xf86xv.h xf86xvmc.h xf86xvpriv.h +endif + +if XF86VIDMODE +XF86VMODE_SDK = vidmodeproc.h +endif + +if DGA +DGASOURCES = xf86DGA.c +endif + +RANDRSOURCES = xf86RandR.c + +BUSSOURCES = xf86pciBus.c xf86fbBus.c xf86noBus.c $(SBUS_SOURCES) + +MODEDEFSOURCES = $(srcdir)/vesamodes $(srcdir)/extramodes + +xf86DefModeSet.c: $(srcdir)/modeline2c.awk $(MODEDEFSOURCES) + $(AM_V_GEN)cat $(MODEDEFSOURCES) | LC_ALL=C $(AWK) -f $(srcdir)/modeline2c.awk > $@ + $(AM_V_GEN)echo >> $@ + +BUILT_SOURCES = xf86DefModeSet.c + +AM_LDFLAGS = -r +libcommon_la_SOURCES = xf86Configure.c xf86ShowOpts.c xf86Bus.c xf86Config.c \ + xf86Cursor.c $(DGASOURCES) xf86DPMS.c \ + xf86Events.c xf86Globals.c xf86AutoConfig.c \ + xf86Option.c xf86Init.c xf86VGAarbiter.c \ + xf86VidMode.c xf86fbman.c xf86cmap.c \ + xf86Helper.c xf86PM.c xf86Xinput.c xisb.c \ + xf86Mode.c xorgHelper.c \ + $(XVSOURCES) $(BUSSOURCES) $(RANDRSOURCES) +nodist_libcommon_la_SOURCES = xf86DefModeSet.c xf86Build.h +libcommon_la_LIBADD = $(top_builddir)/config/libconfig.la + +INCLUDES = $(XORG_INCS) -I$(srcdir)/../ddc -I$(srcdir)/../i2c \ + -I$(srcdir)/../loader -I$(srcdir)/../parser \ + -I$(srcdir)/../vbe -I$(srcdir)/../int10 \ + -I$(srcdir)/../vgahw -I$(srcdir)/../dixmods/extmod \ + -I$(srcdir)/../modes -I$(srcdir)/../ramdac + +sdk_HEADERS = compiler.h fourcc.h xf86.h xf86Module.h xf86Opt.h \ + xf86PciInfo.h xf86Priv.h xf86Privstr.h \ + xf86cmap.h xf86fbman.h xf86str.h xf86Xinput.h xisb.h \ + $(XVSDKINCS) $(XF86VMODE_SDK) xorgVersion.h \ + xf86sbusBus.h xf86VGAarbiter.h + +DISTCLEANFILES = xf86Build.h +CLEANFILES = $(BUILT_SOURCES) + +EXTRA_DIST = \ + compiler.h \ + fourcc.h \ + vidmodeproc.h \ + xf86.h \ + xf86Bus.h \ + xf86Config.h \ + xf86InPriv.h \ + xf86Module.h \ + xf86Opt.h \ + xf86PciInfo.h \ + xf86Priv.h \ + xf86Privstr.h \ + xf86Xinput.h \ + xf86cmap.h \ + xf86fbman.h \ + xf86pciBus.h \ + xf86str.h \ + xf86xv.h \ + xf86xvmc.h \ + xf86xvpriv.h \ + xisb.h \ + xorgVersion.h \ + $(MODEDEFSOURCES) \ + modeline2c.awk \ + xf86VGAarbiter.h \ + xf86VGAarbiterPriv.h \ + $(DISTKBDSOURCES) + +if LNXACPI +XORG_CFLAGS += -DHAVE_ACPI +endif + +AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) diff --git a/hw/xfree86/common/Makefile.in b/hw/xfree86/common/Makefile.in new file mode 100644 index 0000000..0e01dcf --- /dev/null +++ b/hw/xfree86/common/Makefile.in @@ -0,0 +1,878 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +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@ +@LNXACPI_TRUE@am__append_1 = -DHAVE_ACPI +subdir = hw/xfree86/common +DIST_COMMON = $(am__sdk_HEADERS_DIST) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/xf86Build.h.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_define_dir.m4 \ + $(top_srcdir)/m4/ax_tls.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/include/do-not-use-config.h \ + $(top_builddir)/include/xorg-server.h \ + $(top_builddir)/include/dix-config.h \ + $(top_builddir)/include/xorg-config.h \ + $(top_builddir)/include/xkb-config.h \ + $(top_builddir)/include/xwin-config.h \ + $(top_builddir)/include/kdrive-config.h \ + $(top_builddir)/include/version-config.h +CONFIG_CLEAN_FILES = xf86Build.h +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libcommon_la_DEPENDENCIES = $(top_builddir)/config/libconfig.la +am__libcommon_la_SOURCES_DIST = xf86Configure.c xf86ShowOpts.c \ + xf86Bus.c xf86Config.c xf86Cursor.c xf86DGA.c xf86DPMS.c \ + xf86Events.c xf86Globals.c xf86AutoConfig.c xf86Option.c \ + xf86Init.c xf86VGAarbiter.c xf86VidMode.c xf86fbman.c \ + xf86cmap.c xf86Helper.c xf86PM.c xf86Xinput.c xisb.c \ + xf86Mode.c xorgHelper.c xf86xv.c xf86xvmc.c xf86pciBus.c \ + xf86fbBus.c xf86noBus.c xf86sbusBus.c xf86RandR.c +@DGA_TRUE@am__objects_1 = xf86DGA.lo +@XV_TRUE@am__objects_2 = xf86xv.lo xf86xvmc.lo +@XORG_BUS_SPARC_TRUE@am__objects_3 = xf86sbusBus.lo +am__objects_4 = xf86pciBus.lo xf86fbBus.lo xf86noBus.lo \ + $(am__objects_3) +am__objects_5 = xf86RandR.lo +am_libcommon_la_OBJECTS = xf86Configure.lo xf86ShowOpts.lo xf86Bus.lo \ + xf86Config.lo xf86Cursor.lo $(am__objects_1) xf86DPMS.lo \ + xf86Events.lo xf86Globals.lo xf86AutoConfig.lo xf86Option.lo \ + xf86Init.lo xf86VGAarbiter.lo xf86VidMode.lo xf86fbman.lo \ + xf86cmap.lo xf86Helper.lo xf86PM.lo xf86Xinput.lo xisb.lo \ + xf86Mode.lo xorgHelper.lo $(am__objects_2) $(am__objects_4) \ + $(am__objects_5) +nodist_libcommon_la_OBJECTS = xf86DefModeSet.lo +libcommon_la_OBJECTS = $(am_libcommon_la_OBJECTS) \ + $(nodist_libcommon_la_OBJECTS) +AM_V_lt = $(am__v_lt_$(V)) +am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +am__v_lt_0 = --silent +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_$(V)) +am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +am__v_CC_0 = @echo " CC " $@; +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_$(V)) +am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(libcommon_la_SOURCES) $(nodist_libcommon_la_SOURCES) +DIST_SOURCES = $(am__libcommon_la_SOURCES_DIST) +am__sdk_HEADERS_DIST = compiler.h fourcc.h xf86.h xf86Module.h \ + xf86Opt.h xf86PciInfo.h xf86Priv.h xf86Privstr.h xf86cmap.h \ + xf86fbman.h xf86str.h xf86Xinput.h xisb.h xf86xv.h xf86xvmc.h \ + xf86xvpriv.h vidmodeproc.h xorgVersion.h xf86sbusBus.h \ + xf86VGAarbiter.h +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 = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(sdkdir)" +HEADERS = $(sdk_HEADERS) +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@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APPLE_APPLICATIONS_DIR = @APPLE_APPLICATIONS_DIR@ +APPLE_APPLICATION_NAME = @APPLE_APPLICATION_NAME@ +APP_MAN_DIR = @APP_MAN_DIR@ +APP_MAN_SUFFIX = @APP_MAN_SUFFIX@ +AR = @AR@ +ARM_BACKTRACE_CFLAGS = @ARM_BACKTRACE_CFLAGS@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASE_FONT_PATH = @BASE_FONT_PATH@ +BUILD_DATE = @BUILD_DATE@ +BUILD_TIME = @BUILD_TIME@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHANGELOG_CMD = @CHANGELOG_CMD@ +COMPILEDDEFAULTFONTPATH = @COMPILEDDEFAULTFONTPATH@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CWARNFLAGS = @CWARNFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DARWIN_LIBS = @DARWIN_LIBS@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_LIBS = @DBUS_LIBS@ +DEFAULT_LIBRARY_PATH = @DEFAULT_LIBRARY_PATH@ +DEFAULT_LOGDIR = @DEFAULT_LOGDIR@ +DEFAULT_LOGPREFIX = @DEFAULT_LOGPREFIX@ +DEFAULT_MODULE_PATH = @DEFAULT_MODULE_PATH@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DGA_CFLAGS = @DGA_CFLAGS@ +DGA_LIBS = @DGA_LIBS@ +DIX_CFLAGS = @DIX_CFLAGS@ +DIX_LIB = @DIX_LIB@ +DLLTOOL = @DLLTOOL@ +DLOPEN_LIBS = @DLOPEN_LIBS@ +DMXEXAMPLES_DEP_CFLAGS = @DMXEXAMPLES_DEP_CFLAGS@ +DMXEXAMPLES_DEP_LIBS = @DMXEXAMPLES_DEP_LIBS@ +DMXMODULES_CFLAGS = @DMXMODULES_CFLAGS@ +DMXMODULES_LIBS = @DMXMODULES_LIBS@ +DMXXIEXAMPLES_DEP_CFLAGS = @DMXXIEXAMPLES_DEP_CFLAGS@ +DMXXIEXAMPLES_DEP_LIBS = @DMXXIEXAMPLES_DEP_LIBS@ +DMXXMUEXAMPLES_DEP_CFLAGS = @DMXXMUEXAMPLES_DEP_CFLAGS@ +DMXXMUEXAMPLES_DEP_LIBS = @DMXXMUEXAMPLES_DEP_LIBS@ +DOXYGEN = @DOXYGEN@ +DRI2PROTO_CFLAGS = @DRI2PROTO_CFLAGS@ +DRI2PROTO_LIBS = @DRI2PROTO_LIBS@ +DRIPROTO_CFLAGS = @DRIPROTO_CFLAGS@ +DRIPROTO_LIBS = @DRIPROTO_LIBS@ +DRIVER_MAN_DIR = @DRIVER_MAN_DIR@ +DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@ +DRI_CFLAGS = @DRI_CFLAGS@ +DRI_DRIVER_PATH = @DRI_DRIVER_PATH@ +DRI_LIBS = @DRI_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DTRACE = @DTRACE@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILE_MAN_DIR = @FILE_MAN_DIR@ +FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@ +FONT100DPIDIR = @FONT100DPIDIR@ +FONT75DPIDIR = @FONT75DPIDIR@ +FONTMISCDIR = @FONTMISCDIR@ +FONTOTFDIR = @FONTOTFDIR@ +FONTROOTDIR = @FONTROOTDIR@ +FONTTTFDIR = @FONTTTFDIR@ +FONTTYPE1DIR = @FONTTYPE1DIR@ +FOP = @FOP@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_LIBS = @GLIB_LIBS@ +GLX_ARCH_DEFINES = @GLX_ARCH_DEFINES@ +GLX_DEFINES = @GLX_DEFINES@ +GLX_TLS = @GLX_TLS@ +GL_CFLAGS = @GL_CFLAGS@ +GL_LIBS = @GL_LIBS@ +GREP = @GREP@ +HAL_CFLAGS = @HAL_CFLAGS@ +HAL_LIBS = @HAL_LIBS@ +INSTALL = @INSTALL@ +INSTALL_CMD = @INSTALL_CMD@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KDRIVE_CFLAGS = @KDRIVE_CFLAGS@ +KDRIVE_INCS = @KDRIVE_INCS@ +KDRIVE_LIBS = @KDRIVE_LIBS@ +KDRIVE_LOCAL_LIBS = @KDRIVE_LOCAL_LIBS@ +KDRIVE_PURE_INCS = @KDRIVE_PURE_INCS@ +KDRIVE_PURE_LIBS = @KDRIVE_PURE_LIBS@ +LAUNCHD_ID_PREFIX = @LAUNCHD_ID_PREFIX@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LD_EXPORT_SYMBOLS_FLAG = @LD_EXPORT_SYMBOLS_FLAG@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBDRM_CFLAGS = @LIBDRM_CFLAGS@ +LIBDRM_LIBS = @LIBDRM_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSHA1_CFLAGS = @LIBSHA1_CFLAGS@ +LIBSHA1_LIBS = @LIBSHA1_LIBS@ +LIBTOOL = @LIBTOOL@ +LIB_MAN_DIR = @LIB_MAN_DIR@ +LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAIN_LIB = @MAIN_LIB@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAN_SUBSTS = @MAN_SUBSTS@ +MISC_MAN_DIR = @MISC_MAN_DIR@ +MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCCLD = @OBJCCLD@ +OBJCDEPMODE = @OBJCDEPMODE@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCLINK = @OBJCLINK@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OS_LIB = @OS_LIB@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PCIACCESS_CFLAGS = @PCIACCESS_CFLAGS@ +PCIACCESS_LIBS = @PCIACCESS_LIBS@ +PCI_TXT_IDS_PATH = @PCI_TXT_IDS_PATH@ +PERL = @PERL@ +PIXMAN_CFLAGS = @PIXMAN_CFLAGS@ +PIXMAN_LIBS = @PIXMAN_LIBS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROJECTROOT = @PROJECTROOT@ +RANLIB = @RANLIB@ +RAWCPP = @RAWCPP@ +RAWCPPFLAGS = @RAWCPPFLAGS@ +RELEASE_DATE = @RELEASE_DATE@ +SDK_REQUIRED_MODULES = @SDK_REQUIRED_MODULES@ +SED = @SED@ +SELINUX_CFLAGS = @SELINUX_CFLAGS@ +SELINUX_LIBS = @SELINUX_LIBS@ +SERVER_MISC_CONFIG_PATH = @SERVER_MISC_CONFIG_PATH@ +SET_MAKE = @SET_MAKE@ +SHA1_CFLAGS = @SHA1_CFLAGS@ +SHA1_LIBS = @SHA1_LIBS@ +SHELL = @SHELL@ +SOLARIS_ASM_CFLAGS = @SOLARIS_ASM_CFLAGS@ +SOLARIS_INOUT_ARCH = @SOLARIS_INOUT_ARCH@ +STRIP = @STRIP@ +STYLESHEET_SRCDIR = @STYLESHEET_SRCDIR@ +SYSCONFDIR = @SYSCONFDIR@ +TSLIB_CFLAGS = @TSLIB_CFLAGS@ +TSLIB_LIBS = @TSLIB_LIBS@ +UDEV_CFLAGS = @UDEV_CFLAGS@ +UDEV_LIBS = @UDEV_LIBS@ +UTILS_SYS_LIBS = @UTILS_SYS_LIBS@ +VENDOR_NAME_SHORT = @VENDOR_NAME_SHORT@ +VERSION = @VERSION@ +WINDOWSWM_CFLAGS = @WINDOWSWM_CFLAGS@ +WINDOWSWM_LIBS = @WINDOWSWM_LIBS@ +WINDRES = @WINDRES@ +X11EXAMPLES_DEP_CFLAGS = @X11EXAMPLES_DEP_CFLAGS@ +X11EXAMPLES_DEP_LIBS = @X11EXAMPLES_DEP_LIBS@ +XDMCP_CFLAGS = @XDMCP_CFLAGS@ +XDMCP_LIBS = @XDMCP_LIBS@ +XDMXCONFIG_DEP_CFLAGS = @XDMXCONFIG_DEP_CFLAGS@ +XDMXCONFIG_DEP_LIBS = @XDMXCONFIG_DEP_LIBS@ +XDMX_CFLAGS = @XDMX_CFLAGS@ +XDMX_LIBS = @XDMX_LIBS@ +XDMX_SYS_LIBS = @XDMX_SYS_LIBS@ +XEPHYR_CFLAGS = @XEPHYR_CFLAGS@ +XEPHYR_INCS = @XEPHYR_INCS@ +XEPHYR_LIBS = @XEPHYR_LIBS@ +XF86CONFIGDIR = @XF86CONFIGDIR@ +XF86CONFIGFILE = @XF86CONFIGFILE@ +XF86VIDMODE_CFLAGS = @XF86VIDMODE_CFLAGS@ +XF86VIDMODE_LIBS = @XF86VIDMODE_LIBS@ +XKB_BASE_DIRECTORY = @XKB_BASE_DIRECTORY@ +XKB_BIN_DIRECTORY = @XKB_BIN_DIRECTORY@ +XKB_COMPILED_DIR = @XKB_COMPILED_DIR@ +XKM_OUTPUT_DIR = @XKM_OUTPUT_DIR@ +XLIB_CFLAGS = @XLIB_CFLAGS@ +XLIB_LIBS = @XLIB_LIBS@ +XMLTO = @XMLTO@ +XNESTMODULES_CFLAGS = @XNESTMODULES_CFLAGS@ +XNESTMODULES_LIBS = @XNESTMODULES_LIBS@ +XNEST_LIBS = @XNEST_LIBS@ +XNEST_SYS_LIBS = @XNEST_SYS_LIBS@ +XORG_CFLAGS = @XORG_CFLAGS@ $(am__append_1) +XORG_INCS = @XORG_INCS@ +XORG_LIBS = @XORG_LIBS@ +XORG_MAN_PAGE = @XORG_MAN_PAGE@ +XORG_MODULES_CFLAGS = @XORG_MODULES_CFLAGS@ +XORG_MODULES_LIBS = @XORG_MODULES_LIBS@ +XORG_OS = @XORG_OS@ +XORG_OS_SUBDIR = @XORG_OS_SUBDIR@ +XORG_SGML_PATH = @XORG_SGML_PATH@ +XORG_SYS_LIBS = @XORG_SYS_LIBS@ +XPBPROXY_CFLAGS = @XPBPROXY_CFLAGS@ +XPBPROXY_LIBS = @XPBPROXY_LIBS@ +XQUARTZ_SPARKLE = @XQUARTZ_SPARKLE@ +XRESEXAMPLES_DEP_CFLAGS = @XRESEXAMPLES_DEP_CFLAGS@ +XRESEXAMPLES_DEP_LIBS = @XRESEXAMPLES_DEP_LIBS@ +XSERVERCFLAGS_CFLAGS = @XSERVERCFLAGS_CFLAGS@ +XSERVERCFLAGS_LIBS = @XSERVERCFLAGS_LIBS@ +XSERVERLIBS_CFLAGS = @XSERVERLIBS_CFLAGS@ +XSERVERLIBS_LIBS = @XSERVERLIBS_LIBS@ +XSERVER_LIBS = @XSERVER_LIBS@ +XSERVER_SYS_LIBS = @XSERVER_SYS_LIBS@ +XSL_STYLESHEET = @XSL_STYLESHEET@ +XTSTEXAMPLES_DEP_CFLAGS = @XTSTEXAMPLES_DEP_CFLAGS@ +XTSTEXAMPLES_DEP_LIBS = @XTSTEXAMPLES_DEP_LIBS@ +XVFB_LIBS = @XVFB_LIBS@ +XVFB_SYS_LIBS = @XVFB_SYS_LIBS@ +XWINMODULES_CFLAGS = @XWINMODULES_CFLAGS@ +XWINMODULES_LIBS = @XWINMODULES_LIBS@ +XWIN_LIBS = @XWIN_LIBS@ +XWIN_SERVER_NAME = @XWIN_SERVER_NAME@ +XWIN_SYS_LIBS = @XWIN_SYS_LIBS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +__XCONFIGDIR__ = @__XCONFIGDIR__@ +__XCONFIGFILE__ = @__XCONFIGFILE__@ +abi_ansic = @abi_ansic@ +abi_extension = @abi_extension@ +abi_videodrv = @abi_videodrv@ +abi_xinput = @abi_xinput@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +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@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +driverdir = @driverdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +extdir = @extdir@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +logdir = @logdir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sdkdir = @sdkdir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +symbol_visibility = @symbol_visibility@ +sysconfdir = @sysconfdir@ +sysconfigdir = @sysconfigdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libcommon.la +@XORG_BUS_SPARC_TRUE@SBUS_SOURCES = xf86sbusBus.c +@XV_TRUE@XVSOURCES = xf86xv.c xf86xvmc.c +@XV_TRUE@XVSDKINCS = xf86xv.h xf86xvmc.h xf86xvpriv.h +@XF86VIDMODE_TRUE@XF86VMODE_SDK = vidmodeproc.h +@DGA_TRUE@DGASOURCES = xf86DGA.c +RANDRSOURCES = xf86RandR.c +BUSSOURCES = xf86pciBus.c xf86fbBus.c xf86noBus.c $(SBUS_SOURCES) +MODEDEFSOURCES = $(srcdir)/vesamodes $(srcdir)/extramodes +BUILT_SOURCES = xf86DefModeSet.c +AM_LDFLAGS = -r +libcommon_la_SOURCES = xf86Configure.c xf86ShowOpts.c xf86Bus.c xf86Config.c \ + xf86Cursor.c $(DGASOURCES) xf86DPMS.c \ + xf86Events.c xf86Globals.c xf86AutoConfig.c \ + xf86Option.c xf86Init.c xf86VGAarbiter.c \ + xf86VidMode.c xf86fbman.c xf86cmap.c \ + xf86Helper.c xf86PM.c xf86Xinput.c xisb.c \ + xf86Mode.c xorgHelper.c \ + $(XVSOURCES) $(BUSSOURCES) $(RANDRSOURCES) + +nodist_libcommon_la_SOURCES = xf86DefModeSet.c xf86Build.h +libcommon_la_LIBADD = $(top_builddir)/config/libconfig.la +INCLUDES = $(XORG_INCS) -I$(srcdir)/../ddc -I$(srcdir)/../i2c \ + -I$(srcdir)/../loader -I$(srcdir)/../parser \ + -I$(srcdir)/../vbe -I$(srcdir)/../int10 \ + -I$(srcdir)/../vgahw -I$(srcdir)/../dixmods/extmod \ + -I$(srcdir)/../modes -I$(srcdir)/../ramdac + +sdk_HEADERS = compiler.h fourcc.h xf86.h xf86Module.h xf86Opt.h \ + xf86PciInfo.h xf86Priv.h xf86Privstr.h \ + xf86cmap.h xf86fbman.h xf86str.h xf86Xinput.h xisb.h \ + $(XVSDKINCS) $(XF86VMODE_SDK) xorgVersion.h \ + xf86sbusBus.h xf86VGAarbiter.h + +DISTCLEANFILES = xf86Build.h +CLEANFILES = $(BUILT_SOURCES) +EXTRA_DIST = \ + compiler.h \ + fourcc.h \ + vidmodeproc.h \ + xf86.h \ + xf86Bus.h \ + xf86Config.h \ + xf86InPriv.h \ + xf86Module.h \ + xf86Opt.h \ + xf86PciInfo.h \ + xf86Priv.h \ + xf86Privstr.h \ + xf86Xinput.h \ + xf86cmap.h \ + xf86fbman.h \ + xf86pciBus.h \ + xf86str.h \ + xf86xv.h \ + xf86xvmc.h \ + xf86xvpriv.h \ + xisb.h \ + xorgVersion.h \ + $(MODEDEFSOURCES) \ + modeline2c.awk \ + xf86VGAarbiter.h \ + xf86VGAarbiterPriv.h \ + $(DISTKBDSOURCES) + +AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) 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 ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign hw/xfree86/common/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign hw/xfree86/common/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 +$(am__aclocal_m4_deps): +xf86Build.h: $(top_builddir)/config.status $(srcdir)/xf86Build.h.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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 +libcommon.la: $(libcommon_la_OBJECTS) $(libcommon_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libcommon_la_OBJECTS) $(libcommon_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86AutoConfig.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86Bus.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86Config.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86Configure.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86Cursor.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86DGA.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86DPMS.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86DefModeSet.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86Events.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86Globals.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86Helper.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86Init.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86Mode.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86Option.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86PM.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86RandR.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86ShowOpts.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86VGAarbiter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86VidMode.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86Xinput.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86cmap.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86fbBus.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86fbman.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86noBus.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86pciBus.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86sbusBus.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86xv.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86xvmc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xisb.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xorgHelper.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@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@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@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@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@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 +install-sdkHEADERS: $(sdk_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(sdkdir)" || $(MKDIR_P) "$(DESTDIR)$(sdkdir)" + @list='$(sdk_HEADERS)'; test -n "$(sdkdir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(sdkdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(sdkdir)" || exit $$?; \ + done + +uninstall-sdkHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(sdk_HEADERS)'; test -n "$(sdkdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(sdkdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(sdkdir)" && rm -f $$files + +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; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + 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; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + 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; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__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)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$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: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(sdkdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) 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: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-sdkHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +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-sdkHEADERS + +.MAKE: all check install install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES 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-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-sdkHEADERS 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-sdkHEADERS + + +xf86DefModeSet.c: $(srcdir)/modeline2c.awk $(MODEDEFSOURCES) + $(AM_V_GEN)cat $(MODEDEFSOURCES) | LC_ALL=C $(AWK) -f $(srcdir)/modeline2c.awk > $@ + $(AM_V_GEN)echo >> $@ + +# 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/hw/xfree86/common/compiler.h b/hw/xfree86/common/compiler.h new file mode 100644 index 0000000..9e00d75 --- /dev/null +++ b/hw/xfree86/common/compiler.h @@ -0,0 +1,1773 @@ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Thomas Roell not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Roell makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS ROELL 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. + * + */ +/* + * Copyright (c) 1994-2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +#ifndef _COMPILER_H + +# define _COMPILER_H + +#if defined(__SUNPRO_C) +# define DO_PROTOTYPES +#endif + +/* Map Sun compiler platform defines to gcc-style used in the code */ +#if defined(__amd64) && !defined(__amd64__) +# define __amd64__ +#endif +#if defined(__i386) && !defined(__i386__) +# define __i386__ +#endif +#if defined(__sparc) && !defined(__sparc__) +# define __sparc__ +#endif +#if defined(__sparcv9) && !defined(__sparc64__) +# define __sparc64__ +#endif + +#ifndef _X_EXPORT +# include <X11/Xfuncproto.h> +#endif + +# include <pixman.h> /* for uint*_t types */ + +/* Allow drivers to use the GCC-supported __inline__ and/or __inline. */ +# ifndef __inline__ +# if defined(__GNUC__) + /* gcc has __inline__ */ +# elif defined(__HIGHC__) +# define __inline__ _Inline +# else +# define __inline__ /**/ +# endif +# endif /* __inline__ */ +# ifndef __inline +# if defined(__GNUC__) + /* gcc has __inline */ +# elif defined(__HIGHC__) +# define __inline _Inline +# else +# define __inline /**/ +# endif +# endif /* __inline */ + +/* Support gcc's __FUNCTION__ for people using other compilers */ +#if !defined(__GNUC__) && !defined(__FUNCTION__) +# define __FUNCTION__ __func__ /* C99 */ +#endif + +# if defined(NO_INLINE) || defined(DO_PROTOTYPES) + +# if !defined(__arm__) +# if !defined(__sparc__) && !defined(__sparc) && !defined(__arm32__) && !defined(__nds32__) \ + && !(defined(__alpha__) && defined(linux)) \ + && !(defined(__ia64__) && defined(linux)) \ + +extern _X_EXPORT void outb(unsigned short, unsigned char); +extern _X_EXPORT void outw(unsigned short, unsigned short); +extern _X_EXPORT void outl(unsigned short, unsigned int); +extern _X_EXPORT unsigned int inb(unsigned short); +extern _X_EXPORT unsigned int inw(unsigned short); +extern _X_EXPORT unsigned int inl(unsigned short); + +# else /* __sparc__, __arm32__, __alpha__, __nds32__ */ + +extern _X_EXPORT void outb(unsigned long, unsigned char); +extern _X_EXPORT void outw(unsigned long, unsigned short); +extern _X_EXPORT void outl(unsigned long, unsigned int); +extern _X_EXPORT unsigned int inb(unsigned long); +extern _X_EXPORT unsigned int inw(unsigned long); +extern _X_EXPORT unsigned int inl(unsigned long); + +# endif /* __sparc__, __arm32__, __alpha__, __nds32__ */ +# endif /* __arm__ */ + +# if defined(__powerpc__) && !defined(__OpenBSD__) +extern unsigned long ldq_u(unsigned long *); +extern unsigned long ldl_u(unsigned int *); +extern unsigned long ldw_u(unsigned short *); +extern void stq_u(unsigned long, unsigned long *); +extern void stl_u(unsigned long, unsigned int *); +extern void stw_u(unsigned long, unsigned short *); +extern void mem_barrier(void); +extern void write_mem_barrier(void); +extern void stl_brx(unsigned long, volatile unsigned char *, int); +extern void stw_brx(unsigned short, volatile unsigned char *, int); +extern unsigned long ldl_brx(volatile unsigned char *, int); +extern unsigned short ldw_brx(volatile unsigned char *, int); +# endif /* __powerpc__ && !__OpenBSD */ + +# endif /* NO_INLINE || DO_PROTOTYPES */ + +# ifndef NO_INLINE +# ifdef __GNUC__ +# ifdef __i386__ + +# ifdef __SSE__ +# define write_mem_barrier() __asm__ __volatile__ ("sfence" : : : "memory") +# else +# define write_mem_barrier() __asm__ __volatile__ ("lock; addl $0,0(%%esp)" : : : "memory") +# endif + +# ifdef __SSE2__ +# define mem_barrier() __asm__ __volatile__ ("mfence" : : : "memory") +# else +# define mem_barrier() __asm__ __volatile__ ("lock; addl $0,0(%%esp)" : : : "memory") +# endif + +# elif defined __alpha__ + +# define mem_barrier() __asm__ __volatile__ ("mb" : : : "memory") +# define write_mem_barrier() __asm__ __volatile__ ("wmb" : : : "memory") + +# elif defined __amd64__ + +# define mem_barrier() __asm__ __volatile__ ("mfence" : : : "memory") +# define write_mem_barrier() __asm__ __volatile__ ("sfence" : : : "memory") + +# elif defined __ia64__ + +# ifndef __INTEL_COMPILER +# define mem_barrier() __asm__ __volatile__ ("mf" : : : "memory") +# define write_mem_barrier() __asm__ __volatile__ ("mf" : : : "memory") +# else +# include "ia64intrin.h" +# define mem_barrier() __mf() +# define write_mem_barrier() __mf() +# endif + +# elif defined __mips__ + /* Note: sync instruction requires MIPS II instruction set */ +# define mem_barrier() \ + __asm__ __volatile__( \ + ".set push\n\t" \ + ".set noreorder\n\t" \ + ".set mips2\n\t" \ + "sync\n\t" \ + ".set pop" \ + : /* no output */ \ + : /* no input */ \ + : "memory") +# define write_mem_barrier() mem_barrier() + +# elif defined __powerpc__ + +# if defined(linux) && defined(__powerpc64__) +# include <linux/version.h> +# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) +# include <asm/memory.h> +# endif +# endif /* defined(linux) && defined(__powerpc64__) */ + +# ifndef eieio /* We deal with arch-specific eieio() routines above... */ +# define eieio() __asm__ __volatile__ ("eieio" ::: "memory") +# endif /* eieio */ +# define mem_barrier() eieio() +# define write_mem_barrier() eieio() + +# elif defined __sparc__ + +# define barrier() __asm__ __volatile__ (".word 0x8143e00a" : : : "memory") +# define mem_barrier() /* XXX: nop for now */ +# define write_mem_barrier() /* XXX: nop for now */ +# endif +# endif /* __GNUC__ */ +# endif /* NO_INLINE */ + +# ifndef mem_barrier +# define mem_barrier() /* NOP */ +# endif + +# ifndef write_mem_barrier +# define write_mem_barrier() /* NOP */ +# endif + + +# ifndef NO_INLINE +# ifdef __GNUC__ + +/* Define some packed structures to use with unaligned accesses */ + +struct __una_u64 { uint64_t x __attribute__((packed)); }; +struct __una_u32 { uint32_t x __attribute__((packed)); }; +struct __una_u16 { uint16_t x __attribute__((packed)); }; + +/* Elemental unaligned loads */ + +static __inline__ uint64_t ldq_u(uint64_t *p) +{ + const struct __una_u64 *ptr = (const struct __una_u64 *) p; + return ptr->x; +} + +static __inline__ uint32_t ldl_u(uint32_t *p) +{ + const struct __una_u32 *ptr = (const struct __una_u32 *) p; + return ptr->x; +} + +static __inline__ uint16_t ldw_u(uint16_t *p) +{ + const struct __una_u16 *ptr = (const struct __una_u16 *) p; + return ptr->x; +} + +/* Elemental unaligned stores */ + +static __inline__ void stq_u(uint64_t val, uint64_t *p) +{ + struct __una_u64 *ptr = (struct __una_u64 *) p; + ptr->x = val; +} + +static __inline__ void stl_u(uint32_t val, uint32_t *p) +{ + struct __una_u32 *ptr = (struct __una_u32 *) p; + ptr->x = val; +} + +static __inline__ void stw_u(uint16_t val, uint16_t *p) +{ + struct __una_u16 *ptr = (struct __una_u16 *) p; + ptr->x = val; +} +# else /* !__GNUC__ */ + +#include <string.h> /* needed for memmove */ + +static __inline__ uint64_t ldq_u(uint64_t *p) +{ + uint64_t ret; + memmove(&ret, p, sizeof(*p)); + return ret; +} + +static __inline__ uint32_t ldl_u(uint32_t *p) +{ + uint32_t ret; + memmove(&ret, p, sizeof(*p)); + return ret; +} + +static __inline__ uint16_t ldw_u(uint16_t *p) +{ + uint16_t ret; + memmove(&ret, p, sizeof(*p)); + return ret; +} + +static __inline__ void stq_u(uint64_t val, uint64_t *p) +{ + uint64_t tmp = val; + memmove(p, &tmp, sizeof(*p)); +} + +static __inline__ void stl_u(uint32_t val, uint32_t *p) +{ + uint32_t tmp = val; + memmove(p, &tmp, sizeof(*p)); +} + +static __inline__ void stw_u(uint16_t val, uint16_t *p) +{ + uint16_t tmp = val; + memmove(p, &tmp, sizeof(*p)); +} + +# endif /* __GNUC__ */ +# endif /* NO_INLINE */ + +# ifndef NO_INLINE +# ifdef __GNUC__ +# if (defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)) && (defined(__alpha__)) + +# ifdef linux +/* for Linux on Alpha, we use the LIBC _inx/_outx routines */ +/* note that the appropriate setup via "ioperm" needs to be done */ +/* *before* any inx/outx is done. */ + +extern _X_EXPORT void _outb(unsigned char val, unsigned long port); +extern _X_EXPORT void _outw(unsigned short val, unsigned long port); +extern _X_EXPORT void _outl(unsigned int val, unsigned long port); +extern _X_EXPORT unsigned int _inb(unsigned long port); +extern _X_EXPORT unsigned int _inw(unsigned long port); +extern _X_EXPORT unsigned int _inl(unsigned long port); + +static __inline__ void +outb(unsigned long port, unsigned char val) +{ + _outb(val, port); +} + +static __inline__ void +outw(unsigned long port, unsigned short val) +{ + _outw(val, port); +} + +static __inline__ void +outl(unsigned long port, unsigned int val) +{ + _outl(val, port); +} + +static __inline__ unsigned int +inb(unsigned long port) +{ + return _inb(port); +} + +static __inline__ unsigned int +inw(unsigned long port) +{ + return _inw(port); +} + +static __inline__ unsigned int +inl(unsigned long port) +{ + return _inl(port); +} + +# endif /* linux */ + +# if (defined(__FreeBSD__) || defined(__OpenBSD__)) \ + && !defined(DO_PROTOTYPES) + +/* for FreeBSD and OpenBSD on Alpha, we use the libio (resp. libalpha) */ +/* inx/outx routines */ +/* note that the appropriate setup via "ioperm" needs to be done */ +/* *before* any inx/outx is done. */ + +extern _X_EXPORT void outb(unsigned int port, unsigned char val); +extern _X_EXPORT void outw(unsigned int port, unsigned short val); +extern _X_EXPORT void outl(unsigned int port, unsigned int val); +extern _X_EXPORT unsigned char inb(unsigned int port); +extern _X_EXPORT unsigned short inw(unsigned int port); +extern _X_EXPORT unsigned int inl(unsigned int port); + +# endif /* (__FreeBSD__ || __OpenBSD__ ) && !DO_PROTOTYPES */ + + +#if defined(__NetBSD__) +#include <machine/pio.h> +#endif /* __NetBSD__ */ + +# elif defined(linux) && defined(__ia64__) + +# include <inttypes.h> + +# include <sys/io.h> + +# undef outb +# undef outw +# undef outl +# undef inb +# undef inw +# undef inl +extern _X_EXPORT void outb(unsigned long port, unsigned char val); +extern _X_EXPORT void outw(unsigned long port, unsigned short val); +extern _X_EXPORT void outl(unsigned long port, unsigned int val); +extern _X_EXPORT unsigned int inb(unsigned long port); +extern _X_EXPORT unsigned int inw(unsigned long port); +extern _X_EXPORT unsigned int inl(unsigned long port); + +# elif (defined(linux) || defined(__FreeBSD__)) && defined(__amd64__) + +# include <inttypes.h> + +static __inline__ void +outb(unsigned short port, unsigned char val) +{ + __asm__ __volatile__("outb %0,%1" : :"a" (val), "d" (port)); +} + + +static __inline__ void +outw(unsigned short port, unsigned short val) +{ + __asm__ __volatile__("outw %0,%1" : :"a" (val), "d" (port)); +} + +static __inline__ void +outl(unsigned short port, unsigned int val) +{ + __asm__ __volatile__("outl %0,%1" : :"a" (val), "d" (port)); +} + +static __inline__ unsigned int +inb(unsigned short port) +{ + unsigned char ret; + __asm__ __volatile__("inb %1,%0" : + "=a" (ret) : + "d" (port)); + return ret; +} + +static __inline__ unsigned int +inw(unsigned short port) +{ + unsigned short ret; + __asm__ __volatile__("inw %1,%0" : + "=a" (ret) : + "d" (port)); + return ret; +} + +static __inline__ unsigned int +inl(unsigned short port) +{ + unsigned int ret; + __asm__ __volatile__("inl %1,%0" : + "=a" (ret) : + "d" (port)); + return ret; +} + +# elif (defined(linux) || defined(sun) || defined(__OpenBSD__) || defined(__FreeBSD__)) && defined(__sparc__) + +# ifndef ASI_PL +# define ASI_PL 0x88 +# endif + +static __inline__ void +outb(unsigned long port, unsigned char val) +{ + __asm__ __volatile__("stba %0, [%1] %2" + : /* No outputs */ + : "r" (val), "r" (port), "i" (ASI_PL)); + barrier(); +} + +static __inline__ void +outw(unsigned long port, unsigned short val) +{ + __asm__ __volatile__("stha %0, [%1] %2" + : /* No outputs */ + : "r" (val), "r" (port), "i" (ASI_PL)); + barrier(); +} + +static __inline__ void +outl(unsigned long port, unsigned int val) +{ + __asm__ __volatile__("sta %0, [%1] %2" + : /* No outputs */ + : "r" (val), "r" (port), "i" (ASI_PL)); + barrier(); +} + +static __inline__ unsigned int +inb(unsigned long port) +{ + unsigned int ret; + __asm__ __volatile__("lduba [%1] %2, %0" + : "=r" (ret) + : "r" (port), "i" (ASI_PL)); + return ret; +} + +static __inline__ unsigned int +inw(unsigned long port) +{ + unsigned int ret; + __asm__ __volatile__("lduha [%1] %2, %0" + : "=r" (ret) + : "r" (port), "i" (ASI_PL)); + return ret; +} + +static __inline__ unsigned int +inl(unsigned long port) +{ + unsigned int ret; + __asm__ __volatile__("lda [%1] %2, %0" + : "=r" (ret) + : "r" (port), "i" (ASI_PL)); + return ret; +} + +static __inline__ unsigned char +xf86ReadMmio8(__volatile__ void *base, const unsigned long offset) +{ + unsigned long addr = ((unsigned long)base) + offset; + unsigned char ret; + + __asm__ __volatile__("lduba [%1] %2, %0" + : "=r" (ret) + : "r" (addr), "i" (ASI_PL)); + return ret; +} + +static __inline__ unsigned short +xf86ReadMmio16Be(__volatile__ void *base, const unsigned long offset) +{ + unsigned long addr = ((unsigned long)base) + offset; + unsigned short ret; + + __asm__ __volatile__("lduh [%1], %0" + : "=r" (ret) + : "r" (addr)); + return ret; +} + +static __inline__ unsigned short +xf86ReadMmio16Le(__volatile__ void *base, const unsigned long offset) +{ + unsigned long addr = ((unsigned long)base) + offset; + unsigned short ret; + + __asm__ __volatile__("lduha [%1] %2, %0" + : "=r" (ret) + : "r" (addr), "i" (ASI_PL)); + return ret; +} + +static __inline__ unsigned int +xf86ReadMmio32Be(__volatile__ void *base, const unsigned long offset) +{ + unsigned long addr = ((unsigned long)base) + offset; + unsigned int ret; + + __asm__ __volatile__("ld [%1], %0" + : "=r" (ret) + : "r" (addr)); + return ret; +} + +static __inline__ unsigned int +xf86ReadMmio32Le(__volatile__ void *base, const unsigned long offset) +{ + unsigned long addr = ((unsigned long)base) + offset; + unsigned int ret; + + __asm__ __volatile__("lda [%1] %2, %0" + : "=r" (ret) + : "r" (addr), "i" (ASI_PL)); + return ret; +} + +static __inline__ void +xf86WriteMmio8(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + unsigned long addr = ((unsigned long)base) + offset; + + __asm__ __volatile__("stba %0, [%1] %2" + : /* No outputs */ + : "r" (val), "r" (addr), "i" (ASI_PL)); + barrier(); +} + +static __inline__ void +xf86WriteMmio16Be(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + unsigned long addr = ((unsigned long)base) + offset; + + __asm__ __volatile__("sth %0, [%1]" + : /* No outputs */ + : "r" (val), "r" (addr)); + barrier(); +} + +static __inline__ void +xf86WriteMmio16Le(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + unsigned long addr = ((unsigned long)base) + offset; + + __asm__ __volatile__("stha %0, [%1] %2" + : /* No outputs */ + : "r" (val), "r" (addr), "i" (ASI_PL)); + barrier(); +} + +static __inline__ void +xf86WriteMmio32Be(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + unsigned long addr = ((unsigned long)base) + offset; + + __asm__ __volatile__("st %0, [%1]" + : /* No outputs */ + : "r" (val), "r" (addr)); + barrier(); +} + +static __inline__ void +xf86WriteMmio32Le(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + unsigned long addr = ((unsigned long)base) + offset; + + __asm__ __volatile__("sta %0, [%1] %2" + : /* No outputs */ + : "r" (val), "r" (addr), "i" (ASI_PL)); + barrier(); +} + +static __inline__ void +xf86WriteMmio8NB(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + unsigned long addr = ((unsigned long)base) + offset; + + __asm__ __volatile__("stba %0, [%1] %2" + : /* No outputs */ + : "r" (val), "r" (addr), "i" (ASI_PL)); +} + +static __inline__ void +xf86WriteMmio16BeNB(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + unsigned long addr = ((unsigned long)base) + offset; + + __asm__ __volatile__("sth %0, [%1]" + : /* No outputs */ + : "r" (val), "r" (addr)); +} + +static __inline__ void +xf86WriteMmio16LeNB(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + unsigned long addr = ((unsigned long)base) + offset; + + __asm__ __volatile__("stha %0, [%1] %2" + : /* No outputs */ + : "r" (val), "r" (addr), "i" (ASI_PL)); +} + +static __inline__ void +xf86WriteMmio32BeNB(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + unsigned long addr = ((unsigned long)base) + offset; + + __asm__ __volatile__("st %0, [%1]" + : /* No outputs */ + : "r" (val), "r" (addr)); +} + +static __inline__ void +xf86WriteMmio32LeNB(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + unsigned long addr = ((unsigned long)base) + offset; + + __asm__ __volatile__("sta %0, [%1] %2" + : /* No outputs */ + : "r" (val), "r" (addr), "i" (ASI_PL)); +} + +# elif defined(__mips__) || (defined(__arm32__) && !defined(__linux__)) +# ifdef __arm32__ +# define PORT_SIZE long +# else +# define PORT_SIZE short +# endif + +_X_EXPORT unsigned int IOPortBase; /* Memory mapped I/O port area */ + +static __inline__ void +outb(unsigned PORT_SIZE port, unsigned char val) +{ + *(volatile unsigned char*)(((unsigned PORT_SIZE)(port))+IOPortBase) = val; +} + +static __inline__ void +outw(unsigned PORT_SIZE port, unsigned short val) +{ + *(volatile unsigned short*)(((unsigned PORT_SIZE)(port))+IOPortBase) = val; +} + +static __inline__ void +outl(unsigned PORT_SIZE port, unsigned int val) +{ + *(volatile unsigned int*)(((unsigned PORT_SIZE)(port))+IOPortBase) = val; +} + +static __inline__ unsigned int +inb(unsigned PORT_SIZE port) +{ + return *(volatile unsigned char*)(((unsigned PORT_SIZE)(port))+IOPortBase); +} + +static __inline__ unsigned int +inw(unsigned PORT_SIZE port) +{ + return *(volatile unsigned short*)(((unsigned PORT_SIZE)(port))+IOPortBase); +} + +static __inline__ unsigned int +inl(unsigned PORT_SIZE port) +{ + return *(volatile unsigned int*)(((unsigned PORT_SIZE)(port))+IOPortBase); +} + + +# if defined(__mips__) +# ifdef linux /* don't mess with other OSs */ +# if X_BYTE_ORDER == X_BIG_ENDIAN +static __inline__ unsigned int +xf86ReadMmio32Be(__volatile__ void *base, const unsigned long offset) +{ + unsigned long addr = ((unsigned long)base) + offset; + unsigned int ret; + + __asm__ __volatile__("lw %0, 0(%1)" + : "=r" (ret) + : "r" (addr)); + return ret; +} + +static __inline__ void +xf86WriteMmio32Be(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + unsigned long addr = ((unsigned long)base) + offset; + + __asm__ __volatile__("sw %0, 0(%1)" + : /* No outputs */ + : "r" (val), "r" (addr)); +} +# endif +# endif /* !linux */ +# endif /* __mips__ */ + +# elif (defined(linux) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)) && defined(__powerpc__) + +# ifndef MAP_FAILED +# define MAP_FAILED ((void *)-1) +# endif + +extern _X_EXPORT volatile unsigned char *ioBase; + +static __inline__ unsigned char +xf86ReadMmio8(__volatile__ void *base, const unsigned long offset) +{ + register unsigned char val; + __asm__ __volatile__( + "lbzx %0,%1,%2\n\t" + "eieio" + : "=r" (val) + : "b" (base), "r" (offset), + "m" (*((volatile unsigned char *)base+offset))); + return val; +} + +static __inline__ unsigned short +xf86ReadMmio16Be(__volatile__ void *base, const unsigned long offset) +{ + register unsigned short val; + __asm__ __volatile__( + "lhzx %0,%1,%2\n\t" + "eieio" + : "=r" (val) + : "b" (base), "r" (offset), + "m" (*((volatile unsigned char *)base+offset))); + return val; +} + +static __inline__ unsigned short +xf86ReadMmio16Le(__volatile__ void *base, const unsigned long offset) +{ + register unsigned short val; + __asm__ __volatile__( + "lhbrx %0,%1,%2\n\t" + "eieio" + : "=r" (val) + : "b" (base), "r" (offset), + "m" (*((volatile unsigned char *)base+offset))); + return val; +} + +static __inline__ unsigned int +xf86ReadMmio32Be(__volatile__ void *base, const unsigned long offset) +{ + register unsigned int val; + __asm__ __volatile__( + "lwzx %0,%1,%2\n\t" + "eieio" + : "=r" (val) + : "b" (base), "r" (offset), + "m" (*((volatile unsigned char *)base+offset))); + return val; +} + +static __inline__ unsigned int +xf86ReadMmio32Le(__volatile__ void *base, const unsigned long offset) +{ + register unsigned int val; + __asm__ __volatile__( + "lwbrx %0,%1,%2\n\t" + "eieio" + : "=r" (val) + : "b" (base), "r" (offset), + "m" (*((volatile unsigned char *)base+offset))); + return val; +} + +static __inline__ void +xf86WriteMmioNB8(__volatile__ void *base, const unsigned long offset, + const unsigned char val) +{ + __asm__ __volatile__( + "stbx %1,%2,%3\n\t" + : "=m" (*((volatile unsigned char *)base+offset)) + : "r" (val), "b" (base), "r" (offset)); +} + +static __inline__ void +xf86WriteMmioNB16Le(__volatile__ void *base, const unsigned long offset, + const unsigned short val) +{ + __asm__ __volatile__( + "sthbrx %1,%2,%3\n\t" + : "=m" (*((volatile unsigned char *)base+offset)) + : "r" (val), "b" (base), "r" (offset)); +} + +static __inline__ void +xf86WriteMmioNB16Be(__volatile__ void *base, const unsigned long offset, + const unsigned short val) +{ + __asm__ __volatile__( + "sthx %1,%2,%3\n\t" + : "=m" (*((volatile unsigned char *)base+offset)) + : "r" (val), "b" (base), "r" (offset)); +} + +static __inline__ void +xf86WriteMmioNB32Le(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + __asm__ __volatile__( + "stwbrx %1,%2,%3\n\t" + : "=m" (*((volatile unsigned char *)base+offset)) + : "r" (val), "b" (base), "r" (offset)); +} + +static __inline__ void +xf86WriteMmioNB32Be(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + __asm__ __volatile__( + "stwx %1,%2,%3\n\t" + : "=m" (*((volatile unsigned char *)base+offset)) + : "r" (val), "b" (base), "r" (offset)); +} + +static __inline__ void +xf86WriteMmio8(__volatile__ void *base, const unsigned long offset, + const unsigned char val) +{ + xf86WriteMmioNB8(base, offset, val); + eieio(); +} + +static __inline__ void +xf86WriteMmio16Le(__volatile__ void *base, const unsigned long offset, + const unsigned short val) +{ + xf86WriteMmioNB16Le(base, offset, val); + eieio(); +} + +static __inline__ void +xf86WriteMmio16Be(__volatile__ void *base, const unsigned long offset, + const unsigned short val) +{ + xf86WriteMmioNB16Be(base, offset, val); + eieio(); +} + +static __inline__ void +xf86WriteMmio32Le(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + xf86WriteMmioNB32Le(base, offset, val); + eieio(); +} + +static __inline__ void +xf86WriteMmio32Be(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + xf86WriteMmioNB32Be(base, offset, val); + eieio(); +} + + +static __inline__ void +outb(unsigned short port, unsigned char value) +{ + if(ioBase == MAP_FAILED) return; + xf86WriteMmio8((void *)ioBase, port, value); +} + +static __inline__ void +outw(unsigned short port, unsigned short value) +{ + if(ioBase == MAP_FAILED) return; + xf86WriteMmio16Le((void *)ioBase, port, value); +} + +static __inline__ void +outl(unsigned short port, unsigned int value) +{ + if(ioBase == MAP_FAILED) return; + xf86WriteMmio32Le((void *)ioBase, port, value); +} + +static __inline__ unsigned int +inb(unsigned short port) +{ + if(ioBase == MAP_FAILED) return 0; + return xf86ReadMmio8((void *)ioBase, port); +} + +static __inline__ unsigned int +inw(unsigned short port) +{ + if(ioBase == MAP_FAILED) return 0; + return xf86ReadMmio16Le((void *)ioBase, port); +} + +static __inline__ unsigned int +inl(unsigned short port) +{ + if(ioBase == MAP_FAILED) return 0; + return xf86ReadMmio32Le((void *)ioBase, port); +} + +#elif defined(__arm__) && defined(__linux__) + +/* for Linux on ARM, we use the LIBC inx/outx routines */ +/* note that the appropriate setup via "ioperm" needs to be done */ +/* *before* any inx/outx is done. */ + +#include <sys/io.h> + +static __inline__ void +xf_outb(unsigned short port, unsigned char val) +{ + outb(val, port); +} + +static __inline__ void +xf_outw(unsigned short port, unsigned short val) +{ + outw(val, port); +} + +static __inline__ void +xf_outl(unsigned short port, unsigned int val) +{ + outl(val, port); +} + +#define outb xf_outb +#define outw xf_outw +#define outl xf_outl + +# elif defined(__nds32__) + +/* + * Assume all port access are aligned. We need to revise this implementation + * if there is unaligned port access. For ldq_u, ldl_u, ldw_u, stq_u, stl_u and + * stw_u, they are assumed unaligned. + */ + +#define barrier() /* no barrier */ + +#define PORT_SIZE long + +static __inline__ unsigned char +xf86ReadMmio8(__volatile__ void *base, const unsigned long offset) +{ + return *(volatile unsigned char *)((unsigned char *)base + offset) ; +} + +static __inline__ void +xf86WriteMmio8(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + *(volatile unsigned char *)((unsigned char *)base + offset) = val ; + barrier(); +} + +static __inline__ void +xf86WriteMmio8NB(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + *(volatile unsigned char *)((unsigned char *)base + offset) = val ; +} + +static __inline__ unsigned short +xf86ReadMmio16Swap(__volatile__ void *base, const unsigned long offset) +{ + unsigned long addr = ((unsigned long)base) + offset; + unsigned short ret; + + __asm__ __volatile__( + "lhi %0, [%1];\n\t" + "wsbh %0, %0;\n\t" + : "=r" (ret) + : "r" (addr)); + return ret; +} + +static __inline__ unsigned short +xf86ReadMmio16(__volatile__ void *base, const unsigned long offset) +{ + return *(volatile unsigned short *)((char *)base + offset) ; +} + +static __inline__ void +xf86WriteMmio16Swap(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + unsigned long addr = ((unsigned long)base) + offset; + + __asm__ __volatile__( + "wsbh %0, %0;\n\t" + "shi %0, [%1];\n\t" + : /* No outputs */ + : "r" (val), "r" (addr)); + barrier(); +} + +static __inline__ void +xf86WriteMmio16(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + *(volatile unsigned short *)((unsigned char *)base + offset) = val ; + barrier(); +} + +static __inline__ void +xf86WriteMmio16SwapNB(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + unsigned long addr = ((unsigned long)base) + offset; + + __asm__ __volatile__( + "wsbh %0, %0;\n\t" + "shi %0, [%1];\n\t" + : /* No outputs */ + : "r" (val), "r" (addr)); +} + +static __inline__ void +xf86WriteMmio16NB(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + *(volatile unsigned short *)((unsigned char *)base + offset) = val ; +} + +static __inline__ unsigned int +xf86ReadMmio32Swap(__volatile__ void *base, const unsigned long offset) +{ + unsigned long addr = ((unsigned long)base) + offset; + unsigned int ret; + + __asm__ __volatile__( + "lwi %0, [%1];\n\t" + "wsbh %0, %0;\n\t" + "rotri %0, %0, 16;\n\t" + : "=r" (ret) + : "r" (addr)); + return ret; +} + +static __inline__ unsigned int +xf86ReadMmio32(__volatile__ void *base, const unsigned long offset) +{ + return *(volatile unsigned int *)((unsigned char *)base + offset) ; +} + +static __inline__ void +xf86WriteMmio32Swap(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + unsigned long addr = ((unsigned long)base) + offset; + + __asm__ __volatile__( + "wsbh %0, %0;\n\t" + "rotri %0, %0, 16;\n\t" + "swi %0, [%1];\n\t" + : /* No outputs */ + : "r" (val), "r" (addr)); + barrier(); +} + +static __inline__ void +xf86WriteMmio32(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + *(volatile unsigned int *)((unsigned char *)base + offset) = val ; + barrier(); +} + +static __inline__ void +xf86WriteMmio32SwapNB(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + unsigned long addr = ((unsigned long)base) + offset; + + __asm__ __volatile__( + "wsbh %0, %0;\n\t" + "rotri %0, %0, 16;\n\t" + "swi %0, [%1];\n\t" + : /* No outputs */ + : "r" (val), "r" (addr)); +} + +static __inline__ void +xf86WriteMmio32NB(__volatile__ void *base, const unsigned long offset, + const unsigned int val) +{ + *(volatile unsigned int *)((unsigned char *)base + offset) = val ; +} + +# if defined(NDS32_MMIO_SWAP) +static __inline__ void +outb(unsigned PORT_SIZE port, unsigned char val) +{ + xf86WriteMmio8(IOPortBase, port, val); +} + +static __inline__ void +outw(unsigned PORT_SIZE port, unsigned short val) +{ + xf86WriteMmio16Swap(IOPortBase, port, val); +} + +static __inline__ void +outl(unsigned PORT_SIZE port, unsigned int val) +{ + xf86WriteMmio32Swap(IOPortBase, port, val); +} + +static __inline__ unsigned int +inb(unsigned PORT_SIZE port) +{ + return xf86ReadMmio8(IOPortBase, port); +} + +static __inline__ unsigned int +inw(unsigned PORT_SIZE port) +{ + return xf86ReadMmio16Swap(IOPortBase, port); +} + +static __inline__ unsigned int +inl(unsigned PORT_SIZE port) +{ + return xf86ReadMmio32Swap(IOPortBase, port); +} + +static __inline__ unsigned long ldq_u(unsigned long *p) +{ + unsigned long addr = (unsigned long)p; + unsigned int ret; + + __asm__ __volatile__( + "lmw.bi %0, [%1], %0, 0;\n\t" + "wsbh %0, %0;\n\t" + "rotri %0, %0, 16;\n\t" + : "=r" (ret) + : "r" (addr)); + return ret; +} + +static __inline__ unsigned long ldl_u(unsigned int *p) +{ + unsigned long addr = (unsigned long)p; + unsigned int ret; + + __asm__ __volatile__( + "lmw.bi %0, [%1], %0, 0;\n\t" + "wsbh %0, %0;\n\t" + "rotri %0, %0, 16;\n\t" + : "=r" (ret) + : "r" (addr)); + return ret; +} + +static __inline__ void stq_u(unsigned long val, unsigned long *p) +{ + unsigned long addr = (unsigned long)p; + + __asm__ __volatile__( + "wsbh %0, %0;\n\t" + "rotri %0, %0, 16;\n\t" + "smw.bi %0, [%1], %0, 0;\n\t" + : /* No outputs */ + : "r" (val), "r" (addr)); +} + +static __inline__ void stl_u(unsigned long val, unsigned int *p) +{ + unsigned long addr = (unsigned long)p; + + __asm__ __volatile__( + "wsbh %0, %0;\n\t" + "rotri %0, %0, 16;\n\t" + "smw.bi %0, [%1], %0, 0;\n\t" + : /* No outputs */ + : "r" (val), "r" (addr)); +} + +# else /* !NDS32_MMIO_SWAP */ +static __inline__ void +outb(unsigned PORT_SIZE port, unsigned char val) +{ + *(volatile unsigned char*)(((unsigned PORT_SIZE)(port))) = val; + barrier(); +} + +static __inline__ void +outw(unsigned PORT_SIZE port, unsigned short val) +{ + *(volatile unsigned short*)(((unsigned PORT_SIZE)(port))) = val; + barrier(); +} + +static __inline__ void +outl(unsigned PORT_SIZE port, unsigned int val) +{ + *(volatile unsigned int*)(((unsigned PORT_SIZE)(port))) = val; + barrier(); +} +static __inline__ unsigned int +inb(unsigned PORT_SIZE port) +{ + return *(volatile unsigned char*)(((unsigned PORT_SIZE)(port))); +} + +static __inline__ unsigned int +inw(unsigned PORT_SIZE port) +{ + return *(volatile unsigned short*)(((unsigned PORT_SIZE)(port))); +} + +static __inline__ unsigned int +inl(unsigned PORT_SIZE port) +{ + return *(volatile unsigned int*)(((unsigned PORT_SIZE)(port))); +} + +static __inline__ unsigned long ldq_u(unsigned long *p) +{ + unsigned long addr = (unsigned long)p; + unsigned int ret; + + __asm__ __volatile__( + "lmw.bi %0, [%1], %0, 0;\n\t" + : "=r" (ret) + : "r" (addr)); + return ret; +} + +static __inline__ unsigned long ldl_u(unsigned int *p) +{ + unsigned long addr = (unsigned long)p; + unsigned int ret; + + __asm__ __volatile__( + "lmw.bi %0, [%1], %0, 0;\n\t" + : "=r" (ret) + : "r" (addr)); + return ret; +} + + +static __inline__ void stq_u(unsigned long val, unsigned long *p) +{ + unsigned long addr = (unsigned long)p; + + __asm__ __volatile__( + "smw.bi %0, [%1], %0, 0;\n\t" + : /* No outputs */ + : "r" (val), "r" (addr)); +} + +static __inline__ void stl_u(unsigned long val, unsigned int *p) +{ + unsigned long addr = (unsigned long)p; + + __asm__ __volatile__( + "smw.bi %0, [%1], %0, 0;\n\t" + : /* No outputs */ + : "r" (val), "r" (addr)); +} +# endif /* NDS32_MMIO_SWAP */ + +# if (((X_BYTE_ORDER == X_BIG_ENDIAN) && !defined(NDS32_MMIO_SWAP)) || ((X_BYTE_ORDER != X_BIG_ENDIAN) && defined(NDS32_MMIO_SWAP))) +# define ldw_u(p) ((*(unsigned char *)(p)) << 8 | \ + (*((unsigned char *)(p)+1))) +# define stw_u(v,p) (*(unsigned char *)(p)) = ((v) >> 8); \ + (*((unsigned char *)(p)+1)) = (v) +# else +# define ldw_u(p) ((*(unsigned char *)(p)) | \ + (*((unsigned char *)(p)+1)<<8)) +# define stw_u(v,p) (*(unsigned char *)(p)) = (v); \ + (*((unsigned char *)(p)+1)) = ((v) >> 8) +# endif + +# define mem_barrier() /* XXX: nop for now */ +# define write_mem_barrier() /* XXX: nop for now */ + +# else /* ix86 */ + +# if !defined(__SUNPRO_C) +# if !defined(FAKEIT) && !defined(__mc68000__) && !defined(__arm__) && !defined(__sh__) && !defined(__hppa__) && !defined(__s390__) && !defined(__m32r__) +# ifdef GCCUSESGAS + +/* + * If gcc uses gas rather than the native assembler, the syntax of these + * inlines has to be different. DHD + */ + +static __inline__ void +outb(unsigned short port, unsigned char val) +{ + __asm__ __volatile__("outb %0,%1" : :"a" (val), "d" (port)); +} + + +static __inline__ void +outw(unsigned short port, unsigned short val) +{ + __asm__ __volatile__("outw %0,%1" : :"a" (val), "d" (port)); +} + +static __inline__ void +outl(unsigned short port, unsigned int val) +{ + __asm__ __volatile__("outl %0,%1" : :"a" (val), "d" (port)); +} + +static __inline__ unsigned int +inb(unsigned short port) +{ + unsigned char ret; + __asm__ __volatile__("inb %1,%0" : + "=a" (ret) : + "d" (port)); + return ret; +} + +static __inline__ unsigned int +inw(unsigned short port) +{ + unsigned short ret; + __asm__ __volatile__("inw %1,%0" : + "=a" (ret) : + "d" (port)); + return ret; +} + +static __inline__ unsigned int +inl(unsigned short port) +{ + unsigned int ret; + __asm__ __volatile__("inl %1,%0" : + "=a" (ret) : + "d" (port)); + return ret; +} + +# else /* GCCUSESGAS */ + +static __inline__ void +outb(unsigned short port, unsigned char val) +{ + __asm__ __volatile__("out%B0 (%1)" : :"a" (val), "d" (port)); +} + +static __inline__ void +outw(unsigned short port, unsigned short val) +{ + __asm__ __volatile__("out%W0 (%1)" : :"a" (val), "d" (port)); +} + +static __inline__ void +outl(unsigned short port, unsigned int val) +{ + __asm__ __volatile__("out%L0 (%1)" : :"a" (val), "d" (port)); +} + +static __inline__ unsigned int +inb(unsigned short port) +{ + unsigned char ret; + __asm__ __volatile__("in%B0 (%1)" : + "=a" (ret) : + "d" (port)); + return ret; +} + +static __inline__ unsigned int +inw(unsigned short port) +{ + unsigned short ret; + __asm__ __volatile__("in%W0 (%1)" : + "=a" (ret) : + "d" (port)); + return ret; +} + +static __inline__ unsigned int +inl(unsigned short port) +{ + unsigned int ret; + __asm__ __volatile__("in%L0 (%1)" : + "=a" (ret) : + "d" (port)); + return ret; +} + +# endif /* GCCUSESGAS */ + +# else /* !defined(FAKEIT) && !defined(__mc68000__) && !defined(__arm__) && !defined(__sh__) && !defined(__hppa__) && !defined(__m32r__) */ + +static __inline__ void +outb(unsigned short port, unsigned char val) +{ +} + +static __inline__ void +outw(unsigned short port, unsigned short val) +{ +} + +static __inline__ void +outl(unsigned short port, unsigned int val) +{ +} + +static __inline__ unsigned int +inb(unsigned short port) +{ + return 0; +} + +static __inline__ unsigned int +inw(unsigned short port) +{ + return 0; +} + +static __inline__ unsigned int +inl(unsigned short port) +{ + return 0; +} + +# endif /* FAKEIT */ +# endif /* __SUNPRO_C */ + +# endif /* ix86 */ + +# else /* !GNUC */ +# if defined(__STDC__) && (__STDC__ == 1) +# ifndef asm +# define asm __asm +# endif +# endif +# if !defined(__SUNPRO_C) +# include <sys/inline.h> +# endif +# if !defined(__HIGHC__) && !defined(__SUNPRO_C) || \ + defined(__USLC__) +# pragma asm partial_optimization outl +# pragma asm partial_optimization outw +# pragma asm partial_optimization outb +# pragma asm partial_optimization inl +# pragma asm partial_optimization inw +# pragma asm partial_optimization inb +# endif +# endif /* __GNUC__ */ + +# endif /* NO_INLINE */ + +# ifdef __alpha__ +/* entry points for Mmio memory access routines */ +extern _X_EXPORT int (*xf86ReadMmio8)(void *, unsigned long); +extern _X_EXPORT int (*xf86ReadMmio16)(void *, unsigned long); +# ifndef STANDALONE_MMIO +extern _X_EXPORT int (*xf86ReadMmio32)(void *, unsigned long); +# else +/* Some DRI 3D drivers need MMIO_IN32. */ +static __inline__ int +xf86ReadMmio32(void *Base, unsigned long Offset) +{ + mem_barrier(); + return *(volatile unsigned int*)((unsigned long)Base+(Offset)); +} +# endif +extern _X_EXPORT void (*xf86WriteMmio8)(int, void *, unsigned long); +extern _X_EXPORT void (*xf86WriteMmio16)(int, void *, unsigned long); +extern _X_EXPORT void (*xf86WriteMmio32)(int, void *, unsigned long); +extern _X_EXPORT void (*xf86WriteMmioNB8)(int, void *, unsigned long); +extern _X_EXPORT void (*xf86WriteMmioNB16)(int, void *, unsigned long); +extern _X_EXPORT void (*xf86WriteMmioNB32)(int, void *, unsigned long); +extern _X_EXPORT void xf86SlowBCopyFromBus(unsigned char *, unsigned char *, int); +extern _X_EXPORT void xf86SlowBCopyToBus(unsigned char *, unsigned char *, int); + +/* Some macros to hide the system dependencies for MMIO accesses */ +/* Changed to kill noise generated by gcc's -Wcast-align */ +# define MMIO_IN8(base, offset) (*xf86ReadMmio8)(base, offset) +# define MMIO_IN16(base, offset) (*xf86ReadMmio16)(base, offset) +# ifndef STANDALONE_MMIO +# define MMIO_IN32(base, offset) (*xf86ReadMmio32)(base, offset) +# else +# define MMIO_IN32(base, offset) xf86ReadMmio32(base, offset) +# endif + +# define MMIO_OUT32(base, offset, val) \ + do { \ + write_mem_barrier(); \ + *(volatile CARD32 *)(void *)(((CARD8*)(base)) + (offset)) = (val); \ + } while (0) +# define MMIO_ONB32(base, offset, val) \ + *(volatile CARD32 *)(void *)(((CARD8*)(base)) + (offset)) = (val) + +# define MMIO_OUT8(base, offset, val) \ + (*xf86WriteMmio8)((CARD8)(val), base, offset) +# define MMIO_OUT16(base, offset, val) \ + (*xf86WriteMmio16)((CARD16)(val), base, offset) +# define MMIO_ONB8(base, offset, val) \ + (*xf86WriteMmioNB8)((CARD8)(val), base, offset) +# define MMIO_ONB16(base, offset, val) \ + (*xf86WriteMmioNB16)((CARD16)(val), base, offset) +# define MMIO_MOVE32(base, offset, val) \ + MMIO_OUT32(base, offset, val) + +# elif defined(__powerpc__) + /* + * we provide byteswapping and no byteswapping functions here + * with byteswapping as default, + * drivers that don't need byteswapping should define PPC_MMIO_IS_BE + */ +# define MMIO_IN8(base, offset) xf86ReadMmio8(base, offset) +# define MMIO_OUT8(base, offset, val) \ + xf86WriteMmio8(base, offset, (CARD8)(val)) +# define MMIO_ONB8(base, offset, val) \ + xf86WriteMmioNB8(base, offset, (CARD8)(val)) + +# if defined(PPC_MMIO_IS_BE) /* No byteswapping */ +# define MMIO_IN16(base, offset) xf86ReadMmio16Be(base, offset) +# define MMIO_IN32(base, offset) xf86ReadMmio32Be(base, offset) +# define MMIO_OUT16(base, offset, val) \ + xf86WriteMmio16Be(base, offset, (CARD16)(val)) +# define MMIO_OUT32(base, offset, val) \ + xf86WriteMmio32Be(base, offset, (CARD32)(val)) +# define MMIO_ONB16(base, offset, val) \ + xf86WriteMmioNB16Be(base, offset, (CARD16)(val)) +# define MMIO_ONB32(base, offset, val) \ + xf86WriteMmioNB32Be(base, offset, (CARD32)(val)) +# else /* byteswapping is the default */ +# define MMIO_IN16(base, offset) xf86ReadMmio16Le(base, offset) +# define MMIO_IN32(base, offset) xf86ReadMmio32Le(base, offset) +# define MMIO_OUT16(base, offset, val) \ + xf86WriteMmio16Le(base, offset, (CARD16)(val)) +# define MMIO_OUT32(base, offset, val) \ + xf86WriteMmio32Le(base, offset, (CARD32)(val)) +# define MMIO_ONB16(base, offset, val) \ + xf86WriteMmioNB16Le(base, offset, (CARD16)(val)) +# define MMIO_ONB32(base, offset, val) \ + xf86WriteMmioNB32Le(base, offset, (CARD32)(val)) +# endif + +# define MMIO_MOVE32(base, offset, val) \ + xf86WriteMmio32Be(base, offset, (CARD32)(val)) + +# elif defined(__sparc__) || defined(sparc) || defined(__sparc) + /* + * Like powerpc, we provide byteswapping and no byteswapping functions + * here with byteswapping as default, drivers that don't need byteswapping + * should define SPARC_MMIO_IS_BE (perhaps create a generic macro so that we + * do not need to use PPC_MMIO_IS_BE and the sparc one in all the same places + * of drivers?). + */ +# define MMIO_IN8(base, offset) xf86ReadMmio8(base, offset) +# define MMIO_OUT8(base, offset, val) \ + xf86WriteMmio8(base, offset, (CARD8)(val)) +# define MMIO_ONB8(base, offset, val) \ + xf86WriteMmio8NB(base, offset, (CARD8)(val)) + +# if defined(SPARC_MMIO_IS_BE) /* No byteswapping */ +# define MMIO_IN16(base, offset) xf86ReadMmio16Be(base, offset) +# define MMIO_IN32(base, offset) xf86ReadMmio32Be(base, offset) +# define MMIO_OUT16(base, offset, val) \ + xf86WriteMmio16Be(base, offset, (CARD16)(val)) +# define MMIO_OUT32(base, offset, val) \ + xf86WriteMmio32Be(base, offset, (CARD32)(val)) +# define MMIO_ONB16(base, offset, val) \ + xf86WriteMmio16BeNB(base, offset, (CARD16)(val)) +# define MMIO_ONB32(base, offset, val) \ + xf86WriteMmio32BeNB(base, offset, (CARD32)(val)) +# else /* byteswapping is the default */ +# define MMIO_IN16(base, offset) xf86ReadMmio16Le(base, offset) +# define MMIO_IN32(base, offset) xf86ReadMmio32Le(base, offset) +# define MMIO_OUT16(base, offset, val) \ + xf86WriteMmio16Le(base, offset, (CARD16)(val)) +# define MMIO_OUT32(base, offset, val) \ + xf86WriteMmio32Le(base, offset, (CARD32)(val)) +# define MMIO_ONB16(base, offset, val) \ + xf86WriteMmio16LeNB(base, offset, (CARD16)(val)) +# define MMIO_ONB32(base, offset, val) \ + xf86WriteMmio32LeNB(base, offset, (CARD32)(val)) +# endif + +# define MMIO_MOVE32(base, offset, val) \ + xf86WriteMmio32Be(base, offset, (CARD32)(val)) + +# elif defined(__nds32__) + /* + * we provide byteswapping and no byteswapping functions here + * with no byteswapping as default; when endianness of CPU core + * and I/O devices don't match, byte swapping is necessary + * drivers that need byteswapping should define NDS32_MMIO_SWAP + */ +# define MMIO_IN8(base, offset) xf86ReadMmio8(base, offset) +# define MMIO_OUT8(base, offset, val) \ + xf86WriteMmio8(base, offset, (CARD8)(val)) +# define MMIO_ONB8(base, offset, val) \ + xf86WriteMmioNB8(base, offset, (CARD8)(val)) + +# if defined(NDS32_MMIO_SWAP) /* byteswapping */ +# define MMIO_IN16(base, offset) xf86ReadMmio16Swap(base, offset) +# define MMIO_IN32(base, offset) xf86ReadMmio32Swap(base, offset) +# define MMIO_OUT16(base, offset, val) \ + xf86WriteMmio16Swap(base, offset, (CARD16)(val)) +# define MMIO_OUT32(base, offset, val) \ + xf86WriteMmio32Swap(base, offset, (CARD32)(val)) +# define MMIO_ONB16(base, offset, val) \ + xf86WriteMmioNB16Swap(base, offset, (CARD16)(val)) +# define MMIO_ONB32(base, offset, val) \ + xf86WriteMmioNB32Swap(base, offset, (CARD32)(val)) +# else /* no byteswapping is the default */ +# define MMIO_IN16(base, offset) xf86ReadMmio16(base, offset) +# define MMIO_IN32(base, offset) xf86ReadMmio32(base, offset) +# define MMIO_OUT16(base, offset, val) \ + xf86WriteMmio16(base, offset, (CARD16)(val)) +# define MMIO_OUT32(base, offset, val) \ + xf86WriteMmio32(base, offset, (CARD32)(val)) +# define MMIO_ONB16(base, offset, val) \ + xf86WriteMmioNB16(base, offset, (CARD16)(val)) +# define MMIO_ONB32(base, offset, val) \ + xf86WriteMmioNB32(base, offset, (CARD32)(val)) +# endif + +# define MMIO_MOVE32(base, offset, val) \ + xf86WriteMmio32(base, offset, (CARD32)(val)) + +#ifdef N1213_HC /* for NDS32 N1213 hardcore */ +static __inline__ void nds32_flush_icache(char *addr) +{ + __asm__ volatile ( + "isync %0;" + "msync;" + "isb;" + "cctl %0,L1I_VA_INVAL;" + "isb;" + : : "r"(addr) : "memory"); +} +#else +static __inline__ void nds32_flush_icache(char *addr) +{ + __asm__ volatile ( + "isync %0;" + "isb;" + : : "r"(addr) : "memory"); +} +#endif + +# else /* !__alpha__ && !__powerpc__ && !__sparc__ */ + +# define MMIO_IN8(base, offset) \ + *(volatile CARD8 *)(((CARD8*)(base)) + (offset)) +# define MMIO_IN16(base, offset) \ + *(volatile CARD16 *)(void *)(((CARD8*)(base)) + (offset)) +# define MMIO_IN32(base, offset) \ + *(volatile CARD32 *)(void *)(((CARD8*)(base)) + (offset)) +# define MMIO_OUT8(base, offset, val) \ + *(volatile CARD8 *)(((CARD8*)(base)) + (offset)) = (val) +# define MMIO_OUT16(base, offset, val) \ + *(volatile CARD16 *)(void *)(((CARD8*)(base)) + (offset)) = (val) +# define MMIO_OUT32(base, offset, val) \ + *(volatile CARD32 *)(void *)(((CARD8*)(base)) + (offset)) = (val) +# define MMIO_ONB8(base, offset, val) MMIO_OUT8(base, offset, val) +# define MMIO_ONB16(base, offset, val) MMIO_OUT16(base, offset, val) +# define MMIO_ONB32(base, offset, val) MMIO_OUT32(base, offset, val) + +# define MMIO_MOVE32(base, offset, val) MMIO_OUT32(base, offset, val) + +# endif /* __alpha__ */ + +/* + * With Intel, the version in os-support/misc/SlowBcopy.s is used. + * This avoids port I/O during the copy (which causes problems with + * some hardware). + */ +# ifdef __alpha__ +# define slowbcopy_tobus(src,dst,count) xf86SlowBCopyToBus(src,dst,count) +# define slowbcopy_frombus(src,dst,count) xf86SlowBCopyFromBus(src,dst,count) +# else /* __alpha__ */ +# define slowbcopy_tobus(src,dst,count) xf86SlowBcopy(src,dst,count) +# define slowbcopy_frombus(src,dst,count) xf86SlowBcopy(src,dst,count) +# endif /* __alpha__ */ + +#endif /* _COMPILER_H */ diff --git a/hw/xfree86/common/extramodes b/hw/xfree86/common/extramodes new file mode 100644 index 0000000..4505026 --- /dev/null +++ b/hw/xfree86/common/extramodes @@ -0,0 +1,27 @@ +// +// Extra modes to include as default modes in the X server. +// +// $XFree86: xc/programs/Xserver/hw/xfree86/etc/extramodes,v 1.5 2002/06/05 19:43:05 dawes Exp $ +// + +# 832x624 @ 75Hz (74.55Hz) (fix if the official/Apple spec is different) hsync: 49.725kHz +ModeLine "832x624" 57.284 832 864 928 1152 624 625 628 667 -Hsync -Vsync + +# 1400x1050 @ 60Hz (VESA GTF) hsync: 65.5kHz +ModeLine "1400x1050" 122.0 1400 1488 1640 1880 1050 1052 1064 1082 +hsync +vsync + +# 1400x1050 @ 75Hz (VESA GTF) hsync: 82.2kHz +ModeLine "1400x1050" 155.8 1400 1464 1784 1912 1050 1052 1064 1090 +hsync +vsync + +# 1920x1440 @ 85Hz (VESA GTF) hsync: 128.5kHz +Modeline "1920x1440" 341.35 1920 2072 2288 2656 1440 1441 1444 1512 -hsync +vsync + +# 2048x1536 @ 60Hz (VESA GTF) hsync: 95.3kHz +Modeline "2048x1536" 266.95 2048 2200 2424 2800 1536 1537 1540 1589 -hsync +vsync + +# 2048x1536 @ 75Hz (VESA GTF) hsync: 120.2kHz +Modeline "2048x1536" 340.48 2048 2216 2440 2832 1536 1537 1540 1603 -hsync +vsync + +# 2048x1536 @ 85Hz (VESA GTF) hsync: 137.0kHz +Modeline "2048x1536" 388.04 2048 2216 2440 2832 1536 1537 1540 1612 -hsync +vsync + diff --git a/hw/xfree86/common/fourcc.h b/hw/xfree86/common/fourcc.h new file mode 100644 index 0000000..853657e --- /dev/null +++ b/hw/xfree86/common/fourcc.h @@ -0,0 +1,160 @@ + +/* + * Copyright (c) 2000-2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + This header file contains listings of STANDARD guids for video formats. + Please do not place non-registered, or incomplete entries in this file. + A list of some popular fourcc's are at: http://www.webartz.com/fourcc/ + For an explanation of fourcc <-> guid mappings see RFC2361. +*/ + +#ifndef _XF86_FOURCC_H_ +#define _XF86_FOURCC_H_ 1 + +#define FOURCC_YUY2 0x32595559 +#define XVIMAGE_YUY2 \ + { \ + FOURCC_YUY2, \ + XvYUV, \ + LSBFirst, \ + {'Y','U','Y','2', \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 16, \ + XvPacked, \ + 1, \ + 0, 0, 0, 0, \ + 8, 8, 8, \ + 1, 2, 2, \ + 1, 1, 1, \ + {'Y','U','Y','V', \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } + +#define FOURCC_YV12 0x32315659 +#define XVIMAGE_YV12 \ + { \ + FOURCC_YV12, \ + XvYUV, \ + LSBFirst, \ + {'Y','V','1','2', \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 12, \ + XvPlanar, \ + 3, \ + 0, 0, 0, 0, \ + 8, 8, 8, \ + 1, 2, 2, \ + 1, 2, 2, \ + {'Y','V','U', \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } + +#define FOURCC_I420 0x30323449 +#define XVIMAGE_I420 \ + { \ + FOURCC_I420, \ + XvYUV, \ + LSBFirst, \ + {'I','4','2','0', \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 12, \ + XvPlanar, \ + 3, \ + 0, 0, 0, 0, \ + 8, 8, 8, \ + 1, 2, 2, \ + 1, 2, 2, \ + {'Y','U','V', \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } + + +#define FOURCC_UYVY 0x59565955 +#define XVIMAGE_UYVY \ + { \ + FOURCC_UYVY, \ + XvYUV, \ + LSBFirst, \ + {'U','Y','V','Y', \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 16, \ + XvPacked, \ + 1, \ + 0, 0, 0, 0, \ + 8, 8, 8, \ + 1, 2, 2, \ + 1, 1, 1, \ + {'U','Y','V','Y', \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } + +#define FOURCC_IA44 0x34344149 +#define XVIMAGE_IA44 \ + { \ + FOURCC_IA44, \ + XvYUV, \ + LSBFirst, \ + {'I','A','4','4', \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 8, \ + XvPacked, \ + 1, \ + 0, 0, 0, 0, \ + 8, 8, 8, \ + 1, 1, 1, \ + 1, 1, 1, \ + {'A','I', \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } + +#define FOURCC_AI44 0x34344941 +#define XVIMAGE_AI44 \ + { \ + FOURCC_AI44, \ + XvYUV, \ + LSBFirst, \ + {'A','I','4','4', \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 8, \ + XvPacked, \ + 1, \ + 0, 0, 0, 0, \ + 8, 8, 8, \ + 1, 1, 1, \ + 1, 1, 1, \ + {'I','A', \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } + +#endif /* _XF86_FOURCC_H_ */ diff --git a/hw/xfree86/common/modeline2c.awk b/hw/xfree86/common/modeline2c.awk new file mode 100644 index 0000000..038e7e9 --- /dev/null +++ b/hw/xfree86/common/modeline2c.awk @@ -0,0 +1,93 @@ +#!/usr/bin/awk -f +# +# Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>. +# All rights reserved. +# +# Based on Perl script by Dirk Hohndel. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# Usage: modeline2c.awk < modefile > xf86DefModeSet.c +# + +BEGIN { + flagsdict[""] = "0" + + flagsdict["+hsync +vsync"] = "V_PHSYNC | V_PVSYNC" + flagsdict["+hsync -vsync"] = "V_PHSYNC | V_NVSYNC" + flagsdict["-hsync +vsync"] = "V_NHSYNC | V_PVSYNC" + flagsdict["-hsync -vsync"] = "V_NHSYNC | V_NVSYNC" + flagsdict["+hsync +vsync interlace"] = "V_PHSYNC | V_PVSYNC | V_INTERLACE" + flagsdict["+hsync -vsync interlace"] = "V_PHSYNC | V_NVSYNC | V_INTERLACE" + flagsdict["-hsync +vsync interlace"] = "V_NHSYNC | V_PVSYNC | V_INTERLACE" + flagsdict["-hsync -vsync interlace"] = "V_NHSYNC | V_NVSYNC | V_INTERLACE" + + print "/* THIS FILE IS AUTOMATICALLY GENERATED -- DO NOT EDIT -- LOOK at" + print " * modeline2c.awk */" + print "" + print "/*" + print " * Author: Joerg Sonnenberger <joerg@NetBSD.org>" + print " * Based on Perl script from Dirk Hohndel <hohndel@XFree86.Org>" + print " */" + print "" + print "#ifdef HAVE_XORG_CONFIG_H" + print "#include <xorg-config.h>" + print "#endif" + print "" + print "#include \"xf86.h\"" + print "#include \"xf86Config.h\"" + print "#include \"xf86Priv.h\"" + print "#include \"xf86_OSlib.h\"" + print "" + print "#include \"globals.h\"" + print "" + print "#define MODEPREFIX NULL, NULL, NULL, MODE_OK, M_T_DEFAULT" + print "#define MODESUFFIX 0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0" + print "" + print "const DisplayModeRec xf86DefaultModes [] = {" + + modeline = "\t{MODEPREFIX,%d, %d,%d,%d,%d,0, %d,%d,%d,%d,0, %s, MODESUFFIX},\n" + modeline_data = "^[a-zA-Z]+[ \t]+[^ \t]+[ \t0-9.]+" +} + +/^[mM][oO][dD][eE][lL][iI][nN][eE]/ { + flags = $0 + gsub(modeline_data, "", flags) + flags = tolower(flags) + printf(modeline, $3 * 1000, $4, $5, $6, $7, + $8, $9, $10, $11, flagsdict[flags]) + # Half-width double scanned modes + printf(modeline, $3 * 500, $4/2, $5/2, $6/2, $7/2, + $8/2, $9/2, $10/2, $11/2, flagsdict[flags] " | V_DBLSCAN") +} + +/^#/ { + print "/*" substr($0, 2) " */" +} + +END { + print "};" + printf "const int xf86NumDefaultModes = sizeof(xf86DefaultModes) / sizeof(DisplayModeRec);" +} diff --git a/hw/xfree86/common/vesamodes b/hw/xfree86/common/vesamodes new file mode 100644 index 0000000..2bc8862 --- /dev/null +++ b/hw/xfree86/common/vesamodes @@ -0,0 +1,111 @@ +// +// Default modes distilled from +// "VESA and Industry Standards and Guide for Computer Display Monitor +// Timing", version 1.0, revision 0.8, adopted September 17, 1998. +// +// $XFree86: xc/programs/Xserver/hw/xfree86/etc/vesamodes,v 1.3 1999/11/16 03:28:03 tsi Exp $ + + +# 640x350 @ 85Hz (VESA) hsync: 37.9kHz +ModeLine "640x350" 31.5 640 672 736 832 350 382 385 445 +hsync -vsync + +# 640x400 @ 85Hz (VESA) hsync: 37.9kHz +ModeLine "640x400" 31.5 640 672 736 832 400 401 404 445 -hsync +vsync + +# 720x400 @ 85Hz (VESA) hsync: 37.9kHz +ModeLine "720x400" 35.5 720 756 828 936 400 401 404 446 -hsync +vsync + +# 640x480 @ 60Hz (Industry standard) hsync: 31.5kHz +ModeLine "640x480" 25.175 640 656 752 800 480 490 492 525 -hsync -vsync + +# 640x480 @ 72Hz (VESA) hsync: 37.9kHz +ModeLine "640x480" 31.5 640 664 704 832 480 489 492 520 -hsync -vsync + +# 640x480 @ 75Hz (VESA) hsync: 37.5kHz +ModeLine "640x480" 31.5 640 656 720 840 480 481 484 500 -hsync -vsync + +# 640x480 @ 85Hz (VESA) hsync: 43.3kHz +ModeLine "640x480" 36.0 640 696 752 832 480 481 484 509 -hsync -vsync + +# 800x600 @ 56Hz (VESA) hsync: 35.2kHz +ModeLine "800x600" 36.0 800 824 896 1024 600 601 603 625 +hsync +vsync + +# 800x600 @ 60Hz (VESA) hsync: 37.9kHz +ModeLine "800x600" 40.0 800 840 968 1056 600 601 605 628 +hsync +vsync + +# 800x600 @ 72Hz (VESA) hsync: 48.1kHz +ModeLine "800x600" 50.0 800 856 976 1040 600 637 643 666 +hsync +vsync + +# 800x600 @ 75Hz (VESA) hsync: 46.9kHz +ModeLine "800x600" 49.5 800 816 896 1056 600 601 604 625 +hsync +vsync + +# 800x600 @ 85Hz (VESA) hsync: 53.7kHz +ModeLine "800x600" 56.3 800 832 896 1048 600 601 604 631 +hsync +vsync + +# 1024x768i @ 43Hz (industry standard) hsync: 35.5kHz +ModeLine "1024x768" 44.9 1024 1032 1208 1264 768 768 776 817 +hsync +vsync Interlace + +# 1024x768 @ 60Hz (VESA) hsync: 48.4kHz +ModeLine "1024x768" 65.0 1024 1048 1184 1344 768 771 777 806 -hsync -vsync + +# 1024x768 @ 70Hz (VESA) hsync: 56.5kHz +ModeLine "1024x768" 75.0 1024 1048 1184 1328 768 771 777 806 -hsync -vsync + +# 1024x768 @ 75Hz (VESA) hsync: 60.0kHz +ModeLine "1024x768" 78.75 1024 1040 1136 1312 768 769 772 800 +hsync +vsync + +# 1024x768 @ 85Hz (VESA) hsync: 68.7kHz +ModeLine "1024x768" 94.5 1024 1072 1168 1376 768 769 772 808 +hsync +vsync + +# 1152x864 @ 75Hz (VESA) hsync: 67.5kHz +ModeLine "1152x864" 108.0 1152 1216 1344 1600 864 865 868 900 +hsync +vsync + +# 1280x960 @ 60Hz (VESA) hsync: 60.0kHz +ModeLine "1280x960" 108.0 1280 1376 1488 1800 960 961 964 1000 +hsync +vsync + +# 1280x960 @ 85Hz (VESA) hsync: 85.9kHz +ModeLine "1280x960" 148.5 1280 1344 1504 1728 960 961 964 1011 +hsync +vsync + +# 1280x1024 @ 60Hz (VESA) hsync: 64.0kHz +ModeLine "1280x1024" 108.0 1280 1328 1440 1688 1024 1025 1028 1066 +hsync +vsync + +# 1280x1024 @ 75Hz (VESA) hsync: 80.0kHz +ModeLine "1280x1024" 135.0 1280 1296 1440 1688 1024 1025 1028 1066 +hsync +vsync + +# 1280x1024 @ 85Hz (VESA) hsync: 91.1kHz +ModeLine "1280x1024" 157.5 1280 1344 1504 1728 1024 1025 1028 1072 +hsync +vsync + +# 1600x1200 @ 60Hz (VESA) hsync: 75.0kHz +ModeLine "1600x1200" 162.0 1600 1664 1856 2160 1200 1201 1204 1250 +hsync +vsync + +# 1600x1200 @ 65Hz (VESA) hsync: 81.3kHz +ModeLine "1600x1200" 175.5 1600 1664 1856 2160 1200 1201 1204 1250 +hsync +vsync + +# 1600x1200 @ 70Hz (VESA) hsync: 87.5kHz +ModeLine "1600x1200" 189.0 1600 1664 1856 2160 1200 1201 1204 1250 +hsync +vsync + +# 1600x1200 @ 75Hz (VESA) hsync: 93.8kHz +ModeLine "1600x1200" 202.5 1600 1664 1856 2160 1200 1201 1204 1250 +hsync +vsync + +# 1600x1200 @ 85Hz (VESA) hsync: 106.3kHz +ModeLine "1600x1200" 229.5 1600 1664 1856 2160 1200 1201 1204 1250 +hsync +vsync + +# 1792x1344 @ 60Hz (VESA) hsync: 83.6kHz +ModeLine "1792x1344" 204.8 1792 1920 2120 2448 1344 1345 1348 1394 -hsync +vsync + +# 1792x1344 @ 75Hz (VESA) hsync: 106.3kHz +ModeLine "1792x1344" 261.0 1792 1888 2104 2456 1344 1345 1348 1417 -hsync +vsync + +# 1856x1392 @ 60Hz (VESA) hsync: 86.3kHz +ModeLine "1856x1392" 218.3 1856 1952 2176 2528 1392 1393 1396 1439 -hsync +vsync + +# 1856x1392 @ 75Hz (VESA) hsync: 112.5kHz +ModeLine "1856x1392" 288.0 1856 1984 2208 2560 1392 1393 1396 1500 -hsync +vsync + +# 1920x1440 @ 60Hz (VESA) hsync: 90.0kHz +ModeLine "1920x1440" 234.0 1920 2048 2256 2600 1440 1441 1444 1500 -hsync +vsync + +# 1920x1440 @ 75Hz (VESA) hsync: 112.5kHz +ModeLine "1920x1440" 297.0 1920 2064 2288 2640 1440 1441 1444 1500 -hsync +vsync + + diff --git a/hw/xfree86/common/vidmodeproc.h b/hw/xfree86/common/vidmodeproc.h new file mode 100644 index 0000000..da4d05e --- /dev/null +++ b/hw/xfree86/common/vidmodeproc.h @@ -0,0 +1,77 @@ + +/* Prototypes for DGA functions that the DDX must provide */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef _VIDMODEPROC_H_ +#define _VIDMODEPROC_H_ + + +typedef enum { + VIDMODE_H_DISPLAY, + VIDMODE_H_SYNCSTART, + VIDMODE_H_SYNCEND, + VIDMODE_H_TOTAL, + VIDMODE_H_SKEW, + VIDMODE_V_DISPLAY, + VIDMODE_V_SYNCSTART, + VIDMODE_V_SYNCEND, + VIDMODE_V_TOTAL, + VIDMODE_FLAGS, + VIDMODE_CLOCK +} VidModeSelectMode; + +typedef enum { + VIDMODE_MON_VENDOR, + VIDMODE_MON_MODEL, + VIDMODE_MON_NHSYNC, + VIDMODE_MON_NVREFRESH, + VIDMODE_MON_HSYNC_LO, + VIDMODE_MON_HSYNC_HI, + VIDMODE_MON_VREFRESH_LO, + VIDMODE_MON_VREFRESH_HI +} VidModeSelectMonitor; + +typedef union { + pointer ptr; + int i; + float f; +} vidMonitorValue; + +extern _X_EXPORT void XFree86VidModeExtensionInit(void); + +extern _X_EXPORT Bool VidModeAvailable(int scrnIndex); +extern _X_EXPORT Bool VidModeGetCurrentModeline(int scrnIndex, pointer *mode, int *dotClock); +extern _X_EXPORT Bool VidModeGetFirstModeline(int scrnIndex, pointer *mode, int *dotClock); +extern _X_EXPORT Bool VidModeGetNextModeline(int scrnIndex, pointer *mode, int *dotClock); +extern _X_EXPORT Bool VidModeDeleteModeline(int scrnIndex, pointer mode); +extern _X_EXPORT Bool VidModeZoomViewport(int scrnIndex, int zoom); +extern _X_EXPORT Bool VidModeGetViewPort(int scrnIndex, int *x, int *y); +extern _X_EXPORT Bool VidModeSetViewPort(int scrnIndex, int x, int y); +extern _X_EXPORT Bool VidModeSwitchMode(int scrnIndex, pointer mode); +extern _X_EXPORT Bool VidModeLockZoom(int scrnIndex, Bool lock); +extern _X_EXPORT Bool VidModeGetMonitor(int scrnIndex, pointer *monitor); +extern _X_EXPORT int VidModeGetNumOfClocks(int scrnIndex, Bool *progClock); +extern _X_EXPORT Bool VidModeGetClocks(int scrnIndex, int *Clocks); +extern _X_EXPORT ModeStatus VidModeCheckModeForMonitor(int scrnIndex, pointer mode); +extern _X_EXPORT ModeStatus VidModeCheckModeForDriver(int scrnIndex, pointer mode); +extern _X_EXPORT void VidModeSetCrtcForMode(int scrnIndex, pointer mode); +extern _X_EXPORT Bool VidModeAddModeline(int scrnIndex, pointer mode); +extern _X_EXPORT int VidModeGetDotClock(int scrnIndex, int Clock); +extern _X_EXPORT int VidModeGetNumOfModes(int scrnIndex); +extern _X_EXPORT Bool VidModeSetGamma(int scrnIndex, float red, float green, float blue); +extern _X_EXPORT Bool VidModeGetGamma(int scrnIndex, float *red, float *green, float *blue); +extern _X_EXPORT pointer VidModeCreateMode(void); +extern _X_EXPORT void VidModeCopyMode(pointer modefrom, pointer modeto); +extern _X_EXPORT int VidModeGetModeValue(pointer mode, int valtyp); +extern _X_EXPORT void VidModeSetModeValue(pointer mode, int valtyp, int val); +extern _X_EXPORT vidMonitorValue VidModeGetMonitorValue(pointer monitor, int valtyp, int indx); +extern _X_EXPORT Bool VidModeSetGammaRamp(int, int, CARD16 *, CARD16 *, CARD16 *); +extern _X_EXPORT Bool VidModeGetGammaRamp(int, int, CARD16 *, CARD16 *, CARD16 *); +extern _X_EXPORT int VidModeGetGammaRampSize(int scrnIndex); + +#endif + + diff --git a/hw/xfree86/common/xf86.h b/hw/xfree86/common/xf86.h new file mode 100644 index 0000000..54332e3 --- /dev/null +++ b/hw/xfree86/common/xf86.h @@ -0,0 +1,353 @@ +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * This file contains declarations for public XFree86 functions and variables, + * and definitions of public macros. + * + * "public" means available to video drivers. + */ + +#ifndef _XF86_H +#define _XF86_H + +#if HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#elif HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "xf86str.h" +#include "xf86Opt.h" +#include <X11/Xfuncproto.h> +#include <stdarg.h> +#ifdef RANDR +#include <X11/extensions/randr.h> +#endif + +#include "propertyst.h" + +/* General parameters */ +extern _X_EXPORT int xf86DoConfigure; +extern _X_EXPORT int xf86DoShowOptions; +extern _X_EXPORT Bool xf86DoConfigurePass1; + +extern _X_EXPORT DevPrivateKeyRec xf86ScreenKeyRec; +#define xf86ScreenKey (&xf86ScreenKeyRec) + +extern _X_EXPORT DevPrivateKeyRec xf86CreateRootWindowKeyRec; +#define xf86CreateRootWindowKey (&xf86CreateRootWindowKeyRec) + +extern _X_EXPORT ScrnInfoPtr *xf86Screens; /* List of pointers to ScrnInfoRecs */ +extern _X_EXPORT const unsigned char byte_reversed[256]; +extern _X_EXPORT Bool fbSlotClaimed; +#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) +extern _X_EXPORT Bool sbusSlotClaimed; +#endif +extern _X_EXPORT confDRIRec xf86ConfigDRI; +extern _X_EXPORT Bool xf86DRI2Enabled(void); + +extern _X_EXPORT Bool VTSwitchEnabled; /* kbd driver */ + +#define XF86SCRNINFO(p) ((ScrnInfoPtr)dixLookupPrivate(&(p)->devPrivates, \ + xf86ScreenKey)) +#define XF86FLIP_PIXELS() \ + do { \ + if (xf86GetFlipPixels()) { \ + pScreen->whitePixel = (pScreen->whitePixel) ? 0 : 1; \ + pScreen->blackPixel = (pScreen->blackPixel) ? 0 : 1; \ + } \ + while (0) + +#define BOOLTOSTRING(b) ((b) ? "TRUE" : "FALSE") + +#define PIX24TOBPP(p) (((p) == Pix24Use24) ? 24 : \ + (((p) == Pix24Use32) ? 32 : 0)) + +/* Function Prototypes */ +#ifndef _NO_XF86_PROTOTYPES + +/* PCI related */ +#include <pciaccess.h> +extern _X_EXPORT Bool pciSlotClaimed; + +extern _X_EXPORT Bool xf86CheckPciSlot(const struct pci_device *); +extern _X_EXPORT int xf86ClaimPciSlot(struct pci_device *, DriverPtr drvp, + int chipset, GDevPtr dev, Bool active); +extern _X_EXPORT void xf86UnclaimPciSlot(struct pci_device *); +extern _X_EXPORT Bool xf86ParsePciBusString(const char *busID, int *bus, + int *device, int *func); +extern _X_EXPORT Bool xf86ComparePciBusString(const char *busID, int bus, + int device, int func); +extern _X_EXPORT void xf86FormatPciBusNumber(int busnum, char *buffer); +extern _X_EXPORT Bool xf86IsPrimaryPci(struct pci_device * pPci); +extern _X_EXPORT Bool xf86CheckPciMemBase(struct pci_device * pPci, + memType base); +extern _X_EXPORT struct pci_device * xf86GetPciInfoForEntity(int entityIndex); +extern _X_EXPORT int xf86MatchPciInstances(const char *driverName, + int vendorID, SymTabPtr chipsets, PciChipsets *PCIchipsets, + GDevPtr *devList, int numDevs, DriverPtr drvp, int **foundEntities); +extern _X_EXPORT ScrnInfoPtr xf86ConfigPciEntity(ScrnInfoPtr pScrn, + int scrnFlag, int entityIndex,PciChipsets *p_chip, void *dummy, + EntityProc init, EntityProc enter, EntityProc leave, pointer private); +/* Obsolete! don't use */ +extern _X_EXPORT Bool xf86ConfigActivePciEntity(ScrnInfoPtr pScrn, + int entityIndex,PciChipsets *p_chip, void *dummy, EntityProc init, + EntityProc enter, EntityProc leave, pointer private); + +/* xf86Bus.c */ + +extern _X_EXPORT int xf86GetFbInfoForScreen(int scrnIndex); +extern _X_EXPORT int xf86ClaimFbSlot(DriverPtr drvp, int chipset, GDevPtr dev, Bool active); +extern _X_EXPORT int xf86ClaimNoSlot(DriverPtr drvp, int chipset, GDevPtr dev, Bool active); +extern _X_EXPORT Bool xf86DriverHasEntities(DriverPtr drvp); +extern _X_EXPORT void xf86AddEntityToScreen(ScrnInfoPtr pScrn, int entityIndex); +extern _X_EXPORT void xf86SetEntityInstanceForScreen(ScrnInfoPtr pScrn, int entityIndex, + int instance); +extern _X_EXPORT int xf86GetNumEntityInstances(int entityIndex); +extern _X_EXPORT GDevPtr xf86GetDevFromEntity(int entityIndex, int instance); +extern _X_EXPORT void xf86RemoveEntityFromScreen(ScrnInfoPtr pScrn, int entityIndex); +extern _X_EXPORT EntityInfoPtr xf86GetEntityInfo(int entityIndex); +extern _X_EXPORT Bool xf86SetEntityFuncs(int entityIndex, EntityProc init, + EntityProc enter, EntityProc leave, pointer); +extern _X_EXPORT Bool xf86IsEntityPrimary(int entityIndex); +extern _X_EXPORT ScrnInfoPtr xf86FindScreenForEntity(int entityIndex); + +extern _X_EXPORT int xf86GetLastScrnFlag(int entityIndex); +extern _X_EXPORT void xf86SetLastScrnFlag(int entityIndex, int scrnIndex); +extern _X_EXPORT Bool xf86IsEntityShared(int entityIndex); +extern _X_EXPORT void xf86SetEntityShared(int entityIndex); +extern _X_EXPORT Bool xf86IsEntitySharable(int entityIndex); +extern _X_EXPORT void xf86SetEntitySharable(int entityIndex); +extern _X_EXPORT Bool xf86IsPrimInitDone(int entityIndex); +extern _X_EXPORT void xf86SetPrimInitDone(int entityIndex); +extern _X_EXPORT void xf86ClearPrimInitDone(int entityIndex); +extern _X_EXPORT int xf86AllocateEntityPrivateIndex(void); +extern _X_EXPORT DevUnion *xf86GetEntityPrivate(int entityIndex, int privIndex); + +/* xf86Configure.c */ +extern _X_EXPORT GDevPtr xf86AddBusDeviceToConfigure(const char *driver, BusType bus, + void *busData, int chipset); + +/* xf86Cursor.c */ + +extern _X_EXPORT void xf86LockZoom(ScreenPtr pScreen, int lock); +extern _X_EXPORT void xf86InitViewport(ScrnInfoPtr pScr); +extern _X_EXPORT void xf86SetViewport(ScreenPtr pScreen, int x, int y); +extern _X_EXPORT void xf86ZoomViewport(ScreenPtr pScreen, int zoom); +extern _X_EXPORT Bool xf86SwitchMode(ScreenPtr pScreen, DisplayModePtr mode); +extern _X_EXPORT void *xf86GetPointerScreenFuncs(void); +extern _X_EXPORT void xf86InitOrigins(void); +extern _X_EXPORT void xf86ReconfigureLayout(void); + +/* xf86cvt.c */ +extern _X_EXPORT DisplayModePtr xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, + Bool Reduced, Bool Interlaced); + +/* xf86DPMS.c */ + +extern _X_EXPORT Bool xf86DPMSInit(ScreenPtr pScreen, DPMSSetProcPtr set, int flags); + +#ifdef DPMSExtension +extern _X_EXPORT int DPMSSet(ClientPtr client, int level); +extern _X_EXPORT Bool DPMSSupported(void); +#endif + + +/* xf86DGA.c */ + +#ifdef XFreeXDGA +extern _X_EXPORT Bool DGAInit(ScreenPtr pScreen, DGAFunctionPtr funcs, DGAModePtr modes, + int num); +extern _X_EXPORT Bool DGAReInitModes(ScreenPtr pScreen, DGAModePtr modes, int num); +extern _X_EXPORT xf86SetDGAModeProc xf86SetDGAMode; +#endif + +/* xf86Events.c */ + +extern _X_EXPORT void SetTimeSinceLastInputEvent(void); +extern _X_EXPORT pointer xf86AddInputHandler(int fd, InputHandlerProc proc, pointer data); +extern _X_EXPORT int xf86RemoveInputHandler(pointer handler); +extern _X_EXPORT void xf86DisableInputHandler(pointer handler); +extern _X_EXPORT void xf86EnableInputHandler(pointer handler); +extern _X_EXPORT pointer xf86AddGeneralHandler(int fd, InputHandlerProc proc, pointer data); +extern _X_EXPORT int xf86RemoveGeneralHandler(pointer handler); +extern _X_EXPORT void xf86DisableGeneralHandler(pointer handler); +extern _X_EXPORT void xf86EnableGeneralHandler(pointer handler); +extern _X_EXPORT InputHandlerProc xf86SetConsoleHandler(InputHandlerProc handler, pointer data); +extern _X_EXPORT void xf86InterceptSignals(int *signo); +extern _X_EXPORT void xf86InterceptSigIll(void (*sigillhandler)(void)); +extern _X_EXPORT Bool xf86EnableVTSwitch(Bool new); +extern _X_EXPORT void xf86ProcessActionEvent(ActionEvent action, void *arg); +extern _X_EXPORT void xf86PrintBacktrace(void); + +/* xf86Helper.c */ + +extern _X_EXPORT void xf86AddDriver(DriverPtr driver, pointer module, int flags); +extern _X_EXPORT void xf86DeleteDriver(int drvIndex); +extern _X_EXPORT ScrnInfoPtr xf86AllocateScreen(DriverPtr drv, int flags); +extern _X_EXPORT void xf86DeleteScreen(int scrnIndex, int flags); +extern _X_EXPORT int xf86AllocateScrnInfoPrivateIndex(void); +extern _X_EXPORT Bool xf86AddPixFormat(ScrnInfoPtr pScrn, int depth, int bpp, int pad); +extern _X_EXPORT Bool xf86SetDepthBpp(ScrnInfoPtr scrp, int depth, int bpp, int fbbpp, + int depth24flags); +extern _X_EXPORT void xf86PrintDepthBpp(ScrnInfoPtr scrp); +extern _X_EXPORT Bool xf86SetWeight(ScrnInfoPtr scrp, rgb weight, rgb mask); +extern _X_EXPORT Bool xf86SetDefaultVisual(ScrnInfoPtr scrp, int visual); +extern _X_EXPORT Bool xf86SetGamma(ScrnInfoPtr scrp, Gamma newGamma); +extern _X_EXPORT void xf86SetDpi(ScrnInfoPtr pScrn, int x, int y); +extern _X_EXPORT void xf86SetBlackWhitePixels(ScreenPtr pScreen); +extern _X_EXPORT void xf86EnableDisableFBAccess(int scrnIndex, Bool enable); +extern _X_EXPORT void xf86VDrvMsgVerb(int scrnIndex, MessageType type, int verb, + const char *format, va_list args); +extern _X_EXPORT void xf86DrvMsgVerb(int scrnIndex, MessageType type, int verb, + const char *format, ...) _X_ATTRIBUTE_PRINTF(4,5); +extern _X_EXPORT void xf86DrvMsg(int scrnIndex, MessageType type, const char *format, ...) + _X_ATTRIBUTE_PRINTF(3,4); +extern _X_EXPORT void xf86MsgVerb(MessageType type, int verb, const char *format, ...) + _X_ATTRIBUTE_PRINTF(3,4); +extern _X_EXPORT void xf86Msg(MessageType type, const char *format, ...) _X_ATTRIBUTE_PRINTF(2,3); +extern _X_EXPORT void xf86ErrorFVerb(int verb, const char *format, ...) _X_ATTRIBUTE_PRINTF(2,3); +extern _X_EXPORT void xf86ErrorF(const char *format, ...) _X_ATTRIBUTE_PRINTF(1,2); +extern _X_EXPORT const char *xf86TokenToString(SymTabPtr table, int token); +extern _X_EXPORT int xf86StringToToken(SymTabPtr table, const char *string); +extern _X_EXPORT void xf86ShowClocks(ScrnInfoPtr scrp, MessageType from); +extern _X_EXPORT void xf86PrintChipsets(const char *drvname, const char *drvmsg, + SymTabPtr chips); +extern _X_EXPORT int xf86MatchDevice(const char *drivername, GDevPtr **driversectlist); +extern _X_EXPORT void xf86GetClocks(ScrnInfoPtr pScrn, int num, + Bool (*ClockFunc)(ScrnInfoPtr, int), + void (*ProtectRegs)(ScrnInfoPtr, Bool), + void (*BlankScreen)(ScrnInfoPtr, Bool), + IOADDRESS vertsyncreg, int maskval, + int knownclkindex, int knownclkvalue); +extern _X_EXPORT const char *xf86GetVisualName(int visual); +extern _X_EXPORT int xf86GetVerbosity(void); +extern _X_EXPORT Pix24Flags xf86GetPix24(void); +extern _X_EXPORT int xf86GetDepth(void); +extern _X_EXPORT rgb xf86GetWeight(void); +extern _X_EXPORT Gamma xf86GetGamma(void); +extern _X_EXPORT Bool xf86GetFlipPixels(void); +extern _X_EXPORT const char *xf86GetServerName(void); +extern _X_EXPORT Bool xf86ServerIsExiting(void); +extern _X_EXPORT Bool xf86ServerIsResetting(void); +extern _X_EXPORT Bool xf86ServerIsInitialising(void); +extern _X_EXPORT Bool xf86ServerIsOnlyDetecting(void); +extern _X_EXPORT Bool xf86CaughtSignal(void); +extern _X_EXPORT Bool xf86GetVidModeAllowNonLocal(void); +extern _X_EXPORT Bool xf86GetVidModeEnabled(void); +extern _X_EXPORT Bool xf86GetModInDevAllowNonLocal(void); +extern _X_EXPORT Bool xf86GetModInDevEnabled(void); +extern _X_EXPORT Bool xf86GetAllowMouseOpenFail(void); +extern _X_EXPORT Bool xf86IsPc98(void); +extern _X_EXPORT void xf86DisableRandR(void); +extern _X_EXPORT CARD32 xorgGetVersion(void); +extern _X_EXPORT CARD32 xf86GetModuleVersion(pointer module); +extern _X_EXPORT pointer xf86LoadDrvSubModule(DriverPtr drv, const char *name); +extern _X_EXPORT pointer xf86LoadSubModule(ScrnInfoPtr pScrn, const char *name); +extern _X_EXPORT pointer xf86LoadOneModule(char *name, pointer optlist); +extern _X_EXPORT void xf86UnloadSubModule(pointer mod); +extern _X_EXPORT Bool xf86LoaderCheckSymbol(const char *name); +extern _X_EXPORT void xf86SetBackingStore(ScreenPtr pScreen); +extern _X_EXPORT void xf86SetSilkenMouse(ScreenPtr pScreen); +extern _X_EXPORT pointer xf86FindXvOptions(int scrnIndex, int adapt_index, char *port_name, + char **adaptor_name, pointer *adaptor_options); +extern _X_EXPORT void xf86GetOS(const char **name, int *major, int *minor, int *teeny); +extern _X_EXPORT ScrnInfoPtr xf86ConfigFbEntity(ScrnInfoPtr pScrn, int scrnFlag, + int entityIndex, EntityProc init, + EntityProc enter, EntityProc leave, + pointer private); + +extern _X_EXPORT Bool xf86IsScreenPrimary(int scrnIndex); +extern _X_EXPORT int xf86RegisterRootWindowProperty(int ScrnIndex, Atom property, Atom type, + int format, unsigned long len, + pointer value); +extern _X_EXPORT Bool xf86IsUnblank(int mode); + +/* xf86Init.c */ + +extern _X_EXPORT PixmapFormatPtr xf86GetPixFormat(ScrnInfoPtr pScrn, int depth); +extern _X_EXPORT int xf86GetBppFromDepth(ScrnInfoPtr pScrn, int depth); + +/* xf86Mode.c */ + +extern _X_EXPORT int xf86GetNearestClock(ScrnInfoPtr scrp, int freq, Bool allowDiv2, + int DivFactor, int MulFactor, int *divider); +extern _X_EXPORT const char *xf86ModeStatusToString(ModeStatus status); +extern _X_EXPORT ModeStatus xf86LookupMode(ScrnInfoPtr scrp, DisplayModePtr modep, + ClockRangePtr clockRanges, LookupModeFlags strategy); +extern _X_EXPORT ModeStatus xf86CheckModeForMonitor(DisplayModePtr mode, MonPtr monitor); +extern _X_EXPORT ModeStatus xf86InitialCheckModeForDriver(ScrnInfoPtr scrp, DisplayModePtr mode, + ClockRangePtr clockRanges, + LookupModeFlags strategy, + int maxPitch, int virtualX, + int virtualY); +extern _X_EXPORT ModeStatus xf86CheckModeForDriver(ScrnInfoPtr scrp, DisplayModePtr mode, + int flags); +extern _X_EXPORT int xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes, + char **modeNames, ClockRangePtr clockRanges, + int *linePitches, int minPitch, int maxPitch, + int minHeight, int maxHeight, int pitchInc, + int virtualX, int virtualY, int apertureSize, + LookupModeFlags strategy); +extern _X_EXPORT void xf86DeleteMode(DisplayModePtr *modeList, DisplayModePtr mode); +extern _X_EXPORT void xf86PruneDriverModes(ScrnInfoPtr scrp); +extern _X_EXPORT void xf86SetCrtcForModes(ScrnInfoPtr scrp, int adjustFlags); +extern _X_EXPORT void xf86PrintModes(ScrnInfoPtr scrp); +extern _X_EXPORT void xf86ShowClockRanges(ScrnInfoPtr scrp, ClockRangePtr clockRanges); +extern _X_EXPORT double xf86ModeHSync(const DisplayModeRec *mode); +extern _X_EXPORT double xf86ModeVRefresh(const DisplayModeRec *mode); +extern _X_EXPORT void xf86SetModeDefaultName(DisplayModePtr mode); +extern _X_EXPORT void xf86SetModeCrtc(DisplayModePtr p, int adjustFlags); +extern _X_EXPORT DisplayModePtr xf86DuplicateMode(const DisplayModeRec *pMode); +extern _X_EXPORT DisplayModePtr xf86DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList); +extern _X_EXPORT Bool xf86ModesEqual(const DisplayModeRec *pMode1, + const DisplayModeRec *pMode2); +extern _X_EXPORT void xf86PrintModeline(int scrnIndex,DisplayModePtr mode); +extern _X_EXPORT DisplayModePtr xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new); + +/* xf86Option.c */ + +extern _X_EXPORT void xf86CollectOptions(ScrnInfoPtr pScrn, pointer extraOpts); + + +/* xf86RandR.c */ +#ifdef RANDR +extern _X_EXPORT Bool xf86RandRInit (ScreenPtr pScreen); +extern _X_EXPORT Rotation xf86GetRotation(ScreenPtr pScreen); +extern _X_EXPORT Bool xf86RandRSetNewVirtualAndDimensions(ScreenPtr pScreen, + int newvirtX, int newvirtY, + int newmmWidth, int newmmHeight, Bool resetMode); +#endif + +/* xf86VidModeExtentionInit.c */ + +extern _X_EXPORT Bool VidModeExtensionInit(ScreenPtr pScreen); + +#endif /* _NO_XF86_PROTOTYPES */ + +#endif /* _XF86_H */ diff --git a/hw/xfree86/common/xf86AutoConfig.c b/hw/xfree86/common/xf86AutoConfig.c new file mode 100644 index 0000000..5c6e721 --- /dev/null +++ b/hw/xfree86/common/xf86AutoConfig.c @@ -0,0 +1,403 @@ +/* + * Copyright 2003 by David H. Dawes. + * Copyright 2003 by X-Oz Technologies. + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + * + * Author: David Dawes <dawes@XFree86.Org>. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "xf86.h" +#include "xf86Parser.h" +#include "xf86tokens.h" +#include "xf86Config.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" +#include "xf86pciBus.h" +#ifdef __sparc__ +# include "xf86sbusBus.h" +#endif + +#ifdef sun +# include <sys/visual_io.h> +# include <ctype.h> +#endif + +/* Sections for the default built-in configuration. */ + +#define BUILTIN_DEVICE_NAME \ + "\"Builtin Default %s Device %d\"" + +#define BUILTIN_DEVICE_SECTION_PRE \ + "Section \"Device\"\n" \ + "\tIdentifier\t" BUILTIN_DEVICE_NAME "\n" \ + "\tDriver\t\"%s\"\n" + +#define BUILTIN_DEVICE_SECTION_POST \ + "EndSection\n\n" + +#define BUILTIN_DEVICE_SECTION \ + BUILTIN_DEVICE_SECTION_PRE \ + BUILTIN_DEVICE_SECTION_POST + +#define BUILTIN_SCREEN_NAME \ + "\"Builtin Default %s Screen %d\"" + +#define BUILTIN_SCREEN_SECTION \ + "Section \"Screen\"\n" \ + "\tIdentifier\t" BUILTIN_SCREEN_NAME "\n" \ + "\tDevice\t" BUILTIN_DEVICE_NAME "\n" \ + "EndSection\n\n" + +#define BUILTIN_LAYOUT_SECTION_PRE \ + "Section \"ServerLayout\"\n" \ + "\tIdentifier\t\"Builtin Default Layout\"\n" + +#define BUILTIN_LAYOUT_SCREEN_LINE \ + "\tScreen\t" BUILTIN_SCREEN_NAME "\n" + +#define BUILTIN_LAYOUT_SECTION_POST \ + "EndSection\n\n" + +static const char **builtinConfig = NULL; +static int builtinLines = 0; + +static void listPossibleVideoDrivers(char *matches[], int nmatches); + +/* + * A built-in config file is stored as an array of strings, with each string + * representing a single line. AppendToConfig() breaks up the string "s" + * into lines, and appends those lines it to builtinConfig. + */ + +static void +AppendToList(const char *s, const char ***list, int *lines) +{ + char *str, *newstr, *p; + + str = xnfstrdup(s); + for (p = strtok(str, "\n"); p; p = strtok(NULL, "\n")) { + (*lines)++; + *list = xnfrealloc(*list, (*lines + 1) * sizeof(**list)); + newstr = xnfalloc(strlen(p) + 2); + strcpy(newstr, p); + strcat(newstr, "\n"); + (*list)[*lines - 1] = newstr; + (*list)[*lines] = NULL; + } + free(str); +} + +static void +FreeList(const char ***list, int *lines) +{ + int i; + + for (i = 0; i < *lines; i++) { + free((char *)((*list)[i])); + } + free(*list); + *list = NULL; + *lines = 0; +} + +static void +FreeConfig(void) +{ + FreeList(&builtinConfig, &builtinLines); +} + +static void +AppendToConfig(const char *s) +{ + AppendToList(s, &builtinConfig, &builtinLines); +} + +Bool +xf86AutoConfig(void) +{ + char *deviceList[20]; + char **p; + const char **cp; + char buf[1024]; + ConfigStatus ret; + + listPossibleVideoDrivers(deviceList, 20); + + for (p = deviceList; *p; p++) { + snprintf(buf, sizeof(buf), BUILTIN_DEVICE_SECTION, *p, 0, *p); + AppendToConfig(buf); + snprintf(buf, sizeof(buf), BUILTIN_SCREEN_SECTION, *p, 0, *p, 0); + AppendToConfig(buf); + } + + AppendToConfig(BUILTIN_LAYOUT_SECTION_PRE); + for (p = deviceList; *p; p++) { + snprintf(buf, sizeof(buf), BUILTIN_LAYOUT_SCREEN_LINE, *p, 0); + AppendToConfig(buf); + } + AppendToConfig(BUILTIN_LAYOUT_SECTION_POST); + + for (p = deviceList; *p; p++) { + free(*p); + } + + xf86MsgVerb(X_DEFAULT, 0, + "Using default built-in configuration (%d lines)\n", + builtinLines); + + xf86MsgVerb(X_DEFAULT, 3, "--- Start of built-in configuration ---\n"); + for (cp = builtinConfig; *cp; cp++) + xf86ErrorFVerb(3, "\t%s", *cp); + xf86MsgVerb(X_DEFAULT, 3, "--- End of built-in configuration ---\n"); + + xf86initConfigFiles(); + xf86setBuiltinConfig(builtinConfig); + ret = xf86HandleConfigFile(TRUE); + FreeConfig(); + + if (ret != CONFIG_OK) + xf86Msg(X_ERROR, "Error parsing the built-in default configuration.\n"); + + return ret == CONFIG_OK; +} + +static void +listPossibleVideoDrivers(char *matches[], int nmatches) +{ + int i; + + for (i = 0 ; i < nmatches ; i++) { + matches[i] = NULL; + } + i = 0; + +#ifdef sun + /* Check for driver type based on /dev/fb type and if valid, use + it instead of PCI bus probe results */ + if (xf86Info.consoleFd >= 0) { + struct vis_identifier visid; + const char *cp; + extern char xf86SolarisFbDev[PATH_MAX]; + int iret; + + SYSCALL(iret = ioctl(xf86Info.consoleFd, VIS_GETIDENTIFIER, &visid)); + if (iret < 0) { + int fbfd; + + fbfd = open(xf86SolarisFbDev, O_RDONLY); + if (fbfd >= 0) { + SYSCALL(iret = ioctl(fbfd, VIS_GETIDENTIFIER, &visid)); + close(fbfd); + } + } + + if (iret < 0) { + xf86Msg(X_WARNING, + "could not get frame buffer identifier from %s\n", + xf86SolarisFbDev); + } else { + xf86Msg(X_PROBED, "console driver: %s\n", visid.name); + + /* Special case from before the general case was set */ + if (strcmp(visid.name, "NVDAnvda") == 0) { + matches[i++] = xnfstrdup("nvidia"); + } + + /* General case - split into vendor name (initial all-caps + prefix) & driver name (rest of the string). */ + if (strcmp(visid.name, "SUNWtext") != 0) { + for (cp = visid.name; (*cp != '\0') && isupper(*cp); cp++) { + /* find end of all uppercase vendor section */ + } + if ((cp != visid.name) && (*cp != '\0')) { + char *driverName = xnfstrdup(cp); + char *vendorName = xnfstrdup(visid.name); + vendorName[cp - visid.name] = '\0'; + + matches[i++] = vendorName; + matches[i++] = driverName; + } + } + } + } +#endif +#ifdef __sparc__ + { + char *sbusDriver = sparcDriverName(); + if (sbusDriver) + matches[i++] = xnfstrdup(sbusDriver); + } +#endif + + i = xf86PciMatchDriver(matches, nmatches); + + /* Fallback to platform default hardware */ + if (i < (nmatches - 1)) { +#if defined(__i386__) || defined(__amd64__) || defined(__hurd__) + matches[i++] = xnfstrdup("vesa"); +#elif defined(__sparc__) && !defined(sun) + matches[i++] = xnfstrdup("sunffb"); +#endif + } + + /* Fallback to platform default frame buffer driver */ + if (i < (nmatches - 1)) { +#if !defined(__linux__) && defined(__sparc__) + matches[i++] = xnfstrdup("wsfb"); +#else + matches[i++] = xnfstrdup("fbdev"); +#endif + } +} + +/* copy a screen section and enter the desired driver + * and insert it at i in the list of screens */ +static Bool +copyScreen(confScreenPtr oscreen, GDevPtr odev, int i, char *driver) +{ + confScreenPtr nscreen; + GDevPtr cptr = NULL; + + nscreen = malloc(sizeof(confScreenRec)); + if (!nscreen) + return FALSE; + memcpy(nscreen, oscreen, sizeof(confScreenRec)); + + cptr = malloc(sizeof(GDevRec)); + if (!cptr) { + free(nscreen); + return FALSE; + } + memcpy(cptr, odev, sizeof(GDevRec)); + + if (asprintf(&cptr->identifier, "Autoconfigured Video Device %s", driver) + == -1) { + free(cptr); + free(nscreen); + return FALSE; + } + cptr->driver = driver; + + xf86ConfigLayout.screens[i].screen = nscreen; + + /* now associate the new driver entry with the new screen entry */ + xf86ConfigLayout.screens[i].screen->device = cptr; + cptr->myScreenSection = xf86ConfigLayout.screens[i].screen; + + return TRUE; +} + +GDevPtr +autoConfigDevice(GDevPtr preconf_device) +{ + GDevPtr ptr = NULL; + char *matches[20]; /* If we have more than 20 drivers we're in trouble */ + int num_matches = 0, num_screens = 0, i; + screenLayoutPtr slp; + + if (!xf86configptr) { + return NULL; + } + + /* If there's a configured section with no driver chosen, use it */ + if (preconf_device) { + ptr = preconf_device; + } else { + ptr = calloc(1, sizeof(GDevRec)); + if (!ptr) { + return NULL; + } + ptr->chipID = -1; + ptr->chipRev = -1; + ptr->irq = -1; + + ptr->active = TRUE; + ptr->claimed = FALSE; + ptr->identifier = "Autoconfigured Video Device"; + ptr->driver = NULL; + } + if (!ptr->driver) { + /* get all possible video drivers and count them */ + listPossibleVideoDrivers(matches, 20); + for (; matches[num_matches]; num_matches++) { + xf86Msg(X_DEFAULT, "Matched %s as autoconfigured driver %d\n", + matches[num_matches], num_matches); + } + + slp = xf86ConfigLayout.screens; + if (slp) { + /* count the number of screens and make space for + * a new screen for each additional possible driver + * minus one for the already existing first one + * plus one for the terminating NULL */ + for (; slp[num_screens].screen; num_screens++); + xf86ConfigLayout.screens = xnfcalloc(num_screens + num_matches, + sizeof(screenLayoutRec)); + xf86ConfigLayout.screens[0] = slp[0]; + + /* do the first match and set that for the original first screen */ + ptr->driver = matches[0]; + if (!xf86ConfigLayout.screens[0].screen->device) { + xf86ConfigLayout.screens[0].screen->device = ptr; + ptr->myScreenSection = xf86ConfigLayout.screens[0].screen; + } + + /* for each other driver found, copy the first screen, insert it + * into the list of screens and set the driver */ + i = 0; + while (i++ < num_matches) { + if (!copyScreen(slp[0].screen, ptr, i, matches[i])) + return NULL; + } + + /* shift the rest of the original screen list + * to the end of the current screen list + * + * TODO Handle rest of multiple screen sections */ + for (i = 1; i < num_screens; i++) { + xf86ConfigLayout.screens[i+num_matches] = slp[i]; + } + xf86ConfigLayout.screens[num_screens+num_matches-1].screen = NULL; + free(slp); + } else { + /* layout does not have any screens, not much to do */ + ptr->driver = matches[0]; + for (i = 1; matches[i] ; i++) { + if (matches[i] != matches[0]) { + free(matches[i]); + } + } + } + } + + xf86Msg(X_DEFAULT, "Assigned the driver to the xf86ConfigLayout\n"); + + return ptr; +} diff --git a/hw/xfree86/common/xf86Build.h.in b/hw/xfree86/common/xf86Build.h.in new file mode 100644 index 0000000..a4f56b0 --- /dev/null +++ b/hw/xfree86/common/xf86Build.h.in @@ -0,0 +1,2 @@ +#define BUILD_DATE @BUILD_DATE@ +#define BUILD_TIME @BUILD_TIME@ diff --git a/hw/xfree86/common/xf86Bus.c b/hw/xfree86/common/xf86Bus.c new file mode 100644 index 0000000..3b08968 --- /dev/null +++ b/hw/xfree86/common/xf86Bus.c @@ -0,0 +1,636 @@ +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * This file contains the interfaces to the bus-specific code + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <ctype.h> +#include <stdlib.h> +#include <unistd.h> +#include <X11/X.h> +#include "os.h" +#include "xf86.h" +#include "xf86Priv.h" + +/* Bus-specific headers */ + +#include "xf86Bus.h" + +#define XF86_OS_PRIVS +#include "xf86_OSproc.h" +#include "xf86VGAarbiter.h" + +/* Entity data */ +EntityPtr *xf86Entities = NULL; /* Bus slots claimed by drivers */ +int xf86NumEntities = 0; +static int xf86EntityPrivateCount = 0; + +BusRec primaryBus = { BUS_NONE, { 0 } }; + +/** + * Call the driver's correct probe function. + * + * If the driver implements the \c DriverRec::PciProbe entry-point and an + * appropriate PCI device (with matching Device section in the xorg.conf file) + * is found, it is called. If \c DriverRec::PciProbe or no devices can be + * successfully probed with it (e.g., only non-PCI devices are available), + * the driver's \c DriverRec::Probe function is called. + * + * \param drv Driver to probe + * + * \return + * If a device can be successfully probed by the driver, \c TRUE is + * returned. Otherwise, \c FALSE is returned. + */ +Bool +xf86CallDriverProbe( DriverPtr drv, Bool detect_only ) +{ + Bool foundScreen = FALSE; + + if (drv->PciProbe != NULL) { + if (xf86DoConfigure && xf86DoConfigurePass1) { + assert(detect_only); + foundScreen = xf86PciAddMatchingDev(drv); + } + else { + assert(! detect_only); + foundScreen = xf86PciProbeDev(drv); + } + } + + if (!foundScreen && (drv->Probe != NULL)) { + xf86Msg( X_WARNING, "Falling back to old probe method for %s\n", + drv->driverName); + foundScreen = (*drv->Probe)(drv, (detect_only) ? PROBE_DETECT + : PROBE_DEFAULT); + } + + return foundScreen; +} + +/** + * @return TRUE if all buses are configured and set up correctly and FALSE + * otherwise. + */ +Bool +xf86BusConfig(void) +{ + screenLayoutPtr layout; + int i, j; + + /* Enable full I/O access */ + if (xorgHWAccess) + xorgHWAccess = xf86EnableIO(); + + /* + * Now call each of the Probe functions. Each successful probe will + * result in an extra entry added to the xf86Screens[] list for each + * instance of the hardware found. + */ + for (i = 0; i < xf86NumDrivers; i++) { + xorgHWFlags flags; + if (!xorgHWAccess) { + if (!xf86DriverList[i]->driverFunc + || !xf86DriverList[i]->driverFunc(NULL, + GET_REQUIRED_HW_INTERFACES, + &flags) + || NEED_IO_ENABLED(flags)) + continue; + } + + xf86CallDriverProbe(xf86DriverList[i], FALSE); + } + + /* If nothing was detected, return now */ + if (xf86NumScreens == 0) { + xf86Msg(X_ERROR, "No devices detected.\n"); + return FALSE; + } + + xf86VGAarbiterInit(); + + /* + * Match up the screens found by the probes against those specified + * in the config file. Remove the ones that won't be used. Sort + * them in the order specified. + * + * What is the best way to do this? + * + * For now, go through the screens allocated by the probes, and + * look for screen config entry which refers to the same device + * section as picked out by the probe. + * + */ + for (i = 0; i < xf86NumScreens; i++) { + for (layout = xf86ConfigLayout.screens; layout->screen != NULL; + layout++) { + Bool found = FALSE; + for (j = 0; j < xf86Screens[i]->numEntities; j++) { + + GDevPtr dev = xf86GetDevFromEntity( + xf86Screens[i]->entityList[j], + xf86Screens[i]->entityInstanceList[j]); + if (dev == layout->screen->device) { + /* A match has been found */ + xf86Screens[i]->confScreen = layout->screen; + found = TRUE; + break; + } + } + if (found) break; + } + if (layout->screen == NULL) { + /* No match found */ + xf86Msg(X_ERROR, + "Screen %d deleted because of no matching config section.\n", i); + xf86DeleteScreen(i--, 0); + } + } + + /* If no screens left, return now. */ + if (xf86NumScreens == 0) { + xf86Msg(X_ERROR, + "Device(s) detected, but none match those in the config file.\n"); + return FALSE; + } + + return TRUE; +} + +/* + * Call the bus probes relevant to the architecture. + * + * The only one available so far is for PCI and SBUS. + */ + +void +xf86BusProbe(void) +{ + xf86PciProbe(); +#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) + xf86SbusProbe(); +#endif +} + +/* + * Determine what bus type the busID string represents. The start of the + * bus-dependent part of the string is returned as retID. + */ + +BusType +StringToBusType(const char* busID, const char **retID) +{ + char *p, *s; + BusType ret = BUS_NONE; + + /* If no type field, Default to PCI */ + if (isdigit(busID[0])) { + if (retID) + *retID = busID; + return BUS_PCI; + } + + s = xstrdup(busID); + p = strtok(s, ":"); + if (p == NULL || *p == 0) { + free(s); + return BUS_NONE; + } + if (!xf86NameCmp(p, "pci") || !xf86NameCmp(p, "agp")) + ret = BUS_PCI; + if (!xf86NameCmp(p, "sbus")) + ret = BUS_SBUS; + if (ret != BUS_NONE) + if (retID) + *retID = busID + strlen(p) + 1; + free(s); + return ret; +} + +int +xf86AllocateEntity(void) +{ + xf86NumEntities++; + xf86Entities = xnfrealloc(xf86Entities, + sizeof(EntityPtr) * xf86NumEntities); + xf86Entities[xf86NumEntities - 1] = xnfcalloc(1,sizeof(EntityRec)); + xf86Entities[xf86NumEntities - 1]->entityPrivates = + xnfcalloc(sizeof(DevUnion) * xf86EntityPrivateCount, 1); + return xf86NumEntities - 1; +} + +Bool +xf86IsEntityPrimary(int entityIndex) +{ + EntityPtr pEnt = xf86Entities[entityIndex]; + + if (primaryBus.type != pEnt->bus.type) return FALSE; + + switch (pEnt->bus.type) { + case BUS_PCI: + return pEnt->bus.id.pci == primaryBus.id.pci; + case BUS_SBUS: + return pEnt->bus.id.sbus.fbNum == primaryBus.id.sbus.fbNum; + default: + return FALSE; + } +} + +Bool +xf86SetEntityFuncs(int entityIndex, EntityProc init, EntityProc enter, + EntityProc leave, pointer private) +{ + if (entityIndex >= xf86NumEntities) + return FALSE; + xf86Entities[entityIndex]->entityInit = init; + xf86Entities[entityIndex]->entityEnter = enter; + xf86Entities[entityIndex]->entityLeave = leave; + xf86Entities[entityIndex]->private = private; + return TRUE; +} + +Bool +xf86DriverHasEntities(DriverPtr drvp) +{ + int i; + for (i = 0; i < xf86NumEntities; i++) { + if (xf86Entities[i]->driver == drvp) + return TRUE; + } + return FALSE; +} + +void +xf86AddEntityToScreen(ScrnInfoPtr pScrn, int entityIndex) +{ + if (entityIndex == -1) + return; + if (xf86Entities[entityIndex]->inUse && + !(xf86Entities[entityIndex]->entityProp & IS_SHARED_ACCEL)) { + ErrorF("Requested Entity already in use!\n"); + return; + } + + pScrn->numEntities++; + pScrn->entityList = xnfrealloc(pScrn->entityList, + pScrn->numEntities * sizeof(int)); + pScrn->entityList[pScrn->numEntities - 1] = entityIndex; + xf86Entities[entityIndex]->inUse = TRUE; + pScrn->entityInstanceList = xnfrealloc(pScrn->entityInstanceList, + pScrn->numEntities * sizeof(int)); + pScrn->entityInstanceList[pScrn->numEntities - 1] = 0; + pScrn->domainIOBase = xf86Entities[entityIndex]->domainIO; +} + +void +xf86SetEntityInstanceForScreen(ScrnInfoPtr pScrn, int entityIndex, int instance) +{ + int i; + + if (entityIndex == -1 || entityIndex >= xf86NumEntities) + return; + + for (i = 0; i < pScrn->numEntities; i++) { + if (pScrn->entityList[i] == entityIndex) { + pScrn->entityInstanceList[i] = instance; + break; + } + } +} + +/* + * XXX This needs to be updated for the case where a single entity may have + * instances associated with more than one screen. + */ +ScrnInfoPtr +xf86FindScreenForEntity(int entityIndex) +{ + int i,j; + + if (entityIndex == -1) return NULL; + + if (xf86Screens) { + for (i = 0; i < xf86NumScreens; i++) { + for (j = 0; j < xf86Screens[i]->numEntities; j++) { + if ( xf86Screens[i]->entityList[j] == entityIndex ) + return xf86Screens[i]; + } + } + } + return NULL; +} + +void +xf86RemoveEntityFromScreen(ScrnInfoPtr pScrn, int entityIndex) +{ + int i; + + for (i = 0; i < pScrn->numEntities; i++) { + if (pScrn->entityList[i] == entityIndex) { + for (i++; i < pScrn->numEntities; i++) + pScrn->entityList[i-1] = pScrn->entityList[i]; + pScrn->numEntities--; + xf86Entities[entityIndex]->inUse = FALSE; + break; + } + } +} + +/* + * xf86ClearEntitiesForScreen() - called when a screen is deleted + * to mark it's entities unused. Called by xf86DeleteScreen(). + */ +void +xf86ClearEntityListForScreen(int scrnIndex) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + int i, entityIndex; + + if (pScrn->entityList == NULL || pScrn->numEntities == 0) return; + + for (i = 0; i < pScrn->numEntities; i++) { + entityIndex = pScrn->entityList[i]; + xf86Entities[entityIndex]->inUse = FALSE; + /* disable resource: call the disable function */ + } + free(pScrn->entityList); + free(pScrn->entityInstanceList); + pScrn->entityList = NULL; + pScrn->entityInstanceList = NULL; +} + +/* + * Add an extra device section (GDevPtr) to an entity. + */ + +void +xf86AddDevToEntity(int entityIndex, GDevPtr dev) +{ + EntityPtr pEnt; + + if (entityIndex >= xf86NumEntities) + return; + + pEnt = xf86Entities[entityIndex]; + pEnt->numInstances++; + pEnt->devices = xnfrealloc(pEnt->devices, + pEnt->numInstances * sizeof(GDevPtr)); + pEnt->devices[pEnt->numInstances - 1] = dev; + dev->claimed = TRUE; +} + +/* + * xf86GetEntityInfo() -- This function hands information from the + * EntityRec struct to the drivers. The EntityRec structure itself + * remains invisible to the driver. + */ +EntityInfoPtr +xf86GetEntityInfo(int entityIndex) +{ + EntityInfoPtr pEnt; + int i; + + if (entityIndex == -1) + return NULL; + + if (entityIndex >= xf86NumEntities) + return NULL; + + pEnt = xnfcalloc(1,sizeof(EntityInfoRec)); + pEnt->index = entityIndex; + pEnt->location = xf86Entities[entityIndex]->bus; + pEnt->active = xf86Entities[entityIndex]->active; + pEnt->chipset = xf86Entities[entityIndex]->chipset; + pEnt->driver = xf86Entities[entityIndex]->driver; + if ( (xf86Entities[entityIndex]->devices) && + (xf86Entities[entityIndex]->devices[0]) ) { + for (i = 0; i < xf86Entities[entityIndex]->numInstances; i++) + if (xf86Entities[entityIndex]->devices[i]->screen == 0) + break; + pEnt->device = xf86Entities[entityIndex]->devices[i]; + } else + pEnt->device = NULL; + + return pEnt; +} + +int +xf86GetNumEntityInstances(int entityIndex) +{ + if (entityIndex >= xf86NumEntities) + return -1; + + return xf86Entities[entityIndex]->numInstances; +} + +GDevPtr +xf86GetDevFromEntity(int entityIndex, int instance) +{ + int i; + + /* We might not use AddDevtoEntity */ + if ( (!xf86Entities[entityIndex]->devices) || + (!xf86Entities[entityIndex]->devices[0]) ) + return NULL; + + if (entityIndex >= xf86NumEntities || + instance >= xf86Entities[entityIndex]->numInstances) + return NULL; + + for (i = 0; i < xf86Entities[entityIndex]->numInstances; i++) + if (xf86Entities[entityIndex]->devices[i]->screen == instance) + break; + return xf86Entities[entityIndex]->devices[i]; +} + +/* + * xf86AccessEnter() -- gets called to save the text mode VGA IO + * resources when reentering the server after a VT switch. + */ +void +xf86AccessEnter(void) +{ + int i; + + for (i = 0; i < xf86NumEntities; i++) + if (xf86Entities[i]->entityEnter) + xf86Entities[i]->entityEnter(i,xf86Entities[i]->private); +} + +void +xf86AccessLeave(void) +{ + int i; + + for (i = 0; i < xf86NumEntities; i++) + if (xf86Entities[i]->entityLeave) + xf86Entities[i]->entityLeave(i,xf86Entities[i]->private); +} + +/* + * xf86PostProbe() -- Allocate all non conflicting resources + * This function gets called by xf86Init(). + */ +void +xf86PostProbe(void) +{ + int i; + + if (fbSlotClaimed && (pciSlotClaimed +#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) + || sbusSlotClaimed +#endif + )) + FatalError("Cannot run in framebuffer mode. Please specify busIDs " + " for all framebuffer devices\n"); + + for (i = 0; i < xf86NumEntities; i++) + if (xf86Entities[i]->entityInit) + xf86Entities[i]->entityInit(i,xf86Entities[i]->private); +} + +int +xf86GetLastScrnFlag(int entityIndex) +{ + if(entityIndex < xf86NumEntities) { + return xf86Entities[entityIndex]->lastScrnFlag; + } else { + return -1; + } +} + +void +xf86SetLastScrnFlag(int entityIndex, int scrnIndex) +{ + if(entityIndex < xf86NumEntities) { + xf86Entities[entityIndex]->lastScrnFlag = scrnIndex; + } +} + +Bool +xf86IsEntityShared(int entityIndex) +{ + if(entityIndex < xf86NumEntities) { + if(xf86Entities[entityIndex]->entityProp & IS_SHARED_ACCEL) { + return TRUE; + } + } + return FALSE; +} + +void +xf86SetEntityShared(int entityIndex) +{ + if(entityIndex < xf86NumEntities) { + xf86Entities[entityIndex]->entityProp |= IS_SHARED_ACCEL; + } +} + +Bool +xf86IsEntitySharable(int entityIndex) +{ + if(entityIndex < xf86NumEntities) { + if(xf86Entities[entityIndex]->entityProp & ACCEL_IS_SHARABLE) { + return TRUE; + } + } + return FALSE; +} + +void +xf86SetEntitySharable(int entityIndex) +{ + if(entityIndex < xf86NumEntities) { + xf86Entities[entityIndex]->entityProp |= ACCEL_IS_SHARABLE; + } +} + +Bool +xf86IsPrimInitDone(int entityIndex) +{ + if(entityIndex < xf86NumEntities) { + if(xf86Entities[entityIndex]->entityProp & SA_PRIM_INIT_DONE) { + return TRUE; + } + } + return FALSE; +} + +void +xf86SetPrimInitDone(int entityIndex) +{ + if(entityIndex < xf86NumEntities) { + xf86Entities[entityIndex]->entityProp |= SA_PRIM_INIT_DONE; + } +} + +void +xf86ClearPrimInitDone(int entityIndex) +{ + if(entityIndex < xf86NumEntities) { + xf86Entities[entityIndex]->entityProp &= ~SA_PRIM_INIT_DONE; + } +} + + +/* + * Allocate a private in the entities. + */ + +int +xf86AllocateEntityPrivateIndex(void) +{ + int idx, i; + EntityPtr pEnt; + DevUnion *nprivs; + + idx = xf86EntityPrivateCount++; + for (i = 0; i < xf86NumEntities; i++) { + pEnt = xf86Entities[i]; + nprivs = xnfrealloc(pEnt->entityPrivates, + xf86EntityPrivateCount * sizeof(DevUnion)); + /* Zero the new private */ + memset(&nprivs[idx], 0, sizeof(DevUnion)); + pEnt->entityPrivates = nprivs; + } + return idx; +} + +DevUnion * +xf86GetEntityPrivate(int entityIndex, int privIndex) +{ + if (entityIndex >= xf86NumEntities || privIndex >= xf86EntityPrivateCount) + return NULL; + + return &(xf86Entities[entityIndex]->entityPrivates[privIndex]); +} + diff --git a/hw/xfree86/common/xf86Bus.h b/hw/xfree86/common/xf86Bus.h new file mode 100644 index 0000000..e161c7f --- /dev/null +++ b/hw/xfree86/common/xf86Bus.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * This file contains definitions of the bus-related data structures/types. + * Everything contained here is private to xf86Bus.c. In particular the + * video drivers must not include this file. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#ifndef _XF86_BUS_H +#define _XF86_BUS_H + +#include "xf86pciBus.h" +#if defined(__sparc__) || defined(__sparc) +#include "xf86sbusBus.h" +#endif + +typedef struct { + DriverPtr driver; + int chipset; + int entityProp; + EntityProc entityInit; + EntityProc entityEnter; + EntityProc entityLeave; + pointer private; + Bool active; + Bool inUse; + BusRec bus; + int lastScrnFlag; + DevUnion * entityPrivates; + int numInstances; + GDevPtr * devices; + IOADDRESS domainIO; +} EntityRec, *EntityPtr; + +#define ACCEL_IS_SHARABLE 0x100 +#define IS_SHARED_ACCEL 0x200 +#define SA_PRIM_INIT_DONE 0x400 + +extern EntityPtr *xf86Entities; +extern int xf86NumEntities; +extern BusRec primaryBus; + +int xf86AllocateEntity(void); +BusType StringToBusType(const char* busID, const char **retID); + +#endif /* _XF86_BUS_H */ diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c new file mode 100644 index 0000000..114bdc3 --- /dev/null +++ b/hw/xfree86/common/xf86Config.c @@ -0,0 +1,2531 @@ +/* + * Loosely based on code bearing the following copyright: + * + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + */ + +/* + * Copyright 1992-2003 by The XFree86 Project, Inc. + * Copyright 1997 by Metro Link, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * + * Authors: + * Dirk Hohndel <hohndel@XFree86.Org> + * David Dawes <dawes@XFree86.Org> + * Marc La France <tsi@XFree86.Org> + * Egbert Eich <eich@XFree86.Org> + * ... and others + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#ifdef XF86DRI +#include <sys/types.h> +#include <grp.h> +#endif + +#include "xf86.h" +#include "xf86Parser.h" +#include "xf86tokens.h" +#include "xf86Config.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" +#include "configProcs.h" +#include "globals.h" +#include "extension.h" +#include "xf86pciBus.h" + +#include "xf86Xinput.h" + +#include "xkbsrv.h" + +#include "picture.h" + +/* + * These paths define the way the config file search is done. The escape + * sequences are documented in parser/scan.c. + */ +#ifndef ROOT_CONFIGPATH +#define ROOT_CONFIGPATH "%A," "%R," \ + "/etc/X11/%R," "%P/etc/X11/%R," \ + "%E," "%F," \ + "/etc/X11/%F," "%P/etc/X11/%F," \ + "/etc/X11/%X," "/etc/%X," \ + "%P/etc/X11/%X.%H," \ + "%P/etc/X11/%X," \ + "%P/lib/X11/%X.%H," \ + "%P/lib/X11/%X" +#endif +#ifndef USER_CONFIGPATH +#define USER_CONFIGPATH "/etc/X11/%S," "%P/etc/X11/%S," \ + "/etc/X11/%G," "%P/etc/X11/%G," \ + "/etc/X11/%X," "/etc/%X," \ + "%P/etc/X11/%X.%H," \ + "%P/etc/X11/%X," \ + "%P/lib/X11/%X.%H," \ + "%P/lib/X11/%X" +#endif +#ifndef ROOT_CONFIGDIRPATH +#define ROOT_CONFIGDIRPATH "%A," "%R," \ + "/etc/X11/%R," "%C/X11/%R," \ + "/etc/X11/%X," "%C/X11/%X" +#endif +#ifndef USER_CONFIGDIRPATH +#define USER_CONFIGDIRPATH "/etc/X11/%R," "%C/X11/%R," \ + "/etc/X11/%X," "%C/X11/%X" +#endif +#ifndef SYS_CONFIGDIRPATH +#define SYS_CONFIGDIRPATH "/usr/share/X11/%X," "%D/X11/%X" +#endif +#ifndef PROJECTROOT +#define PROJECTROOT "/usr/X11R6" +#endif + +static ModuleDefault ModuleDefaults[] = { + {.name = "extmod", .toLoad = TRUE, .load_opt=NULL}, +#ifdef DBE + {.name = "dbe", .toLoad = TRUE, .load_opt=NULL}, +#endif +#ifdef GLXEXT + {.name = "glx", .toLoad = TRUE, .load_opt=NULL}, +#endif +#ifdef XRECORD + {.name = "record", .toLoad = TRUE, .load_opt=NULL}, +#endif +#ifdef XF86DRI + {.name = "dri", .toLoad = TRUE, .load_opt=NULL}, +#endif +#ifdef DRI2 + {.name = "dri2", .toLoad = TRUE, .load_opt=NULL}, +#endif + {.name = NULL, .toLoad = FALSE, .load_opt=NULL} +}; + + +/* Forward declarations */ +static Bool configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen, + int scrnum, MessageType from); +static Bool configMonitor(MonPtr monitorp, XF86ConfMonitorPtr conf_monitor); +static Bool configDevice(GDevPtr devicep, XF86ConfDevicePtr conf_device, + Bool active); +static Bool configInput(InputInfoPtr pInfo, XF86ConfInputPtr conf_input, + MessageType from); +static Bool configDisplay(DispPtr displayp, XF86ConfDisplayPtr conf_display); +static Bool addDefaultModes(MonPtr monitorp); +#ifdef XF86DRI +static void configDRI(XF86ConfDRIPtr drip); +#endif +static void configExtensions(XF86ConfExtensionsPtr conf_ext); + +/* + * xf86GetPathElem -- + * Extract a single element from the font path string starting at + * pnt. The font path element will be returned, and pnt will be + * updated to point to the start of the next element, or set to + * NULL if there are no more. + */ +static char * +xf86GetPathElem(char **pnt) +{ + char *p1; + + p1 = *pnt; + *pnt = index(*pnt, ','); + if (*pnt != NULL) { + **pnt = '\0'; + *pnt += 1; + } + return p1; +} + +/* + * xf86ValidateFontPath -- + * Validates the user-specified font path. Each element that + * begins with a '/' is checked to make sure the directory exists. + * If the directory exists, the existence of a file named 'fonts.dir' + * is checked. If either check fails, an error is printed and the + * element is removed from the font path. + */ + +#define DIR_FILE "/fonts.dir" +static char * +xf86ValidateFontPath(char *path) +{ + char *tmp_path, *out_pnt, *path_elem, *next, *p1, *dir_elem; + struct stat stat_buf; + int flag; + int dirlen; + + tmp_path = calloc(1,strlen(path)+1); + out_pnt = tmp_path; + path_elem = NULL; + next = path; + while (next != NULL) { + path_elem = xf86GetPathElem(&next); + if (*path_elem == '/') { + dir_elem = xnfcalloc(1, strlen(path_elem) + 1); + if ((p1 = strchr(path_elem, ':')) != 0) + dirlen = p1 - path_elem; + else + dirlen = strlen(path_elem); + strncpy(dir_elem, path_elem, dirlen); + dir_elem[dirlen] = '\0'; + flag = stat(dir_elem, &stat_buf); + if (flag == 0) + if (!S_ISDIR(stat_buf.st_mode)) + flag = -1; + if (flag != 0) { + xf86Msg(X_WARNING, "The directory \"%s\" does not exist.\n", dir_elem); + xf86ErrorF("\tEntry deleted from font path.\n"); + free(dir_elem); + continue; + } + else { + XNFasprintf(&p1, "%s%s", dir_elem, DIR_FILE); + flag = stat(p1, &stat_buf); + if (flag == 0) + if (!S_ISREG(stat_buf.st_mode)) + flag = -1; + free(p1); + if (flag != 0) { + xf86Msg(X_WARNING, + "`fonts.dir' not found (or not valid) in \"%s\".\n", + dir_elem); + xf86ErrorF("\tEntry deleted from font path.\n"); + xf86ErrorF("\t(Run 'mkfontdir' on \"%s\").\n", dir_elem); + free(dir_elem); + continue; + } + } + free(dir_elem); + } + + /* + * Either an OK directory, or a font server name. So add it to + * the path. + */ + if (out_pnt != tmp_path) + *out_pnt++ = ','; + strcat(out_pnt, path_elem); + out_pnt += strlen(path_elem); + } + return tmp_path; +} + + +/* + * use the datastructure that the parser provides and pick out the parts + * that we need at this point + */ +char ** +xf86ModulelistFromConfig(pointer **optlist) +{ + int count = 0, i = 0; + char **modulearray; + char *ignore[] = { "GLcore", "speedo", "bitmap", "drm", + "freetype", "type1", + NULL }; + pointer *optarray; + XF86LoadPtr modp; + Bool found; + + /* + * make sure the config file has been parsed and that we have a + * ModulePath set; if no ModulePath was given, use the default + * ModulePath + */ + if (xf86configptr == NULL) { + xf86Msg(X_ERROR, "Cannot access global config data structure\n"); + return NULL; + } + + if (xf86configptr->conf_modules) { + /* Walk the disable list and let people know what we've parsed to + * not be loaded + */ + modp = xf86configptr->conf_modules->mod_disable_lst; + while (modp) { + xf86Msg(X_WARNING, "\"%s\" will not be loaded unless you've specified it to be loaded elsewhere.\n", modp->load_name); + modp = (XF86LoadPtr) modp->list.next; + } + /* + * Walk the default settings table. For each module listed to be + * loaded, make sure it's in the mod_load_lst. If it's not, make + * sure it's not in the mod_no_load_lst. If it's not disabled, + * append it to mod_load_lst + */ + for (i=0 ; ModuleDefaults[i].name != NULL ; i++) { + if (ModuleDefaults[i].toLoad == FALSE) { + xf86Msg(X_WARNING, "\"%s\" is not to be loaded by default. Skipping.\n", ModuleDefaults[i].name); + continue; + } + found = FALSE; + modp = xf86configptr->conf_modules->mod_load_lst; + while (modp) { + if (strcmp(modp->load_name, ModuleDefaults[i].name) == 0) { + xf86Msg(X_INFO, "\"%s\" will be loaded. This was enabled by default and also specified in the config file.\n", ModuleDefaults[i].name); + found = TRUE; + break; + } + modp = (XF86LoadPtr) modp->list.next; + } + if (found == FALSE) { + modp = xf86configptr->conf_modules->mod_disable_lst; + while (modp) { + if (strcmp(modp->load_name, ModuleDefaults[i].name) == 0) { + xf86Msg(X_INFO, "\"%s\" will be loaded even though the default is to disable it.\n", ModuleDefaults[i].name); + found = TRUE; + break; + } + modp = (XF86LoadPtr) modp->list.next; + } + } + if (found == FALSE) { + XF86LoadPtr ptr = (XF86LoadPtr)xf86configptr->conf_modules; + xf86addNewLoadDirective(ptr, ModuleDefaults[i].name, XF86_LOAD_MODULE, ModuleDefaults[i].load_opt); + xf86Msg(X_INFO, "\"%s\" will be loaded by default.\n", ModuleDefaults[i].name); + } + } + } else { + xf86configptr->conf_modules = xnfcalloc(1, sizeof(XF86ConfModuleRec)); + for (i=0 ; ModuleDefaults[i].name != NULL ; i++) { + if (ModuleDefaults[i].toLoad == TRUE) { + XF86LoadPtr ptr = (XF86LoadPtr)xf86configptr->conf_modules; + xf86addNewLoadDirective(ptr, ModuleDefaults[i].name, XF86_LOAD_MODULE, ModuleDefaults[i].load_opt); + } + } + } + + /* + * Walk the list of modules in the "Module" section to determine how + * many we have. + */ + modp = xf86configptr->conf_modules->mod_load_lst; + while (modp) { + for (i = 0; ignore[i]; i++) { + if (strcmp(modp->load_name, ignore[i]) == 0) + modp->ignore = 1; + } + if (!modp->ignore) + count++; + modp = (XF86LoadPtr) modp->list.next; + } + + /* + * allocate the memory and walk the list again to fill in the pointers + */ + modulearray = xnfalloc((count + 1) * sizeof(char*)); + optarray = xnfalloc((count + 1) * sizeof(pointer)); + count = 0; + if (xf86configptr->conf_modules) { + modp = xf86configptr->conf_modules->mod_load_lst; + while (modp) { + if (!modp->ignore) { + modulearray[count] = modp->load_name; + optarray[count] = modp->load_opt; + count++; + } + modp = (XF86LoadPtr) modp->list.next; + } + } + modulearray[count] = NULL; + optarray[count] = NULL; + if (optlist) + *optlist = optarray; + else + free(optarray); + return modulearray; +} + + +char ** +xf86DriverlistFromConfig(void) +{ + int count = 0; + int j; + char **modulearray; + screenLayoutPtr slp; + + /* + * make sure the config file has been parsed and that we have a + * ModulePath set; if no ModulePath was given, use the default + * ModulePath + */ + if (xf86configptr == NULL) { + xf86Msg(X_ERROR, "Cannot access global config data structure\n"); + return NULL; + } + + /* + * Walk the list of driver lines in active "Device" sections to + * determine now many implicitly loaded modules there are. + * + */ + if (xf86ConfigLayout.screens) { + slp = xf86ConfigLayout.screens; + while ((slp++)->screen) { + count++; + } + } + + /* + * Handle the set of inactive "Device" sections. + */ + j = 0; + while (xf86ConfigLayout.inactives[j++].identifier) + count++; + + if (count == 0) + return NULL; + + /* + * allocate the memory and walk the list again to fill in the pointers + */ + modulearray = xnfalloc((count + 1) * sizeof(char*)); + count = 0; + slp = xf86ConfigLayout.screens; + while (slp->screen) { + modulearray[count] = slp->screen->device->driver; + count++; + slp++; + } + + j = 0; + + while (xf86ConfigLayout.inactives[j].identifier) + modulearray[count++] = xf86ConfigLayout.inactives[j++].driver; + + modulearray[count] = NULL; + + /* Remove duplicates */ + for (count = 0; modulearray[count] != NULL; count++) { + int i; + + for (i = 0; i < count; i++) + if (xf86NameCmp(modulearray[i], modulearray[count]) == 0) { + modulearray[count] = ""; + break; + } + } + return modulearray; +} + +char ** +xf86InputDriverlistFromConfig(void) +{ + int count = 0; + char **modulearray; + InputInfoPtr *idp; + + /* + * make sure the config file has been parsed and that we have a + * ModulePath set; if no ModulePath was given, use the default + * ModulePath + */ + if (xf86configptr == NULL) { + xf86Msg(X_ERROR, "Cannot access global config data structure\n"); + return NULL; + } + + /* + * Walk the list of driver lines in active "InputDevice" sections to + * determine now many implicitly loaded modules there are. + */ + if (xf86ConfigLayout.inputs) { + idp = xf86ConfigLayout.inputs; + while (*idp) { + count++; + idp++; + } + } + + if (count == 0) + return NULL; + + /* + * allocate the memory and walk the list again to fill in the pointers + */ + modulearray = xnfalloc((count + 1) * sizeof(char*)); + count = 0; + idp = xf86ConfigLayout.inputs; + while (idp && *idp) { + modulearray[count] = (*idp)->driver; + count++; + idp++; + } + modulearray[count] = NULL; + + /* Remove duplicates */ + for (count = 0; modulearray[count] != NULL; count++) { + int i; + + for (i = 0; i < count; i++) + if (xf86NameCmp(modulearray[i], modulearray[count]) == 0) { + modulearray[count] = ""; + break; + } + } + return modulearray; +} + +static void +fixup_video_driver_list(char **drivers) +{ + static const char *fallback[4] = { "vesa", "fbdev", "wsfb", NULL }; + char **end, **drv; + char *x; + int i; + + /* walk to the end of the list */ + for (end = drivers; *end && **end; end++) ; + end--; + + /* + * for each of the fallback drivers, if we find it in the list, + * swap it with the last available non-fallback driver. + */ + for (i = 0; fallback[i]; i++) { + for (drv = drivers; drv != end; drv++) { + if (strstr(*drv, fallback[i])) { + x = *drv; *drv = *end; *end = x; + end--; + break; + } + } + } +} + +static char ** +GenerateDriverlist(char * dirname) +{ + char **ret; + const char *subdirs[] = { dirname, NULL }; + static const char *patlist[] = {"(.*)_drv\\.so", NULL}; + ret = LoaderListDirs(subdirs, patlist); + + /* fix up the probe order for video drivers */ + if (strstr(dirname, "drivers") && ret != NULL) + fixup_video_driver_list(ret); + + return ret; +} + +char ** +xf86DriverlistFromCompile(void) +{ + static char **driverlist = NULL; + + if (!driverlist) + driverlist = GenerateDriverlist("drivers"); + + return driverlist; +} + +/* + * xf86ConfigError -- + * Print a READABLE ErrorMessage!!! All information that is + * available is printed. + */ +static void +xf86ConfigError(char *msg, ...) +{ + va_list ap; + + ErrorF("\nConfig Error:\n"); + va_start(ap, msg); + VErrorF(msg, ap); + va_end(ap); + ErrorF("\n"); + return; +} + +static void +configFiles(XF86ConfFilesPtr fileconf) +{ + MessageType pathFrom; + Bool must_copy; + int size, countDirs; + char *temp_path, *log_buf, *start, *end; + + /* FontPath */ + must_copy = TRUE; + + temp_path = defaultFontPath ? defaultFontPath : ""; + if (xf86fpFlag) + pathFrom = X_CMDLINE; + else if (fileconf && fileconf->file_fontpath) { + pathFrom = X_CONFIG; + if (xf86Info.useDefaultFontPath) { + if (asprintf(&defaultFontPath, "%s%s%s", fileconf->file_fontpath, + *temp_path ? "," : "", temp_path) == -1) + defaultFontPath = NULL; + else + must_copy = FALSE; + } + else + defaultFontPath = fileconf->file_fontpath; + } + else + pathFrom = X_DEFAULT; + temp_path = defaultFontPath ? defaultFontPath : ""; + + /* xf86ValidateFontPath modifies its argument, but returns a copy of it. */ + temp_path = must_copy ? xnfstrdup(defaultFontPath) : defaultFontPath; + defaultFontPath = xf86ValidateFontPath(temp_path); + free(temp_path); + + /* make fontpath more readable in the logfiles */ + countDirs = 1; + temp_path = defaultFontPath; + while ((temp_path = index(temp_path, ',')) != NULL) { + countDirs++; + temp_path++; + } + + log_buf = xnfalloc(strlen(defaultFontPath) + (2 * countDirs) + 1); + temp_path = log_buf; + start = defaultFontPath; + while((end = index(start, ',')) != NULL) { + size = (end - start) + 1; + *(temp_path++) = '\t'; + strncpy(temp_path, start, size); + temp_path += size; + *(temp_path++) = '\n'; + start += size; + } + /* copy last entry */ + *(temp_path++) = '\t'; + strcpy(temp_path, start); + xf86Msg(pathFrom, "FontPath set to:\n%s\n", log_buf); + free(log_buf); + + /* ModulePath */ + + if (fileconf) { + if (xf86ModPathFrom != X_CMDLINE && fileconf->file_modulepath) { + xf86ModulePath = fileconf->file_modulepath; + xf86ModPathFrom = X_CONFIG; + } + } + + xf86Msg(xf86ModPathFrom, "ModulePath set to \"%s\"\n", xf86ModulePath); + + if (!xf86xkbdirFlag && fileconf && fileconf->file_xkbdir) { + XkbBaseDirectory = fileconf->file_xkbdir; + xf86Msg(X_CONFIG, "XKB base directory set to \"%s\"\n", + XkbBaseDirectory); + } +#if 0 + /* LogFile */ + /* + * XXX The problem with this is that the log file is already open. + * One option might be to copy the exiting contents to the new location. + * and re-open it. The down side is that the default location would + * already have been overwritten. Another option would be to start with + * unique temporary location, then copy it once the correct name is known. + * A problem with this is what happens if the server exits before that + * happens. + */ + if (xf86LogFileFrom == X_DEFAULT && fileconf->file_logfile) { + xf86LogFile = fileconf->file_logfile; + xf86LogFileFrom = X_CONFIG; + } +#endif + + return; +} + +typedef enum { + FLAG_NOTRAPSIGNALS, + FLAG_DONTVTSWITCH, + FLAG_DONTZAP, + FLAG_DONTZOOM, + FLAG_DISABLEVIDMODE, + FLAG_ALLOWNONLOCAL, + FLAG_ALLOWMOUSEOPENFAIL, + FLAG_VTSYSREQ, + FLAG_SAVER_BLANKTIME, + FLAG_DPMS_STANDBYTIME, + FLAG_DPMS_SUSPENDTIME, + FLAG_DPMS_OFFTIME, + FLAG_PIXMAP, + FLAG_PC98, + FLAG_NOPM, + FLAG_XINERAMA, + FLAG_LOG, + FLAG_RENDER_COLORMAP_MODE, + FLAG_RANDR, + FLAG_AIGLX, + FLAG_IGNORE_ABI, + FLAG_ALLOW_EMPTY_INPUT, + FLAG_USE_DEFAULT_FONT_PATH, + FLAG_AUTO_ADD_DEVICES, + FLAG_AUTO_ENABLE_DEVICES, + FLAG_GLX_VISUALS, + FLAG_DRI2, + FLAG_USE_SIGIO +} FlagValues; + +/** + * NOTE: the last value for each entry is NOT the default. It is set to TRUE + * if the parser found the option in the config file. + */ +static OptionInfoRec FlagOptions[] = { + { FLAG_NOTRAPSIGNALS, "NoTrapSignals", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_DONTVTSWITCH, "DontVTSwitch", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_DONTZAP, "DontZap", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_DONTZOOM, "DontZoom", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_DISABLEVIDMODE, "DisableVidModeExtension", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_ALLOWNONLOCAL, "AllowNonLocalXvidtune", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_ALLOWMOUSEOPENFAIL, "AllowMouseOpenFail", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_VTSYSREQ, "VTSysReq", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_SAVER_BLANKTIME, "BlankTime" , OPTV_INTEGER, + {0}, FALSE }, + { FLAG_DPMS_STANDBYTIME, "StandbyTime", OPTV_INTEGER, + {0}, FALSE }, + { FLAG_DPMS_SUSPENDTIME, "SuspendTime", OPTV_INTEGER, + {0}, FALSE }, + { FLAG_DPMS_OFFTIME, "OffTime", OPTV_INTEGER, + {0}, FALSE }, + { FLAG_PIXMAP, "Pixmap", OPTV_INTEGER, + {0}, FALSE }, + { FLAG_PC98, "PC98", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_NOPM, "NoPM", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_XINERAMA, "Xinerama", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_LOG, "Log", OPTV_STRING, + {0}, FALSE }, + { FLAG_RENDER_COLORMAP_MODE, "RenderColormapMode", OPTV_STRING, + {0}, FALSE }, + { FLAG_RANDR, "RandR", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_AIGLX, "AIGLX", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_IGNORE_ABI, "IgnoreABI", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_USE_DEFAULT_FONT_PATH, "UseDefaultFontPath", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_AUTO_ADD_DEVICES, "AutoAddDevices", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_AUTO_ENABLE_DEVICES, "AutoEnableDevices", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_GLX_VISUALS, "GlxVisuals", OPTV_STRING, + {0}, FALSE }, + { FLAG_DRI2, "DRI2", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_USE_SIGIO, "UseSIGIO", OPTV_BOOLEAN, + {0}, FALSE }, + { -1, NULL, OPTV_NONE, + {0}, FALSE }, +}; + +#ifdef SUPPORT_PC98 +static Bool +detectPC98(void) +{ + unsigned char buf[2]; + + if (xf86ReadBIOS(0xf8000, 0xe80, buf, 2) != 2) + return FALSE; + if ((buf[0] == 0x98) && (buf[1] == 0x21)) + return TRUE; + else + return FALSE; +} +#endif + +static Bool +configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts) +{ + XF86OptionPtr optp, tmp; + int i; + Pix24Flags pix24 = Pix24DontCare; + Bool value; + MessageType from; + const char *s; + XkbRMLVOSet set; + /* Default options. */ + set.rules = "base"; + set.model = "pc105"; + set.layout = "us"; + set.variant = NULL; + set.options = NULL; + + /* + * Merge the ServerLayout and ServerFlags options. The former have + * precedence over the latter. + */ + optp = NULL; + if (flagsconf && flagsconf->flg_option_lst) + optp = xf86optionListDup(flagsconf->flg_option_lst); + if (layoutopts) { + tmp = xf86optionListDup(layoutopts); + if (optp) + optp = xf86optionListMerge(optp, tmp); + else + optp = tmp; + } + + xf86ProcessOptions(-1, optp, FlagOptions); + + xf86GetOptValBool(FlagOptions, FLAG_NOTRAPSIGNALS, &xf86Info.notrapSignals); + xf86GetOptValBool(FlagOptions, FLAG_DONTVTSWITCH, &xf86Info.dontVTSwitch); + xf86GetOptValBool(FlagOptions, FLAG_DONTZAP, &xf86Info.dontZap); + xf86GetOptValBool(FlagOptions, FLAG_DONTZOOM, &xf86Info.dontZoom); + + xf86GetOptValBool(FlagOptions, FLAG_IGNORE_ABI, &xf86Info.ignoreABI); + if (xf86Info.ignoreABI) { + xf86Msg(X_CONFIG, "Ignoring ABI Version\n"); + } + + if (xf86SIGIOSupported()) { + xf86Info.useSIGIO = xf86ReturnOptValBool(FlagOptions, FLAG_USE_SIGIO, USE_SIGIO_BY_DEFAULT); + if (xf86IsOptionSet(FlagOptions, FLAG_USE_SIGIO)) { + from = X_CONFIG; + } else { + from = X_DEFAULT; + } + if (!xf86Info.useSIGIO) { + xf86Msg(from, "Disabling SIGIO handlers for input devices\n"); + } else if (from == X_CONFIG) { + xf86Msg(from, "Enabling SIGIO handlers for input devices\n"); + } + } else { + xf86Info.useSIGIO = FALSE; + } + + if (xf86IsOptionSet(FlagOptions, FLAG_AUTO_ADD_DEVICES)) { + xf86GetOptValBool(FlagOptions, FLAG_AUTO_ADD_DEVICES, + &xf86Info.autoAddDevices); + from = X_CONFIG; + } + else { + from = X_DEFAULT; + } + xf86Msg(from, "%sutomatically adding devices\n", + xf86Info.autoAddDevices ? "A" : "Not a"); + + if (xf86IsOptionSet(FlagOptions, FLAG_AUTO_ENABLE_DEVICES)) { + xf86GetOptValBool(FlagOptions, FLAG_AUTO_ENABLE_DEVICES, + &xf86Info.autoEnableDevices); + from = X_CONFIG; + } + else { + from = X_DEFAULT; + } + xf86Msg(from, "%sutomatically enabling devices\n", + xf86Info.autoEnableDevices ? "A" : "Not a"); + + /* + * Set things up based on the config file information. Some of these + * settings may be overridden later when the command line options are + * checked. + */ +#ifdef XF86VIDMODE + if (xf86GetOptValBool(FlagOptions, FLAG_DISABLEVIDMODE, &value)) + xf86Info.vidModeEnabled = !value; + if (xf86GetOptValBool(FlagOptions, FLAG_ALLOWNONLOCAL, &value)) + xf86Info.vidModeAllowNonLocal = value; +#endif + + if (xf86GetOptValBool(FlagOptions, FLAG_ALLOWMOUSEOPENFAIL, &value)) + xf86Info.allowMouseOpenFail = value; + + if (xf86GetOptValBool(FlagOptions, FLAG_VTSYSREQ, &value)) { +#ifdef USE_VT_SYSREQ + xf86Info.vtSysreq = value; + xf86Msg(X_CONFIG, "VTSysReq %s\n", value ? "enabled" : "disabled"); +#else + if (value) + xf86Msg(X_WARNING, "VTSysReq is not supported on this OS\n"); +#endif + } + + xf86Info.pmFlag = TRUE; + if (xf86GetOptValBool(FlagOptions, FLAG_NOPM, &value)) + xf86Info.pmFlag = !value; + { + if ((s = xf86GetOptValString(FlagOptions, FLAG_LOG))) { + if (!xf86NameCmp(s,"flush")) { + xf86Msg(X_CONFIG, "Flushing logfile enabled\n"); + xf86Info.log = LogFlush; + LogSetParameter(XLOG_FLUSH, TRUE); + } else if (!xf86NameCmp(s,"sync")) { + xf86Msg(X_CONFIG, "Syncing logfile enabled\n"); + xf86Info.log = LogSync; + LogSetParameter(XLOG_FLUSH, TRUE); + LogSetParameter(XLOG_SYNC, TRUE); + } else { + xf86Msg(X_WARNING,"Unknown Log option\n"); + } + } + } + + { + if ((s = xf86GetOptValString(FlagOptions, FLAG_RENDER_COLORMAP_MODE))){ + int policy = PictureParseCmapPolicy (s); + if (policy == PictureCmapPolicyInvalid) + xf86Msg(X_WARNING, "Unknown colormap policy \"%s\"\n", s); + else + { + xf86Msg(X_CONFIG, "Render colormap policy set to %s\n", s); + PictureCmapPolicy = policy; + } + } + } + +#ifdef RANDR + xf86Info.disableRandR = FALSE; + xf86Info.randRFrom = X_DEFAULT; + if (xf86GetOptValBool(FlagOptions, FLAG_RANDR, &value)) { + xf86Info.disableRandR = !value; + xf86Info.randRFrom = X_CONFIG; + } +#endif + + xf86Info.aiglx = TRUE; + xf86Info.aiglxFrom = X_DEFAULT; + if (xf86GetOptValBool(FlagOptions, FLAG_AIGLX, &value)) { + xf86Info.aiglx = value; + xf86Info.aiglxFrom = X_CONFIG; + } + +#ifdef GLXEXT + xf86Info.glxVisuals = XF86_GlxVisualsTypical; + xf86Info.glxVisualsFrom = X_DEFAULT; + if ((s = xf86GetOptValString(FlagOptions, FLAG_GLX_VISUALS))) { + if (!xf86NameCmp(s, "minimal")) { + xf86Info.glxVisuals = XF86_GlxVisualsMinimal; + } else if (!xf86NameCmp(s, "typical")) { + xf86Info.glxVisuals = XF86_GlxVisualsTypical; + } else if (!xf86NameCmp(s, "all")) { + xf86Info.glxVisuals = XF86_GlxVisualsAll; + } else { + xf86Msg(X_WARNING,"Unknown GlxVisuals option\n"); + } + } + + if (xf86GetOptValBool(FlagOptions, FLAG_AIGLX, &value)) { + xf86Info.aiglx = value; + xf86Info.aiglxFrom = X_CONFIG; + } +#endif + + /* if we're not hotplugging, force some input devices to exist */ + xf86Info.forceInputDevices = !(xf86Info.autoAddDevices && xf86Info.autoEnableDevices); + + /* when forcing input devices, we use kbd. otherwise evdev, so use the + * evdev rules set. */ +#if defined(linux) + if (!xf86Info.forceInputDevices) + set.rules = "evdev"; +#endif + XkbSetRulesDflts(&set); + + xf86Info.useDefaultFontPath = TRUE; + xf86Info.useDefaultFontPathFrom = X_DEFAULT; + if (xf86GetOptValBool(FlagOptions, FLAG_USE_DEFAULT_FONT_PATH, &value)) { + xf86Info.useDefaultFontPath = value; + xf86Info.useDefaultFontPathFrom = X_CONFIG; + } + +/* Make sure that timers don't overflow CARD32's after multiplying */ +#define MAX_TIME_IN_MIN (0x7fffffff / MILLI_PER_MIN) + + i = -1; + xf86GetOptValInteger(FlagOptions, FLAG_SAVER_BLANKTIME, &i); + if ((i >= 0) && (i < MAX_TIME_IN_MIN)) + ScreenSaverTime = defaultScreenSaverTime = i * MILLI_PER_MIN; + else if (i != -1) + xf86ConfigError("BlankTime value %d outside legal range of 0 - %d minutes", + i, MAX_TIME_IN_MIN); + +#ifdef DPMSExtension + i = -1; + xf86GetOptValInteger(FlagOptions, FLAG_DPMS_STANDBYTIME, &i); + if ((i >= 0) && (i < MAX_TIME_IN_MIN)) + DPMSStandbyTime = i * MILLI_PER_MIN; + else if (i != -1) + xf86ConfigError("StandbyTime value %d outside legal range of 0 - %d minutes", + i, MAX_TIME_IN_MIN); + i = -1; + xf86GetOptValInteger(FlagOptions, FLAG_DPMS_SUSPENDTIME, &i); + if ((i >= 0) && (i < MAX_TIME_IN_MIN)) + DPMSSuspendTime = i * MILLI_PER_MIN; + else if (i != -1) + xf86ConfigError("SuspendTime value %d outside legal range of 0 - %d minutes", + i, MAX_TIME_IN_MIN); + i = -1; + xf86GetOptValInteger(FlagOptions, FLAG_DPMS_OFFTIME, &i); + if ((i >= 0) && (i < MAX_TIME_IN_MIN)) + DPMSOffTime = i * MILLI_PER_MIN; + else if (i != -1) + xf86ConfigError("OffTime value %d outside legal range of 0 - %d minutes", + i, MAX_TIME_IN_MIN); +#endif + + i = -1; + xf86GetOptValInteger(FlagOptions, FLAG_PIXMAP, &i); + switch (i) { + case 24: + pix24 = Pix24Use24; + break; + case 32: + pix24 = Pix24Use32; + break; + case -1: + break; + default: + xf86ConfigError("Pixmap option's value (%d) must be 24 or 32\n", i); + return FALSE; + } + if (xf86Pix24 != Pix24DontCare) { + xf86Info.pixmap24 = xf86Pix24; + xf86Info.pix24From = X_CMDLINE; + } else if (pix24 != Pix24DontCare) { + xf86Info.pixmap24 = pix24; + xf86Info.pix24From = X_CONFIG; + } else { + xf86Info.pixmap24 = Pix24DontCare; + xf86Info.pix24From = X_DEFAULT; + } +#ifdef SUPPORT_PC98 + if (xf86GetOptValBool(FlagOptions, FLAG_PC98, &value)) { + xf86Info.pc98 = value; + if (value) { + xf86Msg(X_CONFIG, "Japanese PC98 architecture\n"); + } + } else + if (detectPC98()) { + xf86Info.pc98 = TRUE; + xf86Msg(X_PROBED, "Japanese PC98 architecture\n"); + } +#endif + +#ifdef PANORAMIX + from = X_DEFAULT; + if (!noPanoramiXExtension) + from = X_CMDLINE; + else if (xf86GetOptValBool(FlagOptions, FLAG_XINERAMA, &value)) { + noPanoramiXExtension = !value; + from = X_CONFIG; + } + if (!noPanoramiXExtension) + xf86Msg(from, "Xinerama: enabled\n"); +#endif + +#ifdef DRI2 + xf86Info.dri2 = FALSE; + xf86Info.dri2From = X_DEFAULT; + if (xf86GetOptValBool(FlagOptions, FLAG_DRI2, &value)) { + xf86Info.dri2 = value; + xf86Info.dri2From = X_CONFIG; + } +#endif + + return TRUE; +} + +Bool xf86DRI2Enabled(void) +{ + return xf86Info.dri2; +} + +/* + * Locate the core input devices. These can be specified/located in + * the following ways, in order of priority: + * + * 1. The InputDevices named by the -pointer and -keyboard command line + * options. + * 2. The "CorePointer" and "CoreKeyboard" InputDevices referred to by + * the active ServerLayout. + * 3. The first InputDevices marked as "CorePointer" and "CoreKeyboard". + * 4. The first InputDevices that use 'keyboard' or 'kbd' and a valid mouse + * driver (mouse, synaptics, evdev, vmmouse, void) + * 5. Default devices with an empty (default) configuration. These defaults + * will reference the 'mouse' and 'keyboard' drivers. + */ + +static Bool +checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout) +{ + InputInfoPtr corePointer = NULL, coreKeyboard = NULL; + Bool foundPointer = FALSE, foundKeyboard = FALSE; + const char *pointerMsg = NULL, *keyboardMsg = NULL; + InputInfoPtr *devs, /* iterator */ + indp; + InputInfoRec Pointer = {}, Keyboard = {}; + XF86ConfInputPtr confInput; + XF86ConfInputRec defPtr, defKbd; + int count = 0; + MessageType from = X_DEFAULT; + int found = 0; + const char *mousedrivers[] = { "mouse", "synaptics", "evdev", "vmmouse", + "void", NULL }; + + /* + * First check if a core pointer or core keyboard have been specified + * in the active ServerLayout. If more than one is specified for either, + * remove the core attribute from the later ones. + */ + for (devs = servlayoutp->inputs; devs && *devs; devs++) { + indp = *devs; + if (indp->options && + xf86CheckBoolOption(indp->options, "CorePointer", FALSE)) { + if (!corePointer) { + corePointer = indp; + } else { + xf86ReplaceBoolOption(indp->options, "CorePointer", FALSE); + xf86Msg(X_WARNING, "Duplicate core pointer devices. " + "Removing core pointer attribute from \"%s\"\n", + indp->name); + } + } + if (indp->options && + xf86CheckBoolOption(indp->options, "CoreKeyboard", FALSE)) { + if (!coreKeyboard) { + coreKeyboard = indp; + } else { + xf86ReplaceBoolOption(indp->options, "CoreKeyboard", FALSE); + xf86Msg(X_WARNING, "Duplicate core keyboard devices. " + "Removing core keyboard attribute from \"%s\"\n", + indp->name); + } + } + count++; + } + + confInput = NULL; + + /* 1. Check for the -pointer command line option. */ + if (xf86PointerName) { + confInput = xf86findInput(xf86PointerName, + xf86configptr->conf_input_lst); + if (!confInput) { + xf86Msg(X_ERROR, "No InputDevice section called \"%s\"\n", + xf86PointerName); + return FALSE; + } + from = X_CMDLINE; + /* + * If one was already specified in the ServerLayout, it needs to be + * removed. + */ + if (corePointer) { + for (devs = servlayoutp->inputs; devs && *devs; devs++) + if (*devs == corePointer) + { + free(*devs); + *devs = (InputInfoPtr)0x1; /* ensure we dont skip next loop*/ + break; + } + for (; devs && *devs; devs++) + devs[0] = devs[1]; + count--; + } + corePointer = NULL; + foundPointer = TRUE; + } + + /* 2. ServerLayout-specified core pointer. */ + if (corePointer) { + foundPointer = TRUE; + from = X_CONFIG; + } + + /* 3. First core pointer device. */ + if (!foundPointer && (xf86Info.forceInputDevices || implicitLayout)) { + XF86ConfInputPtr p; + + for (p = xf86configptr->conf_input_lst; p; p = p->list.next) { + if (p->inp_option_lst && + xf86CheckBoolOption(p->inp_option_lst, "CorePointer", FALSE)) { + confInput = p; + foundPointer = TRUE; + from = X_DEFAULT; + pointerMsg = "first core pointer device"; + break; + } + } + } + + /* 4. First pointer with an allowed mouse driver. */ + if (!foundPointer && xf86Info.forceInputDevices) { + const char **driver = mousedrivers; + confInput = xf86findInput(CONF_IMPLICIT_POINTER, + xf86configptr->conf_input_lst); + while (*driver && !confInput) { + confInput = xf86findInputByDriver(*driver, + xf86configptr->conf_input_lst); + driver++; + } + if (confInput) { + foundPointer = TRUE; + from = X_DEFAULT; + pointerMsg = "first mouse device"; + } + } + + /* 5. Built-in default. */ + if (!foundPointer && xf86Info.forceInputDevices) { + memset(&defPtr, 0, sizeof(defPtr)); + defPtr.inp_identifier = strdup("<default pointer>"); + defPtr.inp_driver = strdup("mouse"); + confInput = &defPtr; + foundPointer = TRUE; + from = X_DEFAULT; + pointerMsg = "default mouse configuration"; + } + + /* Add the core pointer device to the layout, and set it to Core. */ + if (foundPointer && confInput) { + foundPointer = configInput(&Pointer, confInput, from); + if (foundPointer) { + count++; + devs = xnfrealloc(servlayoutp->inputs, + (count + 1) * sizeof(InputInfoPtr)); + devs[count - 1] = xnfalloc(sizeof(InputInfoRec)); + *devs[count - 1] = Pointer; + devs[count - 1]->options = + xf86addNewOption(devs[count -1]->options, + xnfstrdup("CorePointer"), NULL); + devs[count] = NULL; + servlayoutp->inputs = devs; + } + } + + if (!foundPointer && xf86Info.forceInputDevices) { + /* This shouldn't happen. */ + xf86Msg(X_ERROR, "Cannot locate a core pointer device.\n"); + return FALSE; + } + + /* + * always synthesize a 'mouse' section configured to send core + * events, unless a 'void' section is found, in which case the user + * probably wants to run footless. + * + * If you're using an evdev keyboard and expect a default mouse + * section ... deal. + */ + for (devs = servlayoutp->inputs; devs && *devs; devs++) { + const char **driver = mousedrivers; + while(*driver) { + if (!strcmp((*devs)->driver, *driver)) { + found = 1; + break; + } + driver++; + } + } + if (!found && xf86Info.forceInputDevices) { + xf86Msg(X_INFO, "No default mouse found, adding one\n"); + memset(&defPtr, 0, sizeof(defPtr)); + defPtr.inp_identifier = strdup("<default pointer>"); + defPtr.inp_driver = strdup("mouse"); + confInput = &defPtr; + foundPointer = configInput(&Pointer, confInput, from); + if (foundPointer) { + count++; + devs = xnfrealloc(servlayoutp->inputs, + (count + 1) * sizeof(InputInfoPtr)); + devs[count - 1] = xnfalloc(sizeof(InputInfoRec)); + *devs[count - 1] = Pointer; + devs[count - 1]->options = + xf86addNewOption(NULL, xnfstrdup("AlwaysCore"), NULL); + devs[count] = NULL; + servlayoutp->inputs = devs; + } + } + + confInput = NULL; + + /* 1. Check for the -keyboard command line option. */ + if (xf86KeyboardName) { + confInput = xf86findInput(xf86KeyboardName, + xf86configptr->conf_input_lst); + if (!confInput) { + xf86Msg(X_ERROR, "No InputDevice section called \"%s\"\n", + xf86KeyboardName); + return FALSE; + } + from = X_CMDLINE; + /* + * If one was already specified in the ServerLayout, it needs to be + * removed. + */ + if (coreKeyboard) { + for (devs = servlayoutp->inputs; devs && *devs; devs++) + if (*devs == coreKeyboard) + { + free(*devs); + *devs = (InputInfoPtr)0x1; /* ensure we dont skip next loop */ + break; + } + for (; devs && *devs; devs++) + devs[0] = devs[1]; + count--; + } + coreKeyboard = NULL; + foundKeyboard = TRUE; + } + + /* 2. ServerLayout-specified core keyboard. */ + if (coreKeyboard) { + foundKeyboard = TRUE; + from = X_CONFIG; + } + + /* 3. First core keyboard device. */ + if (!foundKeyboard && (xf86Info.forceInputDevices || implicitLayout)) { + XF86ConfInputPtr p; + + for (p = xf86configptr->conf_input_lst; p; p = p->list.next) { + if (p->inp_option_lst && + xf86CheckBoolOption(p->inp_option_lst, "CoreKeyboard", FALSE)) { + confInput = p; + foundKeyboard = TRUE; + from = X_DEFAULT; + keyboardMsg = "first core keyboard device"; + break; + } + } + } + + /* 4. First keyboard with 'keyboard' or 'kbd' as the driver. */ + if (!foundKeyboard && xf86Info.forceInputDevices) { + confInput = xf86findInput(CONF_IMPLICIT_KEYBOARD, + xf86configptr->conf_input_lst); + if (!confInput) { + confInput = xf86findInputByDriver("kbd", + xf86configptr->conf_input_lst); + } + if (confInput) { + foundKeyboard = TRUE; + from = X_DEFAULT; + keyboardMsg = "first keyboard device"; + } + } + + /* 5. Built-in default. */ + if (!foundKeyboard && xf86Info.forceInputDevices) { + memset(&defKbd, 0, sizeof(defKbd)); + defKbd.inp_identifier = strdup("<default keyboard>"); + defKbd.inp_driver = strdup("kbd"); + confInput = &defKbd; + foundKeyboard = TRUE; + keyboardMsg = "default keyboard configuration"; + from = X_DEFAULT; + } + + /* Add the core keyboard device to the layout, and set it to Core. */ + if (foundKeyboard && confInput) { + foundKeyboard = configInput(&Keyboard, confInput, from); + if (foundKeyboard) { + count++; + devs = xnfrealloc(servlayoutp->inputs, + (count + 1) * sizeof(InputInfoPtr)); + devs[count - 1] = xnfalloc(sizeof(InputInfoRec)); + *devs[count - 1] = Keyboard; + devs[count - 1]->options = + xf86addNewOption(devs[count - 1]->options, + xnfstrdup("CoreKeyboard"), NULL); + devs[count] = NULL; + servlayoutp->inputs = devs; + } + } + + if (!foundKeyboard && xf86Info.forceInputDevices) { + /* This shouldn't happen. */ + xf86Msg(X_ERROR, "Cannot locate a core keyboard device.\n"); + return FALSE; + } + + if (pointerMsg) { + if (implicitLayout) + xf86Msg(X_DEFAULT, "No Layout section. Using the %s.\n", + pointerMsg); + else + xf86Msg(X_DEFAULT, "The core pointer device wasn't specified " + "explicitly in the layout.\n" + "\tUsing the %s.\n", pointerMsg); + } + + if (keyboardMsg) { + if (implicitLayout) + xf86Msg(X_DEFAULT, "No Layout section. Using the %s.\n", + keyboardMsg); + else + xf86Msg(X_DEFAULT, "The core keyboard device wasn't specified " + "explicitly in the layout.\n" + "\tUsing the %s.\n", keyboardMsg); + } + + if (!xf86Info.forceInputDevices && !(foundPointer && foundKeyboard)) { +#if defined(CONFIG_HAL) || defined(CONFIG_UDEV) + const char *config_backend; +#if defined(CONFIG_HAL) + config_backend = "HAL"; +#else + config_backend = "udev"; +#endif + xf86Msg(X_INFO, "The server relies on %s to provide the list of " + "input devices.\n\tIf no devices become available, " + "reconfigure %s or disable AutoAddDevices.\n", + config_backend, config_backend); +#else + xf86Msg(X_WARNING, "Hotplugging requested but the server was " + "compiled without a config backend. " + "No input devices were configured, the server " + "will start without any input devices.\n"); +#endif + } + + return TRUE; +} + +typedef enum { + LAYOUT_ISOLATEDEVICE, + LAYOUT_SINGLECARD +} LayoutValues; + +static OptionInfoRec LayoutOptions[] = { + { LAYOUT_ISOLATEDEVICE, "IsolateDevice", OPTV_STRING, + {0}, FALSE }, + { LAYOUT_SINGLECARD, "SingleCard", OPTV_BOOLEAN, + {0}, FALSE }, + { -1, NULL, OPTV_NONE, + {0}, FALSE }, +}; + +static Bool +configInputDevices(XF86ConfLayoutPtr layout, serverLayoutPtr servlayoutp) +{ + XF86ConfInputrefPtr irp; + InputInfoPtr *indp; + int count = 0; + + /* + * Count the number of input devices. + */ + irp = layout->lay_input_lst; + while (irp) { + count++; + irp = (XF86ConfInputrefPtr)irp->list.next; + } + DebugF("Found %d input devices in the layout section %s\n", + count, layout->lay_identifier); + indp = xnfcalloc((count + 1), sizeof(InputInfoPtr)); + indp[count] = NULL; + irp = layout->lay_input_lst; + count = 0; + while (irp) { + indp[count] = xf86AllocateInput(); + if (!configInput(indp[count], irp->iref_inputdev, X_CONFIG)) { + do { + free(indp[count]); + } while(count--); + free(indp); + return FALSE; + } + indp[count]->options = xf86OptionListMerge(indp[count]->options, + irp->iref_option_lst); + count++; + irp = (XF86ConfInputrefPtr)irp->list.next; + } + servlayoutp->inputs = indp; + + return TRUE; +} + + +/* + * figure out which layout is active, which screens are used in that layout, + * which drivers and monitors are used in these screens + */ +static Bool +configLayout(serverLayoutPtr servlayoutp, XF86ConfLayoutPtr conf_layout, + char *default_layout) +{ + XF86ConfAdjacencyPtr adjp; + XF86ConfInactivePtr idp; + int saved_count, count = 0; + int scrnum; + XF86ConfLayoutPtr l; + MessageType from; + screenLayoutPtr slp; + GDevPtr gdp; + int i = 0, j; + + if (!servlayoutp) + return FALSE; + + /* + * which layout section is the active one? + * + * If there is a -layout command line option, use that one, otherwise + * pick the first one. + */ + from = X_DEFAULT; + if (xf86LayoutName != NULL) + from = X_CMDLINE; + else if (default_layout) { + xf86LayoutName = default_layout; + from = X_CONFIG; + } + if (xf86LayoutName != NULL) { + if ((l = xf86findLayout(xf86LayoutName, conf_layout)) == NULL) { + xf86Msg(X_ERROR, "No ServerLayout section called \"%s\"\n", + xf86LayoutName); + return FALSE; + } + conf_layout = l; + } + xf86Msg(from, "ServerLayout \"%s\"\n", conf_layout->lay_identifier); + adjp = conf_layout->lay_adjacency_lst; + + /* + * we know that each screen is referenced exactly once on the left side + * of a layout statement in the Layout section. So to allocate the right + * size for the array we do a quick walk of the list to figure out how + * many sections we have + */ + while (adjp) { + count++; + adjp = (XF86ConfAdjacencyPtr)adjp->list.next; + } + + DebugF("Found %d screens in the layout section %s", + count, conf_layout->lay_identifier); + if (!count) /* alloc enough storage even if no screen is specified */ + count = 1; + + slp = xnfcalloc(1, (count + 1) * sizeof(screenLayoutRec)); + slp[count].screen = NULL; + /* + * now that we have storage, loop over the list again and fill in our + * data structure; at this point we do not fill in the adjacency + * information as it is not clear if we need it at all + */ + adjp = conf_layout->lay_adjacency_lst; + count = 0; + while (adjp) { + slp[count].screen = xnfcalloc(1, sizeof(confScreenRec)); + if (adjp->adj_scrnum < 0) + scrnum = count; + else + scrnum = adjp->adj_scrnum; + if (!configScreen(slp[count].screen, adjp->adj_screen, scrnum, + X_CONFIG)) { + do { + free(slp[count].screen); + } while(count--); + free(slp); + return FALSE; + } + slp[count].x = adjp->adj_x; + slp[count].y = adjp->adj_y; + slp[count].refname = adjp->adj_refscreen; + switch (adjp->adj_where) { + case CONF_ADJ_OBSOLETE: + slp[count].where = PosObsolete; + slp[count].topname = adjp->adj_top_str; + slp[count].bottomname = adjp->adj_bottom_str; + slp[count].leftname = adjp->adj_left_str; + slp[count].rightname = adjp->adj_right_str; + break; + case CONF_ADJ_ABSOLUTE: + slp[count].where = PosAbsolute; + break; + case CONF_ADJ_RIGHTOF: + slp[count].where = PosRightOf; + break; + case CONF_ADJ_LEFTOF: + slp[count].where = PosLeftOf; + break; + case CONF_ADJ_ABOVE: + slp[count].where = PosAbove; + break; + case CONF_ADJ_BELOW: + slp[count].where = PosBelow; + break; + case CONF_ADJ_RELATIVE: + slp[count].where = PosRelative; + break; + } + count++; + adjp = (XF86ConfAdjacencyPtr)adjp->list.next; + } + + /* No screen was specified in the layout. take the first one from the + * config file, or - if it is NULL - configScreen autogenerates one for + * us */ + if (!count) + { + slp[0].screen = xnfcalloc(1, sizeof(confScreenRec)); + if (!configScreen(slp[0].screen, xf86configptr->conf_screen_lst, + 0, X_CONFIG)) { + free(slp[0].screen); + free(slp); + return FALSE; + } + } + + /* XXX Need to tie down the upper left screen. */ + + /* Fill in the refscreen and top/bottom/left/right values */ + for (i = 0; i < count; i++) { + for (j = 0; j < count; j++) { + if (slp[i].refname && + strcmp(slp[i].refname, slp[j].screen->id) == 0) { + slp[i].refscreen = slp[j].screen; + } + if (slp[i].topname && + strcmp(slp[i].topname, slp[j].screen->id) == 0) { + slp[i].top = slp[j].screen; + } + if (slp[i].bottomname && + strcmp(slp[i].bottomname, slp[j].screen->id) == 0) { + slp[i].bottom = slp[j].screen; + } + if (slp[i].leftname && + strcmp(slp[i].leftname, slp[j].screen->id) == 0) { + slp[i].left = slp[j].screen; + } + if (slp[i].rightname && + strcmp(slp[i].rightname, slp[j].screen->id) == 0) { + slp[i].right = slp[j].screen; + } + } + if (slp[i].where != PosObsolete + && slp[i].where != PosAbsolute + && !slp[i].refscreen) { + xf86Msg(X_ERROR,"Screen %s doesn't exist: deleting placement\n", + slp[i].refname); + slp[i].where = PosAbsolute; + slp[i].x = 0; + slp[i].y = 0; + } + } + + if (!count) + saved_count = 1; + else + saved_count = count; + /* + * Count the number of inactive devices. + */ + count = 0; + idp = conf_layout->lay_inactive_lst; + while (idp) { + count++; + idp = (XF86ConfInactivePtr)idp->list.next; + } + DebugF("Found %d inactive devices in the layout section %s\n", + count, conf_layout->lay_identifier); + gdp = xnfalloc((count + 1) * sizeof(GDevRec)); + gdp[count].identifier = NULL; + idp = conf_layout->lay_inactive_lst; + count = 0; + while (idp) { + if (!configDevice(&gdp[count], idp->inactive_device, FALSE)) + goto bail; + count++; + idp = (XF86ConfInactivePtr)idp->list.next; + } + + if (!configInputDevices(conf_layout, servlayoutp)) + goto bail; + + servlayoutp->id = conf_layout->lay_identifier; + servlayoutp->screens = slp; + servlayoutp->inactives = gdp; + servlayoutp->options = conf_layout->lay_option_lst; + from = X_DEFAULT; + + return TRUE; + +bail: + do { + free(slp[saved_count].screen); + } while(saved_count--); + free(slp); + free(gdp); + return FALSE; +} + +/* + * No layout section, so find the first Screen section and set that up as + * the only active screen. + */ +static Bool +configImpliedLayout(serverLayoutPtr servlayoutp, XF86ConfScreenPtr conf_screen, + XF86ConfigPtr xf86configptr) +{ + MessageType from; + XF86ConfScreenPtr s; + screenLayoutPtr slp; + InputInfoPtr *indp; + XF86ConfLayoutRec layout; + + if (!servlayoutp) + return FALSE; + + /* + * which screen section is the active one? + * + * If there is a -screen option, use that one, otherwise use the first + * one. + */ + + from = X_CONFIG; + if (xf86ScreenName != NULL) { + if ((s = xf86findScreen(xf86ScreenName, conf_screen)) == NULL) { + xf86Msg(X_ERROR, "No Screen section called \"%s\"\n", + xf86ScreenName); + return FALSE; + } + conf_screen = s; + from = X_CMDLINE; + } + + /* We have exactly one screen */ + + slp = xnfcalloc(1, 2 * sizeof(screenLayoutRec)); + slp[0].screen = xnfcalloc(1, sizeof(confScreenRec)); + slp[1].screen = NULL; + if (!configScreen(slp[0].screen, conf_screen, 0, from)) { + free(slp); + return FALSE; + } + servlayoutp->id = "(implicit)"; + servlayoutp->screens = slp; + servlayoutp->inactives = xnfcalloc(1, sizeof(GDevRec)); + servlayoutp->options = NULL; + + memset(&layout, 0, sizeof(layout)); + layout.lay_identifier = servlayoutp->id; + if (xf86layoutAddInputDevices(xf86configptr, &layout) > 0) { + if (!configInputDevices(&layout, servlayoutp)) + return FALSE; + from = X_DEFAULT; + } else { + /* Set up an empty input device list, then look for some core devices. */ + indp = xnfalloc(sizeof(InputInfoPtr)); + *indp = NULL; + servlayoutp->inputs = indp; + } + + return TRUE; +} + +static Bool +configXvAdaptor(confXvAdaptorPtr adaptor, XF86ConfVideoAdaptorPtr conf_adaptor) +{ + int count = 0; + XF86ConfVideoPortPtr conf_port; + + xf86Msg(X_CONFIG, "| |-->VideoAdaptor \"%s\"\n", + conf_adaptor->va_identifier); + adaptor->identifier = conf_adaptor->va_identifier; + adaptor->options = conf_adaptor->va_option_lst; + if (conf_adaptor->va_busid || conf_adaptor->va_driver) { + xf86Msg(X_CONFIG, "| | Unsupported device type, skipping entry\n"); + return FALSE; + } + + /* + * figure out how many videoport subsections there are and fill them in + */ + conf_port = conf_adaptor->va_port_lst; + while(conf_port) { + count++; + conf_port = (XF86ConfVideoPortPtr)conf_port->list.next; + } + adaptor->ports = xnfalloc((count) * sizeof(confXvPortRec)); + adaptor->numports = count; + count = 0; + conf_port = conf_adaptor->va_port_lst; + while(conf_port) { + adaptor->ports[count].identifier = conf_port->vp_identifier; + adaptor->ports[count].options = conf_port->vp_option_lst; + count++; + conf_port = (XF86ConfVideoPortPtr)conf_port->list.next; + } + + return TRUE; +} + +static Bool +configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen, int scrnum, + MessageType from) +{ + int count = 0; + XF86ConfDisplayPtr dispptr; + XF86ConfAdaptorLinkPtr conf_adaptor; + Bool defaultMonitor = FALSE; + XF86ConfScreenRec local_conf_screen; + + if (!conf_screen) { + memset(&local_conf_screen, 0, sizeof(local_conf_screen)); + conf_screen = &local_conf_screen; + conf_screen->scrn_identifier = "Default Screen Section"; + xf86Msg(X_DEFAULT, "No screen section available. Using defaults.\n"); + } + + xf86Msg(from, "|-->Screen \"%s\" (%d)\n", conf_screen->scrn_identifier, + scrnum); + /* + * now we fill in the elements of the screen + */ + screenp->id = conf_screen->scrn_identifier; + screenp->screennum = scrnum; + screenp->defaultdepth = conf_screen->scrn_defaultdepth; + screenp->defaultbpp = conf_screen->scrn_defaultbpp; + screenp->defaultfbbpp = conf_screen->scrn_defaultfbbpp; + screenp->monitor = xnfcalloc(1, sizeof(MonRec)); + /* If no monitor is specified, create a default one. */ + if (!conf_screen->scrn_monitor) { + XF86ConfMonitorRec defMon; + + memset(&defMon, 0, sizeof(defMon)); + defMon.mon_identifier = "<default monitor>"; + if (!configMonitor(screenp->monitor, &defMon)) + return FALSE; + defaultMonitor = TRUE; + } else { + if (!configMonitor(screenp->monitor,conf_screen->scrn_monitor)) + return FALSE; + } + /* Configure the device. If there isn't one configured, attach to the + * first inactive one that we can configure. If there's none that work, + * set it to NULL so that the section can be autoconfigured later */ + screenp->device = xnfcalloc(1, sizeof(GDevRec)); + if ((!conf_screen->scrn_device) && (xf86configptr->conf_device_lst)) { + conf_screen->scrn_device = xf86configptr->conf_device_lst; + xf86Msg(X_DEFAULT, "No device specified for screen \"%s\".\n" + "\tUsing the first device section listed.\n", screenp->id); + } + if (configDevice(screenp->device,conf_screen->scrn_device, TRUE)) { + screenp->device->myScreenSection = screenp; + } else { + screenp->device = NULL; + } + screenp->options = conf_screen->scrn_option_lst; + + /* + * figure out how many display subsections there are and fill them in + */ + dispptr = conf_screen->scrn_display_lst; + while(dispptr) { + count++; + dispptr = (XF86ConfDisplayPtr)dispptr->list.next; + } + screenp->displays = xnfalloc((count) * sizeof(DispRec)); + screenp->numdisplays = count; + + /* Fill in the default Virtual size, if any */ + if (conf_screen->scrn_virtualX && conf_screen->scrn_virtualY) { + for (count = 0, dispptr = conf_screen->scrn_display_lst; + dispptr; + dispptr = (XF86ConfDisplayPtr)dispptr->list.next, count++) { + screenp->displays[count].virtualX = conf_screen->scrn_virtualX; + screenp->displays[count].virtualY = conf_screen->scrn_virtualY; + } + } + + /* Now do the per-Display Virtual sizes */ + count = 0; + dispptr = conf_screen->scrn_display_lst; + while(dispptr) { + configDisplay(&(screenp->displays[count]),dispptr); + count++; + dispptr = (XF86ConfDisplayPtr)dispptr->list.next; + } + + /* + * figure out how many videoadaptor references there are and fill them in + */ + conf_adaptor = conf_screen->scrn_adaptor_lst; + while(conf_adaptor) { + count++; + conf_adaptor = (XF86ConfAdaptorLinkPtr)conf_adaptor->list.next; + } + screenp->xvadaptors = xnfalloc((count) * sizeof(confXvAdaptorRec)); + screenp->numxvadaptors = 0; + conf_adaptor = conf_screen->scrn_adaptor_lst; + while(conf_adaptor) { + if (configXvAdaptor(&(screenp->xvadaptors[screenp->numxvadaptors]), + conf_adaptor->al_adaptor)) + screenp->numxvadaptors++; + conf_adaptor = (XF86ConfAdaptorLinkPtr)conf_adaptor->list.next; + } + + if (defaultMonitor) { + xf86Msg(X_DEFAULT, "No monitor specified for screen \"%s\".\n" + "\tUsing a default monitor configuration.\n", screenp->id); + } + return TRUE; +} + +typedef enum { + MON_REDUCEDBLANKING, + MON_MAX_PIX_CLOCK, +} MonitorValues; + +static OptionInfoRec MonitorOptions[] = { + { MON_REDUCEDBLANKING, "ReducedBlanking", OPTV_BOOLEAN, + {0}, FALSE }, + { MON_MAX_PIX_CLOCK, "MaxPixClock", OPTV_FREQ, + {0}, FALSE }, + { -1, NULL, OPTV_NONE, + {0}, FALSE }, +}; + +static Bool +configMonitor(MonPtr monitorp, XF86ConfMonitorPtr conf_monitor) +{ + int count; + DisplayModePtr mode,last = NULL; + XF86ConfModeLinePtr cmodep; + XF86ConfModesPtr modes; + XF86ConfModesLinkPtr modeslnk = conf_monitor->mon_modes_sect_lst; + Gamma zeros = {0.0, 0.0, 0.0}; + float badgamma = 0.0; + double maxPixClock; + + xf86Msg(X_CONFIG, "| |-->Monitor \"%s\"\n", + conf_monitor->mon_identifier); + monitorp->id = conf_monitor->mon_identifier; + monitorp->vendor = conf_monitor->mon_vendor; + monitorp->model = conf_monitor->mon_modelname; + monitorp->Modes = NULL; + monitorp->Last = NULL; + monitorp->gamma = zeros; + monitorp->widthmm = conf_monitor->mon_width; + monitorp->heightmm = conf_monitor->mon_height; + monitorp->reducedblanking = FALSE; + monitorp->maxPixClock = 0; + monitorp->options = conf_monitor->mon_option_lst; + + /* + * fill in the monitor structure + */ + for( count = 0 ; + count < conf_monitor->mon_n_hsync && count < MAX_HSYNC; + count++) { + monitorp->hsync[count].hi = conf_monitor->mon_hsync[count].hi; + monitorp->hsync[count].lo = conf_monitor->mon_hsync[count].lo; + } + monitorp->nHsync = count; + for( count = 0 ; + count < conf_monitor->mon_n_vrefresh && count < MAX_VREFRESH; + count++) { + monitorp->vrefresh[count].hi = conf_monitor->mon_vrefresh[count].hi; + monitorp->vrefresh[count].lo = conf_monitor->mon_vrefresh[count].lo; + } + monitorp->nVrefresh = count; + + /* + * first we collect the mode lines from the UseModes directive + */ + while(modeslnk) + { + modes = xf86findModes (modeslnk->ml_modes_str, + xf86configptr->conf_modes_lst); + modeslnk->ml_modes = modes; + + + /* now add the modes found in the modes + section to the list of modes for this + monitor unless it has been added before + because we are reusing the same section + for another screen */ + if (xf86itemNotSublist( + (GenericListPtr)conf_monitor->mon_modeline_lst, + (GenericListPtr)modes->mon_modeline_lst)) { + conf_monitor->mon_modeline_lst = (XF86ConfModeLinePtr) + xf86addListItem( + (GenericListPtr)conf_monitor->mon_modeline_lst, + (GenericListPtr)modes->mon_modeline_lst); + } + modeslnk = modeslnk->list.next; + } + + /* + * we need to hook in the mode lines now + * here both data structures use lists, only our internal one + * is double linked + */ + cmodep = conf_monitor->mon_modeline_lst; + while( cmodep ) { + mode = xnfcalloc(1, sizeof(DisplayModeRec)); + mode->type = 0; + mode->Clock = cmodep->ml_clock; + mode->HDisplay = cmodep->ml_hdisplay; + mode->HSyncStart = cmodep->ml_hsyncstart; + mode->HSyncEnd = cmodep->ml_hsyncend; + mode->HTotal = cmodep->ml_htotal; + mode->VDisplay = cmodep->ml_vdisplay; + mode->VSyncStart = cmodep->ml_vsyncstart; + mode->VSyncEnd = cmodep->ml_vsyncend; + mode->VTotal = cmodep->ml_vtotal; + mode->Flags = cmodep->ml_flags; + mode->HSkew = cmodep->ml_hskew; + mode->VScan = cmodep->ml_vscan; + mode->name = xnfstrdup(cmodep->ml_identifier); + if( last ) { + mode->prev = last; + last->next = mode; + } + else { + /* + * this is the first mode + */ + monitorp->Modes = mode; + mode->prev = NULL; + } + last = mode; + cmodep = (XF86ConfModeLinePtr)cmodep->list.next; + } + if(last){ + last->next = NULL; + } + monitorp->Last = last; + + /* add the (VESA) default modes */ + if (! addDefaultModes(monitorp) ) + return FALSE; + + if (conf_monitor->mon_gamma_red > GAMMA_ZERO) + monitorp->gamma.red = conf_monitor->mon_gamma_red; + if (conf_monitor->mon_gamma_green > GAMMA_ZERO) + monitorp->gamma.green = conf_monitor->mon_gamma_green; + if (conf_monitor->mon_gamma_blue > GAMMA_ZERO) + monitorp->gamma.blue = conf_monitor->mon_gamma_blue; + + /* Check that the gamma values are within range */ + if (monitorp->gamma.red > GAMMA_ZERO && + (monitorp->gamma.red < GAMMA_MIN || + monitorp->gamma.red > GAMMA_MAX)) { + badgamma = monitorp->gamma.red; + } else if (monitorp->gamma.green > GAMMA_ZERO && + (monitorp->gamma.green < GAMMA_MIN || + monitorp->gamma.green > GAMMA_MAX)) { + badgamma = monitorp->gamma.green; + } else if (monitorp->gamma.blue > GAMMA_ZERO && + (monitorp->gamma.blue < GAMMA_MIN || + monitorp->gamma.blue > GAMMA_MAX)) { + badgamma = monitorp->gamma.blue; + } + if (badgamma > GAMMA_ZERO) { + xf86ConfigError("Gamma value %.f is out of range (%.2f - %.1f)\n", + badgamma, GAMMA_MIN, GAMMA_MAX); + return FALSE; + } + + xf86ProcessOptions(-1, monitorp->options, MonitorOptions); + xf86GetOptValBool(MonitorOptions, MON_REDUCEDBLANKING, + &monitorp->reducedblanking); + if (xf86GetOptValFreq(MonitorOptions, MON_MAX_PIX_CLOCK, OPTUNITS_KHZ, + &maxPixClock) == TRUE) { + monitorp->maxPixClock = (int) maxPixClock; + } + + return TRUE; +} + +static int +lookupVisual(const char *visname) +{ + int i; + + if (!visname || !*visname) + return -1; + + for (i = 0; i <= DirectColor; i++) { + if (!xf86nameCompare(visname, xf86VisualNames[i])) + break; + } + + if (i <= DirectColor) + return i; + + return -1; +} + + +static Bool +configDisplay(DispPtr displayp, XF86ConfDisplayPtr conf_display) +{ + int count = 0; + XF86ModePtr modep; + + displayp->frameX0 = conf_display->disp_frameX0; + displayp->frameY0 = conf_display->disp_frameY0; + displayp->virtualX = conf_display->disp_virtualX; + displayp->virtualY = conf_display->disp_virtualY; + displayp->depth = conf_display->disp_depth; + displayp->fbbpp = conf_display->disp_bpp; + displayp->weight.red = conf_display->disp_weight.red; + displayp->weight.green = conf_display->disp_weight.green; + displayp->weight.blue = conf_display->disp_weight.blue; + displayp->blackColour.red = conf_display->disp_black.red; + displayp->blackColour.green = conf_display->disp_black.green; + displayp->blackColour.blue = conf_display->disp_black.blue; + displayp->whiteColour.red = conf_display->disp_white.red; + displayp->whiteColour.green = conf_display->disp_white.green; + displayp->whiteColour.blue = conf_display->disp_white.blue; + displayp->options = conf_display->disp_option_lst; + if (conf_display->disp_visual) { + displayp->defaultVisual = lookupVisual(conf_display->disp_visual); + if (displayp->defaultVisual == -1) { + xf86ConfigError("Invalid visual name: \"%s\"", + conf_display->disp_visual); + return FALSE; + } + } else { + displayp->defaultVisual = -1; + } + + /* + * now hook in the modes + */ + modep = conf_display->disp_mode_lst; + while(modep) { + count++; + modep = (XF86ModePtr)modep->list.next; + } + displayp->modes = xnfalloc((count+1) * sizeof(char*)); + modep = conf_display->disp_mode_lst; + count = 0; + while(modep) { + displayp->modes[count] = modep->mode_name; + count++; + modep = (XF86ModePtr)modep->list.next; + } + displayp->modes[count] = NULL; + + return TRUE; +} + +static Bool +configDevice(GDevPtr devicep, XF86ConfDevicePtr conf_device, Bool active) +{ + int i; + + if (!conf_device) { + return FALSE; + } + + if (active) + xf86Msg(X_CONFIG, "| |-->Device \"%s\"\n", + conf_device->dev_identifier); + else + xf86Msg(X_CONFIG, "|-->Inactive Device \"%s\"\n", + conf_device->dev_identifier); + + devicep->identifier = conf_device->dev_identifier; + devicep->vendor = conf_device->dev_vendor; + devicep->board = conf_device->dev_board; + devicep->chipset = conf_device->dev_chipset; + devicep->ramdac = conf_device->dev_ramdac; + devicep->driver = conf_device->dev_driver; + devicep->active = active; + devicep->videoRam = conf_device->dev_videoram; + devicep->BiosBase = conf_device->dev_bios_base; + devicep->MemBase = conf_device->dev_mem_base; + devicep->IOBase = conf_device->dev_io_base; + devicep->clockchip = conf_device->dev_clockchip; + devicep->busID = conf_device->dev_busid; + devicep->textClockFreq = conf_device->dev_textclockfreq; + devicep->chipID = conf_device->dev_chipid; + devicep->chipRev = conf_device->dev_chiprev; + devicep->options = conf_device->dev_option_lst; + devicep->irq = conf_device->dev_irq; + devicep->screen = conf_device->dev_screen; + + for (i = 0; i < MAXDACSPEEDS; i++) { + if (i < CONF_MAXDACSPEEDS) + devicep->dacSpeeds[i] = conf_device->dev_dacSpeeds[i]; + else + devicep->dacSpeeds[i] = 0; + } + devicep->numclocks = conf_device->dev_clocks; + if (devicep->numclocks > MAXCLOCKS) + devicep->numclocks = MAXCLOCKS; + for (i = 0; i < devicep->numclocks; i++) { + devicep->clock[i] = conf_device->dev_clock[i]; + } + devicep->claimed = FALSE; + + return TRUE; +} + +#ifdef XF86DRI +static void +configDRI(XF86ConfDRIPtr drip) +{ + struct group *grp; + + xf86ConfigDRI.group = -1; + xf86ConfigDRI.mode = 0; + + if (drip) { + if (drip->dri_group_name) { + if ((grp = getgrnam(drip->dri_group_name))) + xf86ConfigDRI.group = grp->gr_gid; + } else { + if (drip->dri_group >= 0) + xf86ConfigDRI.group = drip->dri_group; + } + xf86ConfigDRI.mode = drip->dri_mode; + } +} +#endif + +static void +configExtensions(XF86ConfExtensionsPtr conf_ext) +{ + XF86OptionPtr o; + + if (conf_ext && conf_ext->ext_option_lst) { + for (o = conf_ext->ext_option_lst; o; o = xf86NextOption(o)) { + char *name = xf86OptionName(o); + char *val = xf86OptionValue(o); + char *n; + Bool enable = TRUE; + + /* Handle "No<ExtensionName>" */ + n = xf86NormalizeName(name); + if (strncmp(n, "no", 2) == 0) { + name += 2; + enable = FALSE; + } + + if (!val || + xf86NameCmp(val, "enable") == 0 || + xf86NameCmp(val, "enabled") == 0 || + xf86NameCmp(val, "on") == 0 || + xf86NameCmp(val, "1") == 0 || + xf86NameCmp(val, "yes") == 0 || + xf86NameCmp(val, "true") == 0) { + /* NOTHING NEEDED -- enabling is handled below */ + } else if (xf86NameCmp(val, "disable") == 0 || + xf86NameCmp(val, "disabled") == 0 || + xf86NameCmp(val, "off") == 0 || + xf86NameCmp(val, "0") == 0 || + xf86NameCmp(val, "no") == 0 || + xf86NameCmp(val, "false") == 0) { + enable = !enable; + } else { + xf86Msg(X_WARNING, "Ignoring unrecognized value \"%s\"\n", val); + free(n); + continue; + } + + if (EnableDisableExtension(name, enable)) { + xf86Msg(X_CONFIG, "Extension \"%s\" is %s\n", + name, enable ? "enabled" : "disabled"); + } else { + xf86Msg(X_WARNING, "Ignoring unrecognized extension \"%s\"\n", + name); + } + free(n); + } + } +} + +static Bool +configInput(InputInfoPtr inputp, XF86ConfInputPtr conf_input, MessageType from) +{ + xf86Msg(from, "|-->Input Device \"%s\"\n", conf_input->inp_identifier); + inputp->name = conf_input->inp_identifier; + inputp->driver = conf_input->inp_driver; + inputp->options = conf_input->inp_option_lst; + inputp->attrs = NULL; + + return TRUE; +} + +static Bool +modeIsPresent(DisplayModePtr mode, MonPtr monitorp) +{ + DisplayModePtr knownmodes = monitorp->Modes; + + /* all I can think of is a linear search... */ + while(knownmodes != NULL) + { + if(!strcmp(mode->name, knownmodes->name) && + !(knownmodes->type & M_T_DEFAULT)) + return TRUE; + knownmodes = knownmodes->next; + } + return FALSE; +} + +static Bool +addDefaultModes(MonPtr monitorp) +{ + DisplayModePtr mode; + DisplayModePtr last = monitorp->Last; + int i = 0; + + for (i = 0; i < xf86NumDefaultModes; i++) + { + mode = xf86DuplicateMode(&xf86DefaultModes[i]); + if (!modeIsPresent(mode, monitorp)) + { + monitorp->Modes = xf86ModesAdd(monitorp->Modes, mode); + last = mode; + } else { + free(mode); + } + } + monitorp->Last = last; + + return TRUE; +} + +static void +checkInput(serverLayoutPtr layout, Bool implicit_layout) { + checkCoreInputDevices(layout, implicit_layout); + + /* Unless we're forcing input devices, disable mouse/kbd devices in the + * config. Otherwise the same physical device is added multiple times, + * leading to duplicate events. + */ + if (!xf86Info.forceInputDevices && layout->inputs) + { + InputInfoPtr *dev = layout->inputs; + BOOL warned = FALSE; + + while(*dev) + { + if (strcmp((*dev)->driver, "kbd") == 0 || + strcmp((*dev)->driver, "mouse") == 0 || + strcmp((*dev)->driver, "vmmouse") == 0) + { + InputInfoPtr *current; + if (!warned) + { + xf86Msg(X_WARNING, "Hotplugging is on, devices using " + "drivers 'kbd', 'mouse' or 'vmmouse' will be disabled.\n"); + warned = TRUE; + } + + xf86Msg(X_WARNING, "Disabling %s\n", (*dev)->name); + + current = dev; + free(*dev); + + do { + *current = *(current + 1); + current++; + } while(*current); + } else + dev++; + } + } +} + +/* + * load the config file and fill the global data structure + */ +ConfigStatus +xf86HandleConfigFile(Bool autoconfig) +{ + const char *filename, *dirname, *sysdirname; + char *filesearch, *dirsearch; + MessageType filefrom = X_DEFAULT; + MessageType dirfrom = X_DEFAULT; + char *scanptr; + Bool singlecard = 0; + Bool implicit_layout = FALSE; + + if (!autoconfig) { + if (getuid() == 0) { + filesearch = ROOT_CONFIGPATH; + dirsearch = ROOT_CONFIGDIRPATH; + } else { + filesearch = USER_CONFIGPATH; + dirsearch = USER_CONFIGDIRPATH; + } + + if (xf86ConfigFile) + filefrom = X_CMDLINE; + if (xf86ConfigDir) + dirfrom = X_CMDLINE; + + xf86initConfigFiles(); + sysdirname = xf86openConfigDirFiles(SYS_CONFIGDIRPATH, NULL, + PROJECTROOT); + dirname = xf86openConfigDirFiles(dirsearch, xf86ConfigDir, PROJECTROOT); + filename = xf86openConfigFile(filesearch, xf86ConfigFile, PROJECTROOT); + if (filename) { + xf86MsgVerb(filefrom, 0, "Using config file: \"%s\"\n", filename); + xf86ConfigFile = xnfstrdup(filename); + } else { + if (xf86ConfigFile) + xf86Msg(X_ERROR, "Unable to locate/open config file: \"%s\"\n", + xf86ConfigFile); + } + if (dirname) { + xf86MsgVerb(dirfrom, 0, "Using config directory: \"%s\"\n", + dirname); + xf86ConfigDir = xnfstrdup(dirname); + } else { + if (xf86ConfigDir) + xf86Msg(X_ERROR, + "Unable to locate/open config directory: \"%s\"\n", + xf86ConfigDir); + } + if (sysdirname) + xf86MsgVerb(X_DEFAULT, 0, "Using system config directory \"%s\"\n", + sysdirname); + if (!filename && !dirname && !sysdirname) + return CONFIG_NOFILE; + } + + if ((xf86configptr = xf86readConfigFile ()) == NULL) { + xf86Msg(X_ERROR, "Problem parsing the config file\n"); + return CONFIG_PARSE_ERROR; + } + xf86closeConfigFile (); + + /* Initialise a few things. */ + + /* + * now we convert part of the information contained in the parser + * structures into our own structures. + * The important part here is to figure out which Screen Sections + * in the XF86Config file are active so that we can piece together + * the modes that we need later down the road. + * And while we are at it, we'll decode the rest of the stuff as well + */ + + /* First check if a layout section is present, and if it is valid. */ + + if (xf86configptr->conf_layout_lst == NULL || xf86ScreenName != NULL) { + if (xf86ScreenName == NULL) { + xf86Msg(X_DEFAULT, + "No Layout section. Using the first Screen section.\n"); + } + if (!configImpliedLayout(&xf86ConfigLayout, + xf86configptr->conf_screen_lst, + xf86configptr)) { + xf86Msg(X_ERROR, "Unable to determine the screen layout\n"); + return CONFIG_PARSE_ERROR; + } + implicit_layout = TRUE; + } else { + if (xf86configptr->conf_flags != NULL) { + char *dfltlayout = NULL; + pointer optlist = xf86configptr->conf_flags->flg_option_lst; + + if (optlist && xf86FindOption(optlist, "defaultserverlayout")) + dfltlayout = xf86SetStrOption(optlist, "defaultserverlayout", NULL); + if (!configLayout(&xf86ConfigLayout, xf86configptr->conf_layout_lst, + dfltlayout)) { + xf86Msg(X_ERROR, "Unable to determine the screen layout\n"); + return CONFIG_PARSE_ERROR; + } + } else { + if (!configLayout(&xf86ConfigLayout, xf86configptr->conf_layout_lst, + NULL)) { + xf86Msg(X_ERROR, "Unable to determine the screen layout\n"); + return CONFIG_PARSE_ERROR; + } + } + } + + xf86ProcessOptions(-1, xf86ConfigLayout.options, LayoutOptions); + + if ((scanptr = xf86GetOptValString(LayoutOptions, LAYOUT_ISOLATEDEVICE))) { + ; /* IsolateDevice specified; overrides SingleCard */ + } else { + xf86GetOptValBool(LayoutOptions, LAYOUT_SINGLECARD, &singlecard); + if (singlecard) + scanptr = xf86ConfigLayout.screens->screen->device->busID; + } + if (scanptr) { + if (strncmp(scanptr, "PCI:", 4) != 0) { + xf86Msg(X_WARNING, "Bus types other than PCI not yet isolable.\n" + "\tIgnoring IsolateDevice option.\n"); + } else + xf86PciIsolateDevice(scanptr); + } + + /* Now process everything else */ + if (!configServerFlags(xf86configptr->conf_flags,xf86ConfigLayout.options)){ + ErrorF ("Problem when converting the config data structures\n"); + return CONFIG_PARSE_ERROR; + } + + configFiles(xf86configptr->conf_files); + configExtensions(xf86configptr->conf_extensions); +#ifdef XF86DRI + configDRI(xf86configptr->conf_dri); +#endif + + checkInput(&xf86ConfigLayout, implicit_layout); + + /* + * Handle some command line options that can override some of the + * ServerFlags settings. + */ +#ifdef XF86VIDMODE + if (xf86VidModeDisabled) + xf86Info.vidModeEnabled = FALSE; + if (xf86VidModeAllowNonLocal) + xf86Info.vidModeAllowNonLocal = TRUE; +#endif + + if (xf86AllowMouseOpenFail) + xf86Info.allowMouseOpenFail = TRUE; + + return CONFIG_OK; +} + +Bool +xf86PathIsSafe(const char *path) +{ + return (xf86pathIsSafe(path) != 0); +} diff --git a/hw/xfree86/common/xf86Config.h b/hw/xfree86/common/xf86Config.h new file mode 100644 index 0000000..de28704 --- /dev/null +++ b/hw/xfree86/common/xf86Config.h @@ -0,0 +1,72 @@ + +/* + * Copyright (c) 1997-2000 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#ifndef _xf86_config_h +#define _xf86_config_h + +#include "xf86Optrec.h" +#include "xf86Parser.h" +#include "xf86str.h" + +#ifdef HAVE_PARSER_DECLS +/* + * global structure that holds the result of parsing the config file + */ +extern _X_EXPORT XF86ConfigPtr xf86configptr; +#endif + +typedef enum _ConfigStatus { + CONFIG_OK = 0, + CONFIG_PARSE_ERROR, + CONFIG_NOFILE +} ConfigStatus; + +typedef struct _ModuleDefault { + char *name; + Bool toLoad; + XF86OptionPtr load_opt; +} ModuleDefault; + +/* + * prototypes + */ +char ** xf86ModulelistFromConfig(pointer **); +char ** xf86DriverlistFromConfig(void); +char ** xf86DriverlistFromCompile(void); +char ** xf86InputDriverlistFromConfig(void); +Bool xf86BuiltinInputDriver(const char *); +ConfigStatus xf86HandleConfigFile(Bool); + +Bool xf86AutoConfig(void); +GDevPtr autoConfigDevice(GDevPtr preconf_device); + +#endif /* _xf86_config_h */ diff --git a/hw/xfree86/common/xf86Configure.c b/hw/xfree86/common/xf86Configure.c new file mode 100644 index 0000000..883c48c --- /dev/null +++ b/hw/xfree86/common/xf86Configure.c @@ -0,0 +1,765 @@ +/* + * Copyright 2000-2002 by Alan Hourihane, Flint Mountain, North Wales. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Alan Hourihane not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Alan Hourihane makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Author: Alan Hourihane, alanh@fairlite.demon.co.uk + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "xf86.h" +#include "xf86Config.h" +#include "xf86_OSlib.h" +#include "xf86Priv.h" +#define IN_XSERVER +#include "Configint.h" +#include "xf86DDC.h" +#include "xf86pciBus.h" +#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) +#include "xf86Bus.h" +#include "xf86Sbus.h" +#endif + +typedef struct _DevToConfig { + GDevRec GDev; + struct pci_device * pVideo; +#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) + sbusDevicePtr sVideo; +#endif + int iDriver; +} DevToConfigRec, *DevToConfigPtr; + +static DevToConfigPtr DevToConfig = NULL; +static int nDevToConfig = 0, CurrentDriver; + +xf86MonPtr ConfiguredMonitor; +Bool xf86DoConfigurePass1 = TRUE; +static Bool foundMouse = FALSE; + +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) +static char *DFLT_MOUSE_DEV = "/dev/sysmouse"; +static char *DFLT_MOUSE_PROTO = "auto"; +#elif defined(linux) +static char DFLT_MOUSE_DEV[] = "/dev/input/mice"; +static char DFLT_MOUSE_PROTO[] = "auto"; +#else +static char *DFLT_MOUSE_DEV = "/dev/mouse"; +static char *DFLT_MOUSE_PROTO = "auto"; +#endif + +/* + * This is called by the driver, either through xf86Match???Instances() or + * directly. We allocate a GDevRec and fill it in as much as we can, letting + * the caller fill in the rest and/or change it as it sees fit. + */ +GDevPtr +xf86AddBusDeviceToConfigure(const char *driver, BusType bus, void *busData, int chipset) +{ + int ret, i, j; + + if (!xf86DoConfigure || !xf86DoConfigurePass1) + return NULL; + + /* Check for duplicates */ + for (i = 0; i < nDevToConfig; i++) { + switch (bus) { + case BUS_PCI: + ret = xf86PciConfigure(busData, DevToConfig[i].pVideo); + break; +#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) + case BUS_SBUS: + ret = xf86SbusConfigure(busData, DevToConfig[i].sVideo); + break; +#endif + default: + return NULL; + } + if (ret == 0) + goto out; + } + + /* Allocate new structure occurrence */ + i = nDevToConfig++; + DevToConfig = + xnfrealloc(DevToConfig, nDevToConfig * sizeof(DevToConfigRec)); + memset(DevToConfig + i, 0, sizeof(DevToConfigRec)); + + DevToConfig[i].GDev.chipID = + DevToConfig[i].GDev.chipRev = DevToConfig[i].GDev.irq = -1; + + DevToConfig[i].iDriver = CurrentDriver; + + /* Fill in what we know, converting the driver name to lower case */ + DevToConfig[i].GDev.driver = xnfalloc(strlen(driver) + 1); + for (j = 0; (DevToConfig[i].GDev.driver[j] = tolower(driver[j])); j++); + + switch (bus) { + case BUS_PCI: + xf86PciConfigureNewDev(busData, DevToConfig[i].pVideo, + &DevToConfig[i].GDev, &chipset); + break; +#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) + case BUS_SBUS: + xf86SbusConfigureNewDev(busData, DevToConfig[i].sVideo, + &DevToConfig[i].GDev); + break; +#endif + default: + break; + } + + /* Get driver's available options */ + if (xf86DriverList[CurrentDriver]->AvailableOptions) + DevToConfig[i].GDev.options = (OptionInfoPtr) + (*xf86DriverList[CurrentDriver]->AvailableOptions)(chipset, + bus); + + return &DevToConfig[i].GDev; + +out: + return NULL; +} + +static XF86ConfInputPtr +configureInputSection (void) +{ + XF86ConfInputPtr mouse = NULL; + parsePrologue (XF86ConfInputPtr, XF86ConfInputRec) + + ptr->inp_identifier = "Keyboard0"; + ptr->inp_driver = "kbd"; + ptr->list.next = NULL; + + /* Crude mechanism to auto-detect mouse (os dependent) */ + { + int fd; +#ifdef WSCONS_SUPPORT + fd = open("/dev/wsmouse", 0); + if (fd >= 0) { + DFLT_MOUSE_DEV = "/dev/wsmouse"; + DFLT_MOUSE_PROTO = "wsmouse"; + close(fd); + } else { + ErrorF("cannot open /dev/wsmouse\n"); + } +#endif + + fd = open(DFLT_MOUSE_DEV, 0); + if (fd != -1) { + foundMouse = TRUE; + close(fd); + } + } + + mouse = calloc(1, sizeof(XF86ConfInputRec)); + mouse->inp_identifier = "Mouse0"; + mouse->inp_driver = "mouse"; + mouse->inp_option_lst = + xf86addNewOption(mouse->inp_option_lst, strdup("Protocol"), + strdup(DFLT_MOUSE_PROTO)); + mouse->inp_option_lst = + xf86addNewOption(mouse->inp_option_lst, strdup("Device"), + strdup(DFLT_MOUSE_DEV)); + mouse->inp_option_lst = + xf86addNewOption(mouse->inp_option_lst, strdup("ZAxisMapping"), + strdup("4 5 6 7")); + ptr = (XF86ConfInputPtr)xf86addListItem((glp)ptr, (glp)mouse); + return ptr; +} + +static XF86ConfScreenPtr +configureScreenSection (int screennum) +{ + int i; + int depths[] = { 1, 4, 8, 15, 16, 24/*, 32*/ }; + parsePrologue (XF86ConfScreenPtr, XF86ConfScreenRec) + + XNFasprintf(&ptr->scrn_identifier, "Screen%d", screennum); + XNFasprintf(&ptr->scrn_monitor_str, "Monitor%d", screennum); + XNFasprintf(&ptr->scrn_device_str, "Card%d", screennum); + + for (i=0; i<sizeof(depths)/sizeof(depths[0]); i++) + { + XF86ConfDisplayPtr display; + + display = calloc(1, sizeof(XF86ConfDisplayRec)); + display->disp_depth = depths[i]; + display->disp_black.red = display->disp_white.red = -1; + display->disp_black.green = display->disp_white.green = -1; + display->disp_black.blue = display->disp_white.blue = -1; + ptr->scrn_display_lst = (XF86ConfDisplayPtr)xf86addListItem( + (glp)ptr->scrn_display_lst, (glp)display); + } + + return ptr; +} + +static const char* +optionTypeToString(OptionValueType type) +{ + switch (type) { + case OPTV_NONE: + return ""; + case OPTV_INTEGER: + return "<i>"; + case OPTV_STRING: + return "<str>"; + case OPTV_ANYSTR: + return "[<str>]"; + case OPTV_REAL: + return "<f>"; + case OPTV_BOOLEAN: + return "[<bool>]"; + case OPTV_FREQ: + return "<freq>"; + case OPTV_PERCENT: + return "<percent>"; + default: + return ""; + } +} + +static XF86ConfDevicePtr +configureDeviceSection (int screennum) +{ + OptionInfoPtr p; + int i = 0; + parsePrologue (XF86ConfDevicePtr, XF86ConfDeviceRec) + + /* Move device info to parser structure */ + if (asprintf(&ptr->dev_identifier, "Card%d", screennum) == -1) + ptr->dev_identifier = NULL; + ptr->dev_chipset = DevToConfig[screennum].GDev.chipset; + ptr->dev_busid = DevToConfig[screennum].GDev.busID; + ptr->dev_driver = DevToConfig[screennum].GDev.driver; + ptr->dev_ramdac = DevToConfig[screennum].GDev.ramdac; + for (i = 0; (i < MAXDACSPEEDS) && (i < CONF_MAXDACSPEEDS); i++) + ptr->dev_dacSpeeds[i] = DevToConfig[screennum].GDev.dacSpeeds[i]; + ptr->dev_videoram = DevToConfig[screennum].GDev.videoRam; + ptr->dev_textclockfreq = DevToConfig[screennum].GDev.textClockFreq; + ptr->dev_bios_base = DevToConfig[screennum].GDev.BiosBase; + ptr->dev_mem_base = DevToConfig[screennum].GDev.MemBase; + ptr->dev_io_base = DevToConfig[screennum].GDev.IOBase; + ptr->dev_clockchip = DevToConfig[screennum].GDev.clockchip; + for (i = 0; (i < MAXCLOCKS) && (i < DevToConfig[screennum].GDev.numclocks); i++) + ptr->dev_clock[i] = DevToConfig[screennum].GDev.clock[i]; + ptr->dev_clocks = i; + ptr->dev_chipid = DevToConfig[screennum].GDev.chipID; + ptr->dev_chiprev = DevToConfig[screennum].GDev.chipRev; + ptr->dev_irq = DevToConfig[screennum].GDev.irq; + + /* Make sure older drivers don't segv */ + if (DevToConfig[screennum].GDev.options) { + /* Fill in the available driver options for people to use */ + const char *descrip = + " ### Available Driver options are:-\n" + " ### Values: <i>: integer, <f>: float, " + "<bool>: \"True\"/\"False\",\n" + " ### <string>: \"String\", <freq>: \"<f> Hz/kHz/MHz\",\n" + " ### <percent>: \"<f>%\"\n" + " ### [arg]: arg optional\n"; + ptr->dev_comment = strdup(descrip); + if (ptr->dev_comment) { + for (p = DevToConfig[screennum].GDev.options; + p->name != NULL; p++) { + char *p_e; + const char *prefix = " #Option "; + const char *middle = " \t# "; + const char *suffix = "\n"; + const char *opttype = optionTypeToString(p->type); + char *optname; + int len = strlen(ptr->dev_comment) + strlen(prefix) + + strlen(middle) + strlen(suffix) + 1; + + if (asprintf(&optname, "\"%s\"", p->name) == -1) + break; + + len += max(20, strlen(optname)); + len += strlen(opttype); + + ptr->dev_comment = realloc(ptr->dev_comment, len); + if (!ptr->dev_comment) + break; + p_e = ptr->dev_comment + strlen(ptr->dev_comment); + sprintf(p_e, "%s%-20s%s%s%s", prefix, optname, middle, + opttype, suffix); + free(optname); + } + } + } + + return ptr; +} + +static XF86ConfLayoutPtr +configureLayoutSection (void) +{ + int scrnum = 0; + parsePrologue (XF86ConfLayoutPtr, XF86ConfLayoutRec) + + ptr->lay_identifier = "X.org Configured"; + + { + XF86ConfInputrefPtr iptr; + + iptr = malloc (sizeof (XF86ConfInputrefRec)); + iptr->list.next = NULL; + iptr->iref_option_lst = NULL; + iptr->iref_inputdev_str = "Mouse0"; + iptr->iref_option_lst = + xf86addNewOption (iptr->iref_option_lst, strdup("CorePointer"), NULL); + ptr->lay_input_lst = (XF86ConfInputrefPtr) + xf86addListItem ((glp) ptr->lay_input_lst, (glp) iptr); + } + + { + XF86ConfInputrefPtr iptr; + + iptr = malloc (sizeof (XF86ConfInputrefRec)); + iptr->list.next = NULL; + iptr->iref_option_lst = NULL; + iptr->iref_inputdev_str = "Keyboard0"; + iptr->iref_option_lst = + xf86addNewOption (iptr->iref_option_lst, strdup("CoreKeyboard"), NULL); + ptr->lay_input_lst = (XF86ConfInputrefPtr) + xf86addListItem ((glp) ptr->lay_input_lst, (glp) iptr); + } + + for (scrnum = 0; scrnum < nDevToConfig; scrnum++) { + XF86ConfAdjacencyPtr aptr; + + aptr = malloc (sizeof (XF86ConfAdjacencyRec)); + aptr->list.next = NULL; + aptr->adj_x = 0; + aptr->adj_y = 0; + aptr->adj_scrnum = scrnum; + XNFasprintf(&aptr->adj_screen_str, "Screen%d", scrnum); + if (scrnum == 0) { + aptr->adj_where = CONF_ADJ_ABSOLUTE; + aptr->adj_refscreen = NULL; + } + else { + aptr->adj_where = CONF_ADJ_RIGHTOF; + XNFasprintf(&aptr->adj_refscreen, "Screen%d", scrnum - 1); + } + ptr->lay_adjacency_lst = + (XF86ConfAdjacencyPtr)xf86addListItem((glp)ptr->lay_adjacency_lst, + (glp)aptr); + } + + return ptr; +} + +static XF86ConfFlagsPtr +configureFlagsSection (void) +{ + parsePrologue (XF86ConfFlagsPtr, XF86ConfFlagsRec) + + return ptr; +} + +static XF86ConfModulePtr +configureModuleSection (void) +{ + char **elist, **el; + /* Find the list of extension & font modules. */ + const char *esubdirs[] = { + "extensions", + "fonts", + NULL + }; + parsePrologue (XF86ConfModulePtr, XF86ConfModuleRec) + + elist = LoaderListDirs(esubdirs, NULL); + if (elist) { + for (el = elist; *el; el++) { + XF86LoadPtr module; + + module = calloc(1, sizeof(XF86LoadRec)); + module->load_name = *el; + ptr->mod_load_lst = (XF86LoadPtr)xf86addListItem( + (glp)ptr->mod_load_lst, (glp)module); + } + free(elist); + } + + return ptr; +} + +static XF86ConfFilesPtr +configureFilesSection (void) +{ + parsePrologue (XF86ConfFilesPtr, XF86ConfFilesRec) + + if (xf86ModulePath) + ptr->file_modulepath = strdup(xf86ModulePath); + if (defaultFontPath) + ptr->file_fontpath = strdup(defaultFontPath); + + return ptr; +} + +static XF86ConfMonitorPtr +configureMonitorSection (int screennum) +{ + parsePrologue (XF86ConfMonitorPtr, XF86ConfMonitorRec) + + XNFasprintf(&ptr->mon_identifier, "Monitor%d", screennum); + ptr->mon_vendor = strdup("Monitor Vendor"); + ptr->mon_modelname = strdup("Monitor Model"); + + return ptr; +} + +/* Initialize Configure Monitor from Detailed Timing Block */ +static void handle_detailed_input(struct detailed_monitor_section *det_mon, + void *data) +{ + XF86ConfMonitorPtr ptr = (XF86ConfMonitorPtr) data; + + switch (det_mon->type) { + case DS_NAME: + ptr->mon_modelname = realloc(ptr->mon_modelname, + strlen((char*)(det_mon->section.name)) + + 1); + strcpy(ptr->mon_modelname, + (char*)(det_mon->section.name)); + break; + case DS_RANGES: + ptr->mon_hsync[ptr->mon_n_hsync].lo = + det_mon->section.ranges.min_h; + ptr->mon_hsync[ptr->mon_n_hsync].hi = + det_mon->section.ranges.max_h; + ptr->mon_n_vrefresh = 1; + ptr->mon_vrefresh[ptr->mon_n_hsync].lo = + det_mon->section.ranges.min_v; + ptr->mon_vrefresh[ptr->mon_n_hsync].hi = + det_mon->section.ranges.max_v; + ptr->mon_n_hsync++; + default: + break; + } +} + +static XF86ConfMonitorPtr +configureDDCMonitorSection (int screennum) +{ + int len, mon_width, mon_height; +#define displaySizeMaxLen 80 + char displaySize_string[displaySizeMaxLen]; + int displaySizeLen; + + parsePrologue (XF86ConfMonitorPtr, XF86ConfMonitorRec) + + XNFasprintf(&ptr->mon_identifier, "Monitor%d", screennum); + ptr->mon_vendor = strdup(ConfiguredMonitor->vendor.name); + XNFasprintf(&ptr->mon_modelname, "%x", ConfiguredMonitor->vendor.prod_id); + + /* features in centimetres, we want millimetres */ + mon_width = 10 * ConfiguredMonitor->features.hsize ; + mon_height = 10 * ConfiguredMonitor->features.vsize ; + +#ifdef CONFIGURE_DISPLAYSIZE + ptr->mon_width = mon_width; + ptr->mon_height = mon_height; +#else + if (mon_width && mon_height) { + /* when values available add DisplaySize option AS A COMMENT */ + + displaySizeLen = snprintf(displaySize_string, displaySizeMaxLen, + "\t#DisplaySize\t%5d %5d\t# mm\n", + mon_width, mon_height); + + if (displaySizeLen>0 && displaySizeLen<displaySizeMaxLen) { + if (ptr->mon_comment) { + len = strlen(ptr->mon_comment); + } else { + len = 0; + } + if ((ptr->mon_comment = + realloc(ptr->mon_comment, len + strlen(displaySize_string) + 1))) { + strcpy(ptr->mon_comment + len, displaySize_string); + } + } + } +#endif /* def CONFIGURE_DISPLAYSIZE */ + + xf86ForEachDetailedBlock(ConfiguredMonitor, handle_detailed_input, + ptr); + + if (ConfiguredMonitor->features.dpms) { + ptr->mon_option_lst = xf86addNewOption(ptr->mon_option_lst, strdup("DPMS"), NULL); + } + + return ptr; +} + +#if !defined(PATH_MAX) +# define PATH_MAX 1024 +#endif + +void +DoConfigure(void) +{ + int i,j, screennum = -1; + char *home = NULL; + char filename[PATH_MAX]; + char *addslash = ""; + XF86ConfigPtr xf86config = NULL; + char **vlist, **vl; + int *dev2screen; + + vlist = xf86DriverlistFromCompile(); + + if (!vlist) { + ErrorF("Missing output drivers. Configuration failed.\n"); + goto bail; + } + + ErrorF("List of video drivers:\n"); + for (vl = vlist; *vl; vl++) + ErrorF("\t%s\n", *vl); + + /* Load all the drivers that were found. */ + xf86LoadModules(vlist, NULL); + + free(vlist); + + for (i = 0; i < xf86NumDrivers; i++) { + xorgHWFlags flags; + if (!xf86DriverList[i]->driverFunc + || !xf86DriverList[i]->driverFunc(NULL, + GET_REQUIRED_HW_INTERFACES, + &flags) + || NEED_IO_ENABLED(flags)) { + xorgHWAccess = TRUE; + break; + } + } + /* Enable full I/O access */ + if (xorgHWAccess) { + if(!xf86EnableIO()) + /* oops, we have failed */ + xorgHWAccess = FALSE; + } + + /* Create XF86Config file structure */ + xf86config = calloc(1, sizeof(XF86ConfigRec)); + + /* Call all of the probe functions, reporting the results. */ + for (CurrentDriver = 0; CurrentDriver < xf86NumDrivers; CurrentDriver++) { + xorgHWFlags flags; + Bool found_screen; + DriverRec * const drv = xf86DriverList[CurrentDriver]; + + if (!xorgHWAccess) { + if (!drv->driverFunc + || !drv->driverFunc( NULL, GET_REQUIRED_HW_INTERFACES, &flags ) + || NEED_IO_ENABLED(flags)) + continue; + } + + found_screen = xf86CallDriverProbe( drv, TRUE ); + if ( found_screen && drv->Identify ) { + (*drv->Identify)(0); + } + } + + if (nDevToConfig <= 0) { + ErrorF("No devices to configure. Configuration failed.\n"); + goto bail; + } + + /* Add device, monitor and screen sections for detected devices */ + for (screennum = 0; screennum < nDevToConfig; screennum++) { + XF86ConfDevicePtr DevicePtr; + XF86ConfMonitorPtr MonitorPtr; + XF86ConfScreenPtr ScreenPtr; + + DevicePtr = configureDeviceSection(screennum); + xf86config->conf_device_lst = (XF86ConfDevicePtr)xf86addListItem( + (glp)xf86config->conf_device_lst, (glp)DevicePtr); + MonitorPtr = configureMonitorSection(screennum); + xf86config->conf_monitor_lst = (XF86ConfMonitorPtr)xf86addListItem( + (glp)xf86config->conf_monitor_lst, (glp)MonitorPtr); + ScreenPtr = configureScreenSection(screennum); + xf86config->conf_screen_lst = (XF86ConfScreenPtr)xf86addListItem( + (glp)xf86config->conf_screen_lst, (glp)ScreenPtr); + } + + xf86config->conf_files = configureFilesSection(); + xf86config->conf_modules = configureModuleSection(); + xf86config->conf_flags = configureFlagsSection(); + xf86config->conf_videoadaptor_lst = NULL; + xf86config->conf_modes_lst = NULL; + xf86config->conf_vendor_lst = NULL; + xf86config->conf_dri = NULL; + xf86config->conf_input_lst = configureInputSection(); + xf86config->conf_layout_lst = configureLayoutSection(); + + home = getenv("HOME"); + if ((home == NULL) || (home[0] == '\0')) { + home = "/"; + } else { + /* Determine if trailing slash is present or needed */ + int l = strlen(home); + + if (home[l-1] != '/') { + addslash = "/"; + } + } + + snprintf(filename, sizeof(filename), "%s%s" XF86CONFIGFILE ".new", + home, addslash); + + if (xf86writeConfigFile(filename, xf86config) == 0) { + xf86Msg(X_ERROR, "Unable to write config file: \"%s\": %s\n", + filename, strerror(errno)); + goto bail; + } + + xf86DoConfigurePass1 = FALSE; + /* Try to get DDC information filled in */ + xf86ConfigFile = filename; + if (xf86HandleConfigFile(FALSE) != CONFIG_OK) { + goto bail; + } + + xf86DoConfigurePass1 = FALSE; + + dev2screen = xnfcalloc(1,xf86NumDrivers*sizeof(int)); + + { + Bool *driverProbed = xnfcalloc(1,xf86NumDrivers*sizeof(Bool)); + for (screennum = 0; screennum < nDevToConfig; screennum++) { + int k,l,n,oldNumScreens; + + i = DevToConfig[screennum].iDriver; + + if (driverProbed[i]) continue; + driverProbed[i] = TRUE; + + oldNumScreens = xf86NumScreens; + + xf86CallDriverProbe( xf86DriverList[i], FALSE ); + + /* reorder */ + k = screennum > 0 ? screennum : 1; + for (l = oldNumScreens; l < xf86NumScreens; l++) { + /* is screen primary? */ + Bool primary = FALSE; + for (n = 0; n<xf86Screens[l]->numEntities; n++) { + if (xf86IsEntityPrimary(xf86Screens[l]->entityList[n])) { + dev2screen[0] = l; + primary = TRUE; + break; + } + } + if (primary) continue; + /* not primary: assign it to next device of same driver */ + /* + * NOTE: we assume that devices in DevToConfig + * and xf86Screens[] have the same order except + * for the primary device which always comes first. + */ + for (; k < nDevToConfig; k++) { + if (DevToConfig[k].iDriver == i) { + dev2screen[k++] = l; + break; + } + } + } + } + free(driverProbed); + } + + + if (nDevToConfig != xf86NumScreens) { + ErrorF("Number of created screens does not match number of detected" + " devices.\n Configuration failed.\n"); + goto bail; + } + + xf86PostProbe(); + + for (j = 0; j < xf86NumScreens; j++) { + xf86Screens[j]->scrnIndex = j; + } + + xf86freeMonitorList(xf86config->conf_monitor_lst); + xf86config->conf_monitor_lst = NULL; + xf86freeScreenList(xf86config->conf_screen_lst); + xf86config->conf_screen_lst = NULL; + for (j = 0; j < xf86NumScreens; j++) { + XF86ConfMonitorPtr MonitorPtr; + XF86ConfScreenPtr ScreenPtr; + + ConfiguredMonitor = NULL; + + if ((*xf86Screens[dev2screen[j]]->PreInit)(xf86Screens[dev2screen[j]], + PROBE_DETECT) && + ConfiguredMonitor) { + MonitorPtr = configureDDCMonitorSection(j); + } else { + MonitorPtr = configureMonitorSection(j); + } + ScreenPtr = configureScreenSection(j); + xf86config->conf_monitor_lst = (XF86ConfMonitorPtr)xf86addListItem( + (glp)xf86config->conf_monitor_lst, (glp)MonitorPtr); + xf86config->conf_screen_lst = (XF86ConfScreenPtr)xf86addListItem( + (glp)xf86config->conf_screen_lst, (glp)ScreenPtr); + } + + if (xf86writeConfigFile(filename, xf86config) == 0) { + xf86Msg(X_ERROR, "Unable to write config file: \"%s\": %s\n", + filename, strerror(errno)); + goto bail; + } + + ErrorF("\n"); + + if (!foundMouse) { + ErrorF("\n"__XSERVERNAME__" is not able to detect your mouse.\n" + "Edit the file and correct the Device.\n"); + } else { + ErrorF("\n"__XSERVERNAME__" detected your mouse at device %s.\n" + "Please check your config if the mouse is still not\n" + "operational, as by default "__XSERVERNAME__ + " tries to autodetect\n" + "the protocol.\n",DFLT_MOUSE_DEV); + } + + if (xf86NumScreens > 1) { + ErrorF("\n"__XSERVERNAME__ + " has configured a multihead system, please check your config.\n"); + } + + ErrorF("\nYour %s file is %s\n\n", XF86CONFIGFILE ,filename); + ErrorF("To test the server, run 'X -config %s'\n\n", filename); + +bail: + OsCleanup(TRUE); + AbortDDX(); + fflush(stderr); + exit(0); +} diff --git a/hw/xfree86/common/xf86Cursor.c b/hw/xfree86/common/xf86Cursor.c new file mode 100644 index 0000000..929f047 --- /dev/null +++ b/hw/xfree86/common/xf86Cursor.c @@ -0,0 +1,860 @@ +/* + * Copyright (c) 1994-2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xmd.h> +#include "input.h" +#include "cursor.h" +#include "mipointer.h" +#include "scrnintstr.h" +#include "globals.h" + +#include "compiler.h" + +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSproc.h" + +#include <X11/extensions/XIproto.h> +#include "xf86Xinput.h" + +#ifdef XFreeXDGA +#include "dgaproc.h" +#endif + +typedef struct _xf86EdgeRec { + short screen; + short start; + short end; + DDXPointRec offset; + struct _xf86EdgeRec *next; +} xf86EdgeRec, *xf86EdgePtr; + +typedef struct { + xf86EdgePtr left, right, up, down; +} xf86ScreenLayoutRec, *xf86ScreenLayoutPtr; + +static Bool xf86CursorOffScreen(ScreenPtr *pScreen, int *x, int *y); +static void xf86CrossScreen(ScreenPtr pScreen, Bool entering); +static void xf86WarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y); + +static void xf86PointerMoved(int scrnIndex, int x, int y); + +static miPointerScreenFuncRec xf86PointerScreenFuncs = { + xf86CursorOffScreen, + xf86CrossScreen, + xf86WarpCursor, + /* let miPointerInitialize take care of these */ + NULL, + NULL +}; + +static xf86ScreenLayoutRec xf86ScreenLayout[MAXSCREENS]; + +static Bool HardEdges; + +/* + * xf86InitViewport -- + * Initialize paning & zooming parameters, so that a driver must only + * check what resolutions are possible and whether the virtual area + * is valid if specified. + */ + +void +xf86InitViewport(ScrnInfoPtr pScr) +{ + + pScr->PointerMoved = xf86PointerMoved; + + /* + * Compute the initial Viewport if necessary + */ + if (pScr->display) { + if (pScr->display->frameX0 < 0) { + pScr->frameX0 = (pScr->virtualX - pScr->modes->HDisplay) / 2; + pScr->frameY0 = (pScr->virtualY - pScr->modes->VDisplay) / 2; + } else { + pScr->frameX0 = pScr->display->frameX0; + pScr->frameY0 = pScr->display->frameY0; + } + } + + pScr->frameX1 = pScr->frameX0 + pScr->modes->HDisplay - 1; + pScr->frameY1 = pScr->frameY0 + pScr->modes->VDisplay - 1; + + /* + * Now adjust the initial Viewport, so it lies within the virtual area + */ + if (pScr->frameX1 >= pScr->virtualX) + { + pScr->frameX0 = pScr->virtualX - pScr->modes->HDisplay; + pScr->frameX1 = pScr->frameX0 + pScr->modes->HDisplay - 1; + } + + if (pScr->frameY1 >= pScr->virtualY) + { + pScr->frameY0 = pScr->virtualY - pScr->modes->VDisplay; + pScr->frameY1 = pScr->frameY0 + pScr->modes->VDisplay - 1; + } +} + + +/* + * xf86SetViewport -- + * Scroll the visual part of the screen so the pointer is visible. + */ + +void +xf86SetViewport(ScreenPtr pScreen, int x, int y) +{ + ScrnInfoPtr pScr = XF86SCRNINFO(pScreen); + + (*pScr->PointerMoved)(pScreen->myNum, x, y); +} + + +static void +xf86PointerMoved(int scrnIndex, int x, int y) +{ + Bool frameChanged = FALSE; + ScrnInfoPtr pScr = xf86Screens[scrnIndex]; + + /* + * check wether (x,y) belongs to the visual part of the screen + * if not, change the base of the displayed frame accoring + */ + if ( pScr->frameX0 > x) { + pScr->frameX0 = x; + pScr->frameX1 = x + pScr->currentMode->HDisplay - 1; + frameChanged = TRUE ; + } + + if ( pScr->frameX1 < x) { + pScr->frameX1 = x + 1; + pScr->frameX0 = x - pScr->currentMode->HDisplay + 1; + frameChanged = TRUE ; + } + + if ( pScr->frameY0 > y) { + pScr->frameY0 = y; + pScr->frameY1 = y + pScr->currentMode->VDisplay - 1; + frameChanged = TRUE; + } + + if ( pScr->frameY1 < y) { + pScr->frameY1 = y; + pScr->frameY0 = y - pScr->currentMode->VDisplay + 1; + frameChanged = TRUE; + } + + if (frameChanged && pScr->AdjustFrame != NULL) + pScr->AdjustFrame(pScr->scrnIndex, pScr->frameX0, pScr->frameY0, 0); +} + +/* + * xf86LockZoom -- + * Enable/disable ZoomViewport + */ + +void +xf86LockZoom(ScreenPtr pScreen, Bool lock) +{ + XF86SCRNINFO(pScreen)->zoomLocked = lock; +} + +/* + * xf86SwitchMode -- + * This is called by both keyboard processing and the VidMode extension to + * set a new mode. + */ + +Bool +xf86SwitchMode(ScreenPtr pScreen, DisplayModePtr mode) +{ + ScrnInfoPtr pScr = XF86SCRNINFO(pScreen); + ScreenPtr pCursorScreen; + Bool Switched; + int px, py, was_blocked; + DeviceIntPtr dev, it; + + if (!pScr->vtSema || !mode || !pScr->SwitchMode) + return FALSE; + +#ifdef XFreeXDGA + if (DGAActive(pScr->scrnIndex)) + return FALSE; +#endif + + if (mode == pScr->currentMode) + return TRUE; + + if (mode->HDisplay > pScr->virtualX || mode->VDisplay > pScr->virtualY) + return FALSE; + + /* Let's take an educated guess for which pointer to take here. And about as + educated as it gets is to take the first pointer we find. + */ + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (IsPointerDevice(dev) && dev->spriteInfo->spriteOwner) + break; + } + + pCursorScreen = miPointerGetScreen(dev); + if (pScreen == pCursorScreen) + miPointerGetPosition(dev, &px, &py); + + was_blocked = xf86BlockSIGIO(); + Switched = (*pScr->SwitchMode)(pScr->scrnIndex, mode, 0); + if (Switched) { + pScr->currentMode = mode; + + /* + * Adjust frame for new display size. + * Frame is centered around cursor position if cursor is on same screen. + */ + if (pScreen == pCursorScreen) + pScr->frameX0 = px - (mode->HDisplay / 2) + 1; + else + pScr->frameX0 = (pScr->frameX0 + pScr->frameX1 + 1 - mode->HDisplay) / 2; + + if (pScr->frameX0 < 0) + pScr->frameX0 = 0; + + pScr->frameX1 = pScr->frameX0 + mode->HDisplay - 1; + if (pScr->frameX1 >= pScr->virtualX) { + pScr->frameX0 = pScr->virtualX - mode->HDisplay; + pScr->frameX1 = pScr->virtualX - 1; + } + + if (pScreen == pCursorScreen) + pScr->frameY0 = py - (mode->VDisplay / 2) + 1; + else + pScr->frameY0 = (pScr->frameY0 + pScr->frameY1 + 1 - mode->VDisplay) / 2; + + if (pScr->frameY0 < 0) + pScr->frameY0 = 0; + + pScr->frameY1 = pScr->frameY0 + mode->VDisplay - 1; + if (pScr->frameY1 >= pScr->virtualY) { + pScr->frameY0 = pScr->virtualY - mode->VDisplay; + pScr->frameY1 = pScr->virtualY - 1; + } + } + xf86UnblockSIGIO(was_blocked); + + if (pScr->AdjustFrame) + (*pScr->AdjustFrame)(pScr->scrnIndex, pScr->frameX0, pScr->frameY0, 0); + + /* The original code centered the frame around the cursor if possible. + * Since this is hard to achieve with multiple cursors, we do the following: + * - center around the first pointer + * - move all other pointers to the nearest edge on the screen (or leave + * them unmodified if they are within the boundaries). + */ + if (pScreen == pCursorScreen) + { + xf86WarpCursor(dev, pScreen, px, py); + } + + for (it = inputInfo.devices; it; it = it->next) + { + if (it == dev) + continue; + + if (IsPointerDevice(it) && it->spriteInfo->spriteOwner) + { + pCursorScreen = miPointerGetScreen(it); + if (pScreen == pCursorScreen) + { + miPointerGetPosition(it, &px, &py); + if (px < pScr->frameX0) + px = pScr->frameX0; + else if (px > pScr->frameX1) + px = pScr->frameX1; + + if(py < pScr->frameY0) + py = pScr->frameY0; + else if(py > pScr->frameY1) + py = pScr->frameY1; + + xf86WarpCursor(it, pScreen, px, py); + } + } + } + + return Switched; +} + +/* + * xf86ZoomViewport -- + * Reinitialize the visual part of the screen for another mode. + */ + +void +xf86ZoomViewport(ScreenPtr pScreen, int zoom) +{ + ScrnInfoPtr pScr = XF86SCRNINFO(pScreen); + DisplayModePtr mode; + + if (pScr->zoomLocked || !(mode = pScr->currentMode)) + return; + + do { + if (zoom > 0) + mode = mode->next; + else + mode = mode->prev; + } while (mode != pScr->currentMode && !(mode->type & M_T_USERDEF)); + + (void)xf86SwitchMode(pScreen, mode); +} + + +static xf86EdgePtr +FindEdge(xf86EdgePtr edge, int val) +{ + while(edge && (edge->end <= val)) + edge = edge->next; + + if(edge && (edge->start <= val)) + return edge; + + return NULL; +} + +/* + * xf86CursorOffScreen -- + * Check whether it is necessary to switch to another screen + */ + +static Bool +xf86CursorOffScreen(ScreenPtr *pScreen, int *x, int *y) +{ + xf86EdgePtr edge; + int tmp; + + if(screenInfo.numScreens == 1) + return FALSE; + + if(*x < 0) { + tmp = *y; + if(tmp < 0) tmp = 0; + if(tmp >= (*pScreen)->height) tmp = (*pScreen)->height - 1; + + if((edge = xf86ScreenLayout[(*pScreen)->myNum].left)) + edge = FindEdge(edge, tmp); + + if(!edge) *x = 0; + else { + *x += edge->offset.x; + *y += edge->offset.y; + *pScreen = xf86Screens[edge->screen]->pScreen; + } + } + + if(*x >= (*pScreen)->width) { + tmp = *y; + if(tmp < 0) tmp = 0; + if(tmp >= (*pScreen)->height) tmp = (*pScreen)->height - 1; + + if((edge = xf86ScreenLayout[(*pScreen)->myNum].right)) + edge = FindEdge(edge, tmp); + + if(!edge) *x = (*pScreen)->width - 1; + else { + *x += edge->offset.x; + *y += edge->offset.y; + *pScreen = xf86Screens[edge->screen]->pScreen; + } + } + + if(*y < 0) { + tmp = *x; + if(tmp < 0) tmp = 0; + if(tmp >= (*pScreen)->width) tmp = (*pScreen)->width - 1; + + if((edge = xf86ScreenLayout[(*pScreen)->myNum].up)) + edge = FindEdge(edge, tmp); + + if(!edge) *y = 0; + else { + *x += edge->offset.x; + *y += edge->offset.y; + *pScreen = xf86Screens[edge->screen]->pScreen; + } + } + + if(*y >= (*pScreen)->height) { + tmp = *x; + if(tmp < 0) tmp = 0; + if(tmp >= (*pScreen)->width) tmp = (*pScreen)->width - 1; + + if((edge = xf86ScreenLayout[(*pScreen)->myNum].down)) + edge = FindEdge(edge, tmp); + + if(!edge) *y = (*pScreen)->height - 1; + else { + *x += edge->offset.x; + *y += edge->offset.y; + (*pScreen) = xf86Screens[edge->screen]->pScreen; + } + } + + +#if 0 + /* This presents problems for overlapping screens when + HardEdges is used. Have to think about the logic more */ + if((*x < 0) || (*x >= (*pScreen)->width) || + (*y < 0) || (*y >= (*pScreen)->height)) { + /* We may have crossed more than one screen */ + xf86CursorOffScreen(pScreen, x, y); + } +#endif + + return TRUE; +} + + + +/* + * xf86CrossScreen -- + * Switch to another screen + * + * Currently nothing special happens, but mi assumes the CrossScreen + * method exists. + */ + +static void +xf86CrossScreen (ScreenPtr pScreen, Bool entering) +{ +} + + +/* + * xf86WarpCursor -- + * Warp possible to another screen + */ + +/* ARGSUSED */ +static void +xf86WarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ + int sigstate; + sigstate = xf86BlockSIGIO (); + miPointerWarpCursor(pDev, pScreen, x, y); + + xf86Info.currentScreen = pScreen; + xf86UnblockSIGIO (sigstate); +} + + +void * +xf86GetPointerScreenFuncs(void) +{ + return (void *)&xf86PointerScreenFuncs; +} + + +static xf86EdgePtr +AddEdge( + xf86EdgePtr edge, + short min, + short max, + short dx, + short dy, + short screen +){ + xf86EdgePtr pEdge = edge, pPrev = NULL, pNew; + + while(1) { + while(pEdge && (min >= pEdge->end)) { + pPrev = pEdge; + pEdge = pEdge->next; + } + + if(!pEdge) { + if(!(pNew = malloc(sizeof(xf86EdgeRec)))) + break; + + pNew->screen = screen; + pNew->start = min; + pNew->end = max; + pNew->offset.x = dx; + pNew->offset.y = dy; + pNew->next = NULL; + + if(pPrev) + pPrev->next = pNew; + else + edge = pNew; + + break; + } else if (min < pEdge->start) { + if(!(pNew = malloc(sizeof(xf86EdgeRec)))) + break; + + pNew->screen = screen; + pNew->start = min; + pNew->offset.x = dx; + pNew->offset.y = dy; + pNew->next = pEdge; + + if(pPrev) pPrev->next = pNew; + else edge = pNew; + + if(max <= pEdge->start) { + pNew->end = max; + break; + } else { + pNew->end = pEdge->start; + min = pEdge->end; + } + } else + min = pEdge->end; + + pPrev = pEdge; + pEdge = pEdge->next; + + if(max <= min) break; + } + + return edge; +} + +static void +FillOutEdge(xf86EdgePtr pEdge, int limit) +{ + xf86EdgePtr pNext; + int diff; + + if(pEdge->start > 0) pEdge->start = 0; + + while((pNext = pEdge->next)) { + diff = pNext->start - pEdge->end; + if(diff > 0) { + pEdge->end += diff >> 1; + pNext->start -= diff - (diff >> 1); + } + pEdge = pNext; + } + + if(pEdge->end < limit) + pEdge->end = limit; +} + +/* + * xf86InitOrigins() can deal with a maximum of 32 screens + * on 32 bit architectures, 64 on 64 bit architectures. + */ + +void +xf86InitOrigins(void) +{ + unsigned long screensLeft, prevScreensLeft, mask; + screenLayoutPtr screen; + ScreenPtr pScreen, refScreen; + int x1, x2, y1, y2, left, right, top, bottom; + int i, j, ref, minX, minY, min, max; + xf86ScreenLayoutPtr pLayout; + Bool OldStyleConfig = FALSE; + + /* need to have this set up with a config file option */ + HardEdges = FALSE; + + memset(xf86ScreenLayout, 0, MAXSCREENS * sizeof(xf86ScreenLayoutRec)); + + screensLeft = prevScreensLeft = (1 << xf86NumScreens) - 1; + + while(1) { + for(mask = screensLeft, i = 0; mask; mask >>= 1, i++) { + if(!(mask & 1L)) continue; + + screen = &xf86ConfigLayout.screens[i]; + + if (screen->refscreen != NULL && + screen->refscreen->screennum >= xf86NumScreens) { + screensLeft &= ~(1 << i); + xf86Msg(X_WARNING, "Not including screen \"%s\" in origins calculation.\n", + screen->screen->id); + continue; + } + + pScreen = xf86Screens[i]->pScreen; + switch(screen->where) { + case PosObsolete: + OldStyleConfig = TRUE; + pLayout = &xf86ScreenLayout[i]; + /* force edge lists */ + if(screen->left) { + ref = screen->left->screennum; + if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { + ErrorF("Referenced uninitialized screen in Layout!\n"); + break; + } + pLayout->left = AddEdge(pLayout->left, + 0, pScreen->height, + xf86Screens[ref]->pScreen->width, 0, ref); + } + if(screen->right) { + ref = screen->right->screennum; + if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { + ErrorF("Referenced uninitialized screen in Layout!\n"); + break; + } + pLayout->right = AddEdge(pLayout->right, + 0, pScreen->height, -pScreen->width, 0, ref); + } + if(screen->top) { + ref = screen->top->screennum; + if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { + ErrorF("Referenced uninitialized screen in Layout!\n"); + break; + } + pLayout->up = AddEdge(pLayout->up, + 0, pScreen->width, + 0, xf86Screens[ref]->pScreen->height, ref); + } + if(screen->bottom) { + ref = screen->bottom->screennum; + if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { + ErrorF("Referenced uninitialized screen in Layout!\n"); + break; + } + pLayout->down = AddEdge(pLayout->down, + 0, pScreen->width, 0, -pScreen->height, ref); + } + /* we could also try to place it based on those + relative locations if we wanted to */ + screen->x = screen->y = 0; + /* FALLTHROUGH */ + case PosAbsolute: + pScreen->x = screen->x; + pScreen->y = screen->y; + screensLeft &= ~(1 << i); + break; + case PosRelative: + ref = screen->refscreen->screennum; + if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { + ErrorF("Referenced uninitialized screen in Layout!\n"); + break; + } + if(screensLeft & (1 << ref)) break; + refScreen = xf86Screens[ref]->pScreen; + pScreen->x = refScreen->x + screen->x; + pScreen->y = refScreen->y + screen->y; + screensLeft &= ~(1 << i); + break; + case PosRightOf: + ref = screen->refscreen->screennum; + if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { + ErrorF("Referenced uninitialized screen in Layout!\n"); + break; + } + if(screensLeft & (1 << ref)) break; + refScreen = xf86Screens[ref]->pScreen; + pScreen->x = refScreen->x + refScreen->width; + pScreen->y = refScreen->y; + screensLeft &= ~(1 << i); + break; + case PosLeftOf: + ref = screen->refscreen->screennum; + if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { + ErrorF("Referenced uninitialized screen in Layout!\n"); + break; + } + if(screensLeft & (1 << ref)) break; + refScreen = xf86Screens[ref]->pScreen; + pScreen->x = refScreen->x - pScreen->width; + pScreen->y = refScreen->y; + screensLeft &= ~(1 << i); + break; + case PosBelow: + ref = screen->refscreen->screennum; + if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { + ErrorF("Referenced uninitialized screen in Layout!\n"); + break; + } + if(screensLeft & (1 << ref)) break; + refScreen = xf86Screens[ref]->pScreen; + pScreen->x = refScreen->x; + pScreen->y = refScreen->y + refScreen->height; + screensLeft &= ~(1 << i); + break; + case PosAbove: + ref = screen->refscreen->screennum; + if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { + ErrorF("Referenced uninitialized screen in Layout!\n"); + break; + } + if(screensLeft & (1 << ref)) break; + refScreen = xf86Screens[ref]->pScreen; + pScreen->x = refScreen->x; + pScreen->y = refScreen->y - pScreen->height; + screensLeft &= ~(1 << i); + break; + default: + ErrorF("Illegal placement keyword in Layout!\n"); + break; + } + + } + + if(!screensLeft) break; + + if(screensLeft == prevScreensLeft) { + /* All the remaining screens are referencing each other. + Assign a value to one of them and go through again */ + i = 0; + while(!((1 << i) & screensLeft)){ i++; } + + ref = xf86ConfigLayout.screens[i].refscreen->screennum; + xf86Screens[ref]->pScreen->x = xf86Screens[ref]->pScreen->y = 0; + screensLeft &= ~(1 << ref); + } + + prevScreensLeft = screensLeft; + } + + /* justify the topmost and leftmost to (0,0) */ + minX = xf86Screens[0]->pScreen->x; + minY = xf86Screens[0]->pScreen->y; + + for(i = 1; i < xf86NumScreens; i++) { + if(xf86Screens[i]->pScreen->x < minX) + minX = xf86Screens[i]->pScreen->x; + if(xf86Screens[i]->pScreen->y < minY) + minY = xf86Screens[i]->pScreen->y; + } + + if (minX || minY) { + for(i = 0; i < xf86NumScreens; i++) { + xf86Screens[i]->pScreen->x -= minX; + xf86Screens[i]->pScreen->y -= minY; + } + } + + + /* Create the edge lists */ + + if(!OldStyleConfig) { + for(i = 0; i < xf86NumScreens; i++) { + pLayout = &xf86ScreenLayout[i]; + + pScreen = xf86Screens[i]->pScreen; + + left = pScreen->x; + right = left + pScreen->width; + top = pScreen->y; + bottom = top + pScreen->height; + + for(j = 0; j < xf86NumScreens; j++) { + if(i == j) continue; + + refScreen = xf86Screens[j]->pScreen; + + x1 = refScreen->x; + x2 = x1 + refScreen->width; + y1 = refScreen->y; + y2 = y1 + refScreen->height; + + if((bottom > y1) && (top < y2)) { + min = y1 - top; + if(min < 0) min = 0; + max = pScreen->height - (bottom - y2); + if(max > pScreen->height) max = pScreen->height; + + if(((left - 1) >= x1) && ((left - 1) < x2)) + pLayout->left = AddEdge(pLayout->left, min, max, + pScreen->x - refScreen->x, + pScreen->y - refScreen->y, j); + + if((right >= x1) && (right < x2)) + pLayout->right = AddEdge(pLayout->right, min, max, + pScreen->x - refScreen->x, + pScreen->y - refScreen->y, j); + } + + + if((left < x2) && (right > x1)) { + min = x1 - left; + if(min < 0) min = 0; + max = pScreen->width - (right - x2); + if(max > pScreen->width) max = pScreen->width; + + if(((top - 1) >= y1) && ((top - 1) < y2)) + pLayout->up = AddEdge(pLayout->up, min, max, + pScreen->x - refScreen->x, + pScreen->y - refScreen->y, j); + + if((bottom >= y1) && (bottom < y2)) + pLayout->down = AddEdge(pLayout->down, min, max, + pScreen->x - refScreen->x, + pScreen->y - refScreen->y, j); + } + } + } + } + + if(!HardEdges && !OldStyleConfig) { + for(i = 0; i < xf86NumScreens; i++) { + pLayout = &xf86ScreenLayout[i]; + pScreen = xf86Screens[i]->pScreen; + if(pLayout->left) + FillOutEdge(pLayout->left, pScreen->height); + if(pLayout->right) + FillOutEdge(pLayout->right, pScreen->height); + if(pLayout->up) + FillOutEdge(pLayout->up, pScreen->width); + if(pLayout->down) + FillOutEdge(pLayout->down, pScreen->width); + } + } +} + +void +xf86ReconfigureLayout(void) +{ + int i; + + for (i = 0; i < MAXSCREENS; i++) { + xf86ScreenLayoutPtr sl = &xf86ScreenLayout[i]; + /* we don't have to zero these, xf86InitOrigins() takes care of that */ + free(sl->left); + free(sl->right); + free(sl->up); + free(sl->down); + } + + xf86InitOrigins(); +} + + diff --git a/hw/xfree86/common/xf86DGA.c b/hw/xfree86/common/xf86DGA.c new file mode 100644 index 0000000..74eb739 --- /dev/null +++ b/hw/xfree86/common/xf86DGA.c @@ -0,0 +1,1217 @@ +/* + * Copyright (c) 1998-2002 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + * + * Written by Mark Vojkovich + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "xf86.h" +#include "xf86str.h" +#include "xf86Priv.h" +#include "dgaproc.h" +#include <X11/extensions/xf86dgaproto.h> +#include "colormapst.h" +#include "pixmapstr.h" +#include "inputstr.h" +#include "globals.h" +#include "servermd.h" +#include "micmap.h" +#include "xkbsrv.h" +#include "xf86Xinput.h" +#include "exglobals.h" +#include "exevents.h" +#include "eventstr.h" +#include "eventconvert.h" + +#include "mi.h" + +static DevPrivateKeyRec DGAScreenKeyRec; +#define DGAScreenKeyRegistered dixPrivateKeyRegistered(&DGAScreenKeyRec) +static Bool mieq_installed; + +static Bool DGACloseScreen(int i, ScreenPtr pScreen); +static void DGADestroyColormap(ColormapPtr pmap); +static void DGAInstallColormap(ColormapPtr pmap); +static void DGAUninstallColormap(ColormapPtr pmap); +static void DGAHandleEvent(int screen_num, InternalEvent *event, + DeviceIntPtr device); + +static void +DGACopyModeInfo( + DGAModePtr mode, + XDGAModePtr xmode +); + +int *XDGAEventBase = NULL; + +#define DGA_GET_SCREEN_PRIV(pScreen) ((DGAScreenPtr) \ + dixLookupPrivate(&(pScreen)->devPrivates, &DGAScreenKeyRec)) + + +typedef struct _FakedVisualList{ + Bool free; + VisualPtr pVisual; + struct _FakedVisualList *next; +} FakedVisualList; + + +typedef struct { + ScrnInfoPtr pScrn; + int numModes; + DGAModePtr modes; + CloseScreenProcPtr CloseScreen; + DestroyColormapProcPtr DestroyColormap; + InstallColormapProcPtr InstallColormap; + UninstallColormapProcPtr UninstallColormap; + DGADevicePtr current; + DGAFunctionPtr funcs; + int input; + ClientPtr client; + int pixmapMode; + FakedVisualList *fakedVisuals; + ColormapPtr dgaColormap; + ColormapPtr savedColormap; + Bool grabMouse; + Bool grabKeyboard; +} DGAScreenRec, *DGAScreenPtr; + +Bool +DGAInit( + ScreenPtr pScreen, + DGAFunctionPtr funcs, + DGAModePtr modes, + int num +){ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + DGAScreenPtr pScreenPriv; + int i; + + if(!funcs || !funcs->SetMode || !funcs->OpenFramebuffer) + return FALSE; + + if(!modes || num <= 0) + return FALSE; + + if (!dixRegisterPrivateKey(&DGAScreenKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + + if (!pScreenPriv) + { + if(!(pScreenPriv = (DGAScreenPtr)malloc(sizeof(DGAScreenRec)))) + return FALSE; + dixSetPrivate(&pScreen->devPrivates, &DGAScreenKeyRec, pScreenPriv); + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = DGACloseScreen; + pScreenPriv->DestroyColormap = pScreen->DestroyColormap; + pScreen->DestroyColormap = DGADestroyColormap; + pScreenPriv->InstallColormap = pScreen->InstallColormap; + pScreen->InstallColormap = DGAInstallColormap; + pScreenPriv->UninstallColormap = pScreen->UninstallColormap; + pScreen->UninstallColormap = DGAUninstallColormap; + } + + pScreenPriv->pScrn = pScrn; + pScreenPriv->numModes = num; + pScreenPriv->modes = modes; + pScreenPriv->current = NULL; + + pScreenPriv->funcs = funcs; + pScreenPriv->input = 0; + pScreenPriv->client = NULL; + pScreenPriv->fakedVisuals = NULL; + pScreenPriv->dgaColormap = NULL; + pScreenPriv->savedColormap = NULL; + pScreenPriv->grabMouse = FALSE; + pScreenPriv->grabKeyboard = FALSE; + + for(i = 0; i < num; i++) + modes[i].num = i + 1; + +#ifdef PANORAMIX + if(!noPanoramiXExtension) + for(i = 0; i < num; i++) + modes[i].flags &= ~DGA_PIXMAP_AVAILABLE; +#endif + + return TRUE; +} + +/* DGAReInitModes allows the driver to re-initialize + * the DGA mode list. + */ + +Bool +DGAReInitModes( + ScreenPtr pScreen, + DGAModePtr modes, + int num +){ + DGAScreenPtr pScreenPriv; + int i; + + /* No DGA? Ignore call (but don't make it look like it failed) */ + if(!DGAScreenKeyRegistered) + return TRUE; + + pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + + /* Same as above */ + if(!pScreenPriv) + return TRUE; + + /* Can't do this while DGA is active */ + if(pScreenPriv->current) + return FALSE; + + /* Quick sanity check */ + if(!num) + modes = NULL; + else if(!modes) + num = 0; + + pScreenPriv->numModes = num; + pScreenPriv->modes = modes; + + /* This practically disables DGA. So be it. */ + if(!num) + return TRUE; + + for(i = 0; i < num; i++) + modes[i].num = i + 1; + +#ifdef PANORAMIX + if(!noPanoramiXExtension) + for(i = 0; i < num; i++) + modes[i].flags &= ~DGA_PIXMAP_AVAILABLE; +#endif + + return TRUE; +} + +static void +FreeMarkedVisuals(ScreenPtr pScreen) +{ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + FakedVisualList *prev, *curr, *tmp; + + if(!pScreenPriv->fakedVisuals) + return; + + prev = NULL; + curr = pScreenPriv->fakedVisuals; + + while(curr) { + if(curr->free) { + tmp = curr; + curr = curr->next; + if(prev) + prev->next = curr; + else + pScreenPriv->fakedVisuals = curr; + free(tmp->pVisual); + free(tmp); + } else { + prev = curr; + curr = curr->next; + } + } +} + +static Bool +DGACloseScreen(int i, ScreenPtr pScreen) +{ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + + if (mieq_installed) { + mieqSetHandler(ET_DGAEvent, NULL); + mieq_installed = FALSE; + } + + FreeMarkedVisuals(pScreen); + + pScreen->CloseScreen = pScreenPriv->CloseScreen; + pScreen->DestroyColormap = pScreenPriv->DestroyColormap; + pScreen->InstallColormap = pScreenPriv->InstallColormap; + pScreen->UninstallColormap = pScreenPriv->UninstallColormap; + + /* DGAShutdown() should have ensured that no DGA + screen were active by here */ + + free(pScreenPriv); + + return((*pScreen->CloseScreen)(i, pScreen)); +} + + +static void +DGADestroyColormap(ColormapPtr pmap) +{ + ScreenPtr pScreen = pmap->pScreen; + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + VisualPtr pVisual = pmap->pVisual; + + if(pScreenPriv->fakedVisuals) { + FakedVisualList *curr = pScreenPriv->fakedVisuals; + + while(curr) { + if(curr->pVisual == pVisual) { + /* We can't get rid of them yet since FreeColormap + still needs the pVisual during the cleanup */ + curr->free = TRUE; + break; + } + curr = curr->next; + } + } + + if(pScreenPriv->DestroyColormap) { + pScreen->DestroyColormap = pScreenPriv->DestroyColormap; + (*pScreen->DestroyColormap)(pmap); + pScreen->DestroyColormap = DGADestroyColormap; + } +} + + +static void +DGAInstallColormap(ColormapPtr pmap) +{ + ScreenPtr pScreen = pmap->pScreen; + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + + if(pScreenPriv->current && pScreenPriv->dgaColormap) { + if (pmap != pScreenPriv->dgaColormap) { + pScreenPriv->savedColormap = pmap; + pmap = pScreenPriv->dgaColormap; + } + } + + pScreen->InstallColormap = pScreenPriv->InstallColormap; + (*pScreen->InstallColormap)(pmap); + pScreen->InstallColormap = DGAInstallColormap; +} + +static void +DGAUninstallColormap(ColormapPtr pmap) +{ + ScreenPtr pScreen = pmap->pScreen; + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + + if(pScreenPriv->current && pScreenPriv->dgaColormap) { + if (pmap == pScreenPriv->dgaColormap) { + pScreenPriv->dgaColormap = NULL; + } + } + + pScreen->UninstallColormap = pScreenPriv->UninstallColormap; + (*pScreen->UninstallColormap)(pmap); + pScreen->UninstallColormap = DGAUninstallColormap; +} + +int +xf86SetDGAMode( + int index, + int num, + DGADevicePtr devRet +){ + ScreenPtr pScreen = screenInfo.screens[index]; + DGAScreenPtr pScreenPriv; + ScrnInfoPtr pScrn; + DGADevicePtr device; + PixmapPtr pPix = NULL; + DGAModePtr pMode = NULL; + + /* First check if DGAInit was successful on this screen */ + if (!DGAScreenKeyRegistered) + return BadValue; + pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + if (!pScreenPriv) + return BadValue; + pScrn = pScreenPriv->pScrn; + + if(!num) { + if(pScreenPriv->current) { + PixmapPtr oldPix = pScreenPriv->current->pPix; + if(oldPix) { + if(oldPix->drawable.id) + FreeResource(oldPix->drawable.id, RT_NONE); + else + (*pScreen->DestroyPixmap)(oldPix); + } + free(pScreenPriv->current); + pScreenPriv->current = NULL; + pScrn->vtSema = TRUE; + (*pScreenPriv->funcs->SetMode)(pScrn, NULL); + if(pScreenPriv->savedColormap) { + (*pScreen->InstallColormap)(pScreenPriv->savedColormap); + pScreenPriv->savedColormap = NULL; + } + pScreenPriv->dgaColormap = NULL; + (*pScrn->EnableDisableFBAccess)(index, TRUE); + + FreeMarkedVisuals(pScreen); + } + + pScreenPriv->grabMouse = FALSE; + pScreenPriv->grabKeyboard = FALSE; + + return Success; + } + + if(!pScrn->vtSema && !pScreenPriv->current) /* Really switched away */ + return BadAlloc; + + if((num > 0) && (num <= pScreenPriv->numModes)) + pMode = &(pScreenPriv->modes[num - 1]); + else + return BadValue; + + if(!(device = (DGADevicePtr)malloc(sizeof(DGADeviceRec)))) + return BadAlloc; + + if(!pScreenPriv->current) { + Bool oldVTSema = pScrn->vtSema; + + pScrn->vtSema = FALSE; /* kludge until we rewrite VT switching */ + (*pScrn->EnableDisableFBAccess)(index, FALSE); + pScrn->vtSema = oldVTSema; + } + + if(!(*pScreenPriv->funcs->SetMode)(pScrn, pMode)) { + free(device); + return BadAlloc; + } + + pScrn->currentMode = pMode->mode; + + if(!pScreenPriv->current && !pScreenPriv->input) { + /* if it's multihead we need to warp the cursor off of + our screen so it doesn't get trapped */ + } + + pScrn->vtSema = FALSE; + + if(pScreenPriv->current) { + PixmapPtr oldPix = pScreenPriv->current->pPix; + if(oldPix) { + if(oldPix->drawable.id) + FreeResource(oldPix->drawable.id, RT_NONE); + else + (*pScreen->DestroyPixmap)(oldPix); + } + free(pScreenPriv->current); + pScreenPriv->current = NULL; + } + + if(pMode->flags & DGA_PIXMAP_AVAILABLE) { + if((pPix = (*pScreen->CreatePixmap)(pScreen, 0, 0, pMode->depth, 0))) { + (*pScreen->ModifyPixmapHeader)(pPix, + pMode->pixmapWidth, pMode->pixmapHeight, + pMode->depth, pMode->bitsPerPixel, + pMode->bytesPerScanline, + (pointer)(pMode->address)); + } + } + + devRet->mode = device->mode = pMode; + devRet->pPix = device->pPix = pPix; + pScreenPriv->current = device; + pScreenPriv->pixmapMode = FALSE; + pScreenPriv->grabMouse = TRUE; + pScreenPriv->grabKeyboard = TRUE; + + if (!mieq_installed) { + mieqSetHandler(ET_DGAEvent, DGAHandleEvent); + mieq_installed = TRUE; + } + + return Success; +} + + + +/*********** exported ones ***************/ + +void +DGASetInputMode(int index, Bool keyboard, Bool mouse) +{ + ScreenPtr pScreen = screenInfo.screens[index]; + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + + if (pScreenPriv) + { + pScreenPriv->grabMouse = mouse; + pScreenPriv->grabKeyboard = keyboard; + + if (!mieq_installed) { + mieqSetHandler(ET_DGAEvent, DGAHandleEvent); + mieq_installed = TRUE; + } + } +} + +Bool +DGAChangePixmapMode(int index, int *x, int *y, int mode) +{ + DGAScreenPtr pScreenPriv; + DGADevicePtr pDev; + DGAModePtr pMode; + PixmapPtr pPix; + + if(!DGAScreenKeyRegistered) + return FALSE; + + pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + if(!pScreenPriv || !pScreenPriv->current || !pScreenPriv->current->pPix) + return FALSE; + + pDev = pScreenPriv->current; + pPix = pDev->pPix; + pMode = pDev->mode; + + if(mode) { + int shift = 2; + + if(*x > (pMode->pixmapWidth - pMode->viewportWidth)) + *x = pMode->pixmapWidth - pMode->viewportWidth; + if(*y > (pMode->pixmapHeight - pMode->viewportHeight)) + *y = pMode->pixmapHeight - pMode->viewportHeight; + + switch(xf86Screens[index]->bitsPerPixel) { + case 16: shift = 1; break; + case 32: shift = 0; break; + default: break; + } + + if(BITMAP_SCANLINE_PAD == 64) + shift++; + + *x = (*x >> shift) << shift; + + pPix->drawable.x = *x; + pPix->drawable.y = *y; + pPix->drawable.width = pMode->viewportWidth; + pPix->drawable.height = pMode->viewportHeight; + } else { + pPix->drawable.x = 0; + pPix->drawable.y = 0; + pPix->drawable.width = pMode->pixmapWidth; + pPix->drawable.height = pMode->pixmapHeight; + } + pPix->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pScreenPriv->pixmapMode = mode; + + return TRUE; +} + +Bool +DGAAvailable(int index) +{ + if(!DGAScreenKeyRegistered) + return FALSE; + + if(DGA_GET_SCREEN_PRIV(screenInfo.screens[index])) + return TRUE; + + return FALSE; +} + +Bool +DGAActive(int index) +{ + DGAScreenPtr pScreenPriv; + + if(!DGAScreenKeyRegistered) + return FALSE; + + pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + if(pScreenPriv && pScreenPriv->current) + return TRUE; + + return FALSE; +} + + + +/* Called by the event code in case the server is abruptly terminated */ + +void +DGAShutdown(void) +{ + ScrnInfoPtr pScrn; + int i; + + if(!DGAScreenKeyRegistered) + return; + + for(i = 0; i < screenInfo.numScreens; i++) { + pScrn = xf86Screens[i]; + + (void)(*pScrn->SetDGAMode)(pScrn->scrnIndex, 0, NULL); + } +} + +/* Called by the extension to initialize a mode */ + +int +DGASetMode( + int index, + int num, + XDGAModePtr mode, + PixmapPtr *pPix +){ + ScrnInfoPtr pScrn = xf86Screens[index]; + DGADeviceRec device; + int ret; + + /* We rely on the extension to check that DGA is available */ + + ret = (*pScrn->SetDGAMode)(index, num, &device); + if((ret == Success) && num) { + DGACopyModeInfo(device.mode, mode); + *pPix = device.pPix; + } + + return ret; +} + +/* Called from the extension to let the DDX know which events are requested */ + +void +DGASelectInput( + int index, + ClientPtr client, + long mask +){ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + /* We rely on the extension to check that DGA is available */ + pScreenPriv->client = client; + pScreenPriv->input = mask; +} + +int +DGAGetViewportStatus(int index) +{ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + /* We rely on the extension to check that DGA is active */ + + if (!pScreenPriv->funcs->GetViewport) + return 0; + + return (*pScreenPriv->funcs->GetViewport)(pScreenPriv->pScrn); +} + +int +DGASetViewport( + int index, + int x, int y, + int mode +){ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + if (pScreenPriv->funcs->SetViewport) + (*pScreenPriv->funcs->SetViewport)(pScreenPriv->pScrn, x, y, mode); + return Success; +} + + +static int +BitsClear(CARD32 data) +{ + int bits = 0; + CARD32 mask; + + for(mask = 1; mask; mask <<= 1) { + if(!(data & mask)) bits++; + else break; + } + + return bits; +} + +int +DGACreateColormap(int index, ClientPtr client, int id, int mode, int alloc) +{ + ScreenPtr pScreen = screenInfo.screens[index]; + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + FakedVisualList *fvlp; + VisualPtr pVisual; + DGAModePtr pMode; + ColormapPtr pmap; + + if(!mode || (mode > pScreenPriv->numModes)) + return BadValue; + + if((alloc != AllocNone) && (alloc != AllocAll)) + return BadValue; + + pMode = &(pScreenPriv->modes[mode - 1]); + + if(!(pVisual = malloc(sizeof(VisualRec)))) + return BadAlloc; + + pVisual->vid = FakeClientID(0); + pVisual->class = pMode->visualClass; + pVisual->nplanes = pMode->depth; + pVisual->ColormapEntries = 1 << pMode->depth; + pVisual->bitsPerRGBValue = (pMode->depth + 2) / 3; + + switch (pVisual->class) { + case PseudoColor: + case GrayScale: + case StaticGray: + pVisual->bitsPerRGBValue = 8; /* not quite */ + pVisual->redMask = 0; + pVisual->greenMask = 0; + pVisual->blueMask = 0; + pVisual->offsetRed = 0; + pVisual->offsetGreen = 0; + pVisual->offsetBlue = 0; + break; + case DirectColor: + case TrueColor: + pVisual->ColormapEntries = 1 << pVisual->bitsPerRGBValue; + /* fall through */ + case StaticColor: + pVisual->redMask = pMode->red_mask; + pVisual->greenMask = pMode->green_mask; + pVisual->blueMask = pMode->blue_mask; + pVisual->offsetRed = BitsClear(pVisual->redMask); + pVisual->offsetGreen = BitsClear(pVisual->greenMask); + pVisual->offsetBlue = BitsClear(pVisual->blueMask); + } + + if(!(fvlp = malloc(sizeof(FakedVisualList)))) { + free(pVisual); + return BadAlloc; + } + + fvlp->free = FALSE; + fvlp->pVisual = pVisual; + fvlp->next = pScreenPriv->fakedVisuals; + pScreenPriv->fakedVisuals = fvlp; + + LEGAL_NEW_RESOURCE(id, client); + + return CreateColormap(id, pScreen, pVisual, &pmap, alloc, client->index); +} + +/* Called by the extension to install a colormap on DGA active screens */ + +void +DGAInstallCmap(ColormapPtr cmap) +{ + ScreenPtr pScreen = cmap->pScreen; + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + + /* We rely on the extension to check that DGA is active */ + + if(!pScreenPriv->dgaColormap) + pScreenPriv->savedColormap = GetInstalledmiColormap(pScreen); + + pScreenPriv->dgaColormap = cmap; + + (*pScreen->InstallColormap)(cmap); +} + +int +DGASync(int index) +{ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + /* We rely on the extension to check that DGA is active */ + + if (pScreenPriv->funcs->Sync) + (*pScreenPriv->funcs->Sync)(pScreenPriv->pScrn); + + return Success; +} + +int +DGAFillRect( + int index, + int x, int y, int w, int h, + unsigned long color +){ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + /* We rely on the extension to check that DGA is active */ + + if(pScreenPriv->funcs->FillRect && + (pScreenPriv->current->mode->flags & DGA_FILL_RECT)) { + + (*pScreenPriv->funcs->FillRect)(pScreenPriv->pScrn, x, y, w, h, color); + return Success; + } + return BadMatch; +} + +int +DGABlitRect( + int index, + int srcx, int srcy, + int w, int h, + int dstx, int dsty +){ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + /* We rely on the extension to check that DGA is active */ + + if(pScreenPriv->funcs->BlitRect && + (pScreenPriv->current->mode->flags & DGA_BLIT_RECT)) { + + (*pScreenPriv->funcs->BlitRect)(pScreenPriv->pScrn, + srcx, srcy, w, h, dstx, dsty); + return Success; + } + return BadMatch; +} + +int +DGABlitTransRect( + int index, + int srcx, int srcy, + int w, int h, + int dstx, int dsty, + unsigned long color +){ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + /* We rely on the extension to check that DGA is active */ + + if(pScreenPriv->funcs->BlitTransRect && + (pScreenPriv->current->mode->flags & DGA_BLIT_RECT_TRANS)) { + + (*pScreenPriv->funcs->BlitTransRect)(pScreenPriv->pScrn, + srcx, srcy, w, h, dstx, dsty, color); + return Success; + } + return BadMatch; +} + + +int +DGAGetModes(int index) +{ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + /* We rely on the extension to check that DGA is available */ + + return pScreenPriv->numModes; +} + + +int +DGAGetModeInfo( + int index, + XDGAModePtr mode, + int num +){ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + /* We rely on the extension to check that DGA is available */ + + if((num <= 0) || (num > pScreenPriv->numModes)) + return BadValue; + + DGACopyModeInfo(&(pScreenPriv->modes[num - 1]), mode); + + return Success; +} + + +static void +DGACopyModeInfo( + DGAModePtr mode, + XDGAModePtr xmode +){ + DisplayModePtr dmode = mode->mode; + + xmode->num = mode->num; + xmode->name = dmode->name; + xmode->VSync_num = (int)(dmode->VRefresh * 1000.0); + xmode->VSync_den = 1000; + xmode->flags = mode->flags; + xmode->imageWidth = mode->imageWidth; + xmode->imageHeight = mode->imageHeight; + xmode->pixmapWidth = mode->pixmapWidth; + xmode->pixmapHeight = mode->pixmapHeight; + xmode->bytesPerScanline = mode->bytesPerScanline; + xmode->byteOrder = mode->byteOrder; + xmode->depth = mode->depth; + xmode->bitsPerPixel = mode->bitsPerPixel; + xmode->red_mask = mode->red_mask; + xmode->green_mask = mode->green_mask; + xmode->blue_mask = mode->blue_mask; + xmode->visualClass = mode->visualClass; + xmode->viewportWidth = mode->viewportWidth; + xmode->viewportHeight = mode->viewportHeight; + xmode->xViewportStep = mode->xViewportStep; + xmode->yViewportStep = mode->yViewportStep; + xmode->maxViewportX = mode->maxViewportX; + xmode->maxViewportY = mode->maxViewportY; + xmode->viewportFlags = mode->viewportFlags; + xmode->reserved1 = mode->reserved1; + xmode->reserved2 = mode->reserved2; + xmode->offset = mode->offset; + + if(dmode->Flags & V_INTERLACE) xmode->flags |= DGA_INTERLACED; + if(dmode->Flags & V_DBLSCAN) xmode->flags |= DGA_DOUBLESCAN; +} + + +Bool +DGAVTSwitch(void) +{ + ScreenPtr pScreen; + int i; + + for(i = 0; i < screenInfo.numScreens; i++) { + pScreen = screenInfo.screens[i]; + + /* Alternatively, this could send events to DGA clients */ + + if(DGAScreenKeyRegistered) { + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + + if(pScreenPriv && pScreenPriv->current) + return FALSE; + } + } + + return TRUE; +} + +Bool +DGAStealKeyEvent(DeviceIntPtr dev, int index, int key_code, int is_down) +{ + DGAScreenPtr pScreenPriv; + DGAEvent event; + + if(!DGAScreenKeyRegistered) /* no DGA */ + return FALSE; + + if (key_code < 8 || key_code > 255) + return FALSE; + + pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + if(!pScreenPriv || !pScreenPriv->grabKeyboard) /* no direct mode */ + return FALSE; + + memset(&event, 0, sizeof(event)); + event.header = ET_Internal; + event.type = ET_DGAEvent; + event.length = sizeof(event); + event.time = GetTimeInMillis(); + event.subtype = (is_down ? ET_KeyPress : ET_KeyRelease); + event.detail = key_code; + event.dx = 0; + event.dy = 0; + mieqEnqueue (dev, (InternalEvent*)&event); + + return TRUE; +} + +Bool +DGAStealMotionEvent(DeviceIntPtr dev, int index, int dx, int dy) +{ + DGAScreenPtr pScreenPriv; + DGAEvent event; + + if(!DGAScreenKeyRegistered) /* no DGA */ + return FALSE; + + pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + if(!pScreenPriv || !pScreenPriv->grabMouse) /* no direct mode */ + return FALSE; + + memset(&event, 0, sizeof(event)); + event.header = ET_Internal; + event.type = ET_DGAEvent; + event.length = sizeof(event); + event.time = GetTimeInMillis(); + event.subtype = ET_Motion; + event.detail = 0; + event.dx = dx; + event.dy = dy; + mieqEnqueue (dev, (InternalEvent*)&event); + return TRUE; +} + +Bool +DGAStealButtonEvent(DeviceIntPtr dev, int index, int button, int is_down) +{ + DGAScreenPtr pScreenPriv; + DGAEvent event; + + if(!DGAScreenKeyRegistered) /* no DGA */ + return FALSE; + + pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + if (!pScreenPriv || !pScreenPriv->grabMouse) + return FALSE; + + memset(&event, 0, sizeof(event)); + event.header = ET_Internal; + event.type = ET_DGAEvent; + event.length = sizeof(event); + event.time = GetTimeInMillis(); + event.subtype = (is_down ? ET_ButtonPress : ET_ButtonRelease); + event.detail = button; + event.dx = 0; + event.dy = 0; + mieqEnqueue (dev, (InternalEvent*)&event); + + return TRUE; +} + +/* We have the power to steal or modify events that are about to get queued */ + +#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */ +static Mask filters[] = +{ + NoSuchEvent, /* 0 */ + NoSuchEvent, /* 1 */ + KeyPressMask, /* KeyPress */ + KeyReleaseMask, /* KeyRelease */ + ButtonPressMask, /* ButtonPress */ + ButtonReleaseMask, /* ButtonRelease */ + PointerMotionMask, /* MotionNotify (initial state) */ +}; + +static void +DGAProcessKeyboardEvent (ScreenPtr pScreen, DGAEvent *event, DeviceIntPtr keybd) +{ + KeyClassPtr keyc = keybd->key; + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + DeviceIntPtr pointer = GetPairedDevice(keybd); + DeviceEvent ev; + + memset(&ev, 0, sizeof(ev)); + ev.header = ET_Internal; + ev.length = sizeof(ev); + ev.detail.key = event->detail; + ev.type = event->subtype; + ev.root_x = 0; + ev.root_y = 0; + ev.corestate = XkbStateFieldFromRec(&keyc->xkbInfo->state); + ev.corestate |= pointer->button->state; + + UpdateDeviceState(keybd, &ev); + + /* + * Deliver the DGA event + */ + if (pScreenPriv->client) + { + dgaEvent de; + de.u.u.type = *XDGAEventBase + GetCoreType((InternalEvent*)&ev); + de.u.u.detail = event->detail; + de.u.event.time = event->time; + de.u.event.dx = event->dx; + de.u.event.dy = event->dy; + de.u.event.screen = pScreen->myNum; + de.u.event.state = ev.corestate; + + /* If the DGA client has selected input, then deliver based on the usual filter */ + TryClientEvents (pScreenPriv->client, keybd, (xEvent *)&de, 1, + filters[ev.type], pScreenPriv->input, 0); + } + else + { + /* If the keyboard is actively grabbed, deliver a grabbed core event */ + if (keybd->deviceGrab.grab && !keybd->deviceGrab.fromPassiveGrab) + { + ev.detail.key = event->detail; + ev.time = event->time; + ev.root_x = event->dx; + ev.root_y = event->dy; + ev.corestate = event->state; + ev.deviceid = keybd->id; + DeliverGrabbedEvent ((InternalEvent*)&ev, keybd, FALSE); + } + } +} + +static void +DGAProcessPointerEvent (ScreenPtr pScreen, DGAEvent *event, DeviceIntPtr mouse) +{ + ButtonClassPtr butc = mouse->button; + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + DeviceEvent ev; + DeviceIntPtr master = GetMaster(mouse, MASTER_KEYBOARD); + + memset(&ev, 0, sizeof(ev)); + ev.header = ET_Internal; + ev.length = sizeof(ev); + ev.type = event->subtype; + ev.corestate = butc ? butc->state : 0; + if (master && master->key) + ev.corestate |= XkbStateFieldFromRec(&master->key->xkbInfo->state); + + UpdateDeviceState(mouse, &ev); + + /* + * Deliver the DGA event + */ + if (pScreenPriv->client) + { + dgaEvent de; + int coreEquiv; + + coreEquiv = GetCoreType((InternalEvent*)&ev); + + de.u.u.type = *XDGAEventBase + coreEquiv; + de.u.u.detail = event->detail; + de.u.event.time = event->time; + de.u.event.dx = event->dx; + de.u.event.dy = event->dy; + de.u.event.screen = pScreen->myNum; + de.u.event.state = ev.corestate; + + /* If the DGA client has selected input, then deliver based on the usual filter */ + TryClientEvents (pScreenPriv->client, mouse, (xEvent *)&de, 1, + filters[coreEquiv], pScreenPriv->input, 0); + } + else + { + /* If the pointer is actively grabbed, deliver a grabbed core event */ + if (mouse->deviceGrab.grab && !mouse->deviceGrab.fromPassiveGrab) + { + ev.detail.button = event->detail; + ev.time = event->time; + ev.root_x = event->dx; + ev.root_y = event->dy; + ev.corestate = event->state; + /* DGA is core only, so valuators.data doesn't actually matter. + * Mask must be set for EventToCore to create motion events. */ + SetBit(ev.valuators.mask, 0); + SetBit(ev.valuators.mask, 1); + DeliverGrabbedEvent ((InternalEvent*)&ev, mouse, FALSE); + } + } +} + +Bool +DGAOpenFramebuffer( + int index, + char **name, + unsigned char **mem, + int *size, + int *offset, + int *flags +){ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + /* We rely on the extension to check that DGA is available */ + + return (*pScreenPriv->funcs->OpenFramebuffer)(pScreenPriv->pScrn, + name, mem, size, offset, flags); +} + +void +DGACloseFramebuffer(int index) +{ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + /* We rely on the extension to check that DGA is available */ + if(pScreenPriv->funcs->CloseFramebuffer) + (*pScreenPriv->funcs->CloseFramebuffer)(pScreenPriv->pScrn); +} + +/* For DGA 1.0 backwards compatibility only */ + +int +DGAGetOldDGAMode(int index) +{ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + ScrnInfoPtr pScrn = pScreenPriv->pScrn; + DGAModePtr mode; + int i, w, h, p; + + /* We rely on the extension to check that DGA is available */ + + w = pScrn->currentMode->HDisplay; + h = pScrn->currentMode->VDisplay; + p = pad_to_int32(pScrn->displayWidth * bits_to_bytes(pScrn->bitsPerPixel)); + + for(i = 0; i < pScreenPriv->numModes; i++) { + mode = &(pScreenPriv->modes[i]); + + if((mode->viewportWidth == w) && (mode->viewportHeight == h) && + (mode->bytesPerScanline == p) && + (mode->bitsPerPixel == pScrn->bitsPerPixel) && + (mode->depth == pScrn->depth)) { + + return mode->num; + } + } + + return 0; +} + +static void +DGAHandleEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device) +{ + DGAEvent *event= &ev->dga_event; + ScreenPtr pScreen = screenInfo.screens[screen_num]; + DGAScreenPtr pScreenPriv; + + /* no DGA */ + if (!DGAScreenKeyRegistered || XDGAEventBase == 0) + return; + pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + + /* DGA not initialized on this screen */ + if (!pScreenPriv) + return; + + if (!IsMaster(device)) + return; + + switch (event->subtype) { + case KeyPress: + case KeyRelease: + DGAProcessKeyboardEvent (pScreen, event, device); + break; + case MotionNotify: + case ButtonPress: + case ButtonRelease: + DGAProcessPointerEvent (pScreen, event, device); + break; + default: + break; + } +} diff --git a/hw/xfree86/common/xf86DPMS.c b/hw/xfree86/common/xf86DPMS.c new file mode 100644 index 0000000..cd025dc --- /dev/null +++ b/hw/xfree86/common/xf86DPMS.c @@ -0,0 +1,197 @@ +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * This file contains the DPMS functions required by the extension. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <X11/X.h> +#include "os.h" +#include "globals.h" +#include "xf86.h" +#include "xf86Priv.h" +#ifdef DPMSExtension +#include <X11/extensions/dpmsconst.h> +#include "dpmsproc.h" +#endif +#include "xf86VGAarbiter.h" + + +#ifdef DPMSExtension +static DevPrivateKeyRec DPMSKeyRec; +static DevPrivateKey DPMSKey; +static Bool DPMSClose(int i, ScreenPtr pScreen); +static int DPMSCount = 0; +#endif + + +Bool +xf86DPMSInit(ScreenPtr pScreen, DPMSSetProcPtr set, int flags) +{ +#ifdef DPMSExtension + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + DPMSPtr pDPMS; + pointer DPMSOpt; + MessageType enabled_from; + + DPMSKey = &DPMSKeyRec; + + if (!dixRegisterPrivateKey(&DPMSKeyRec, PRIVATE_SCREEN, sizeof (DPMSRec))) + return FALSE; + + pDPMS = dixLookupPrivate(&pScreen->devPrivates, DPMSKey); + pScrn->DPMSSet = set; + pDPMS->Flags = flags; + DPMSOpt = xf86FindOption(pScrn->options, "dpms"); + if (DPMSDisabledSwitch) { + enabled_from = X_CMDLINE; + DPMSEnabled = FALSE; + } + else if (DPMSOpt) { + enabled_from = X_CONFIG; + DPMSEnabled = xf86CheckBoolOption(pScrn->options, "dpms", FALSE); + xf86MarkOptionUsed(DPMSOpt); + } + else { + enabled_from = X_DEFAULT; + DPMSEnabled = TRUE; + } + if (DPMSEnabled) + xf86DrvMsg(pScreen->myNum, enabled_from, "DPMS enabled\n"); + pDPMS->Enabled = DPMSEnabled; + pDPMS->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = DPMSClose; + DPMSCount++; + return TRUE; +#else + return FALSE; +#endif +} + + +#ifdef DPMSExtension + +static Bool +DPMSClose(int i, ScreenPtr pScreen) +{ + DPMSPtr pDPMS; + + /* This shouldn't happen */ + if (DPMSKey == NULL) + return FALSE; + + pDPMS = dixLookupPrivate(&pScreen->devPrivates, DPMSKey); + + /* This shouldn't happen */ + if (!pDPMS) + return FALSE; + + pScreen->CloseScreen = pDPMS->CloseScreen; + + /* + * Turn on DPMS when shutting down. If this function can be used + * depends on the order the driver wraps things. If this is called + * after the driver has shut down everything the driver will have + * to deal with this internally. + */ + if (xf86Screens[i]->vtSema && xf86Screens[i]->DPMSSet) { + xf86Screens[i]->DPMSSet(xf86Screens[i],DPMSModeOn,0); + } + + if (--DPMSCount == 0) + DPMSKey = NULL; + return pScreen->CloseScreen(i, pScreen); +} + + +/* + * DPMSSet -- + * Device dependent DPMS mode setting hook. This is called whenever + * the DPMS mode is to be changed. + */ +int +DPMSSet(ClientPtr client, int level) +{ + int rc, i; + DPMSPtr pDPMS; + ScrnInfoPtr pScrn; + + DPMSPowerLevel = level; + + if (DPMSKey == NULL) + return Success; + + if (level != DPMSModeOn) { + rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, ScreenSaverActive); + if (rc != Success) + return rc; + } + + /* For each screen, set the DPMS level */ + for (i = 0; i < xf86NumScreens; i++) { + pScrn = xf86Screens[i]; + pDPMS = dixLookupPrivate(&screenInfo.screens[i]->devPrivates, DPMSKey); + if (pDPMS && pScrn->DPMSSet && pDPMS->Enabled && pScrn->vtSema) { + xf86VGAarbiterLock(pScrn); + pScrn->DPMSSet(pScrn, level, 0); + xf86VGAarbiterUnlock(pScrn); + } + } + return Success; +} + + +/* + * DPMSSupported -- + * Return TRUE if any screen supports DPMS. + */ +Bool +DPMSSupported(void) +{ + int i; + DPMSPtr pDPMS; + ScrnInfoPtr pScrn; + + if (DPMSKey == NULL) { + return FALSE; + } + + /* For each screen, check if DPMS is supported */ + for (i = 0; i < xf86NumScreens; i++) { + pScrn = xf86Screens[i]; + pDPMS = dixLookupPrivate(&screenInfo.screens[i]->devPrivates, DPMSKey); + if (pDPMS && pScrn->DPMSSet) + return TRUE; + } + return FALSE; +} + +#endif /* DPMSExtension */ diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c new file mode 100644 index 0000000..84c0d18 --- /dev/null +++ b/hw/xfree86/common/xf86Events.c @@ -0,0 +1,753 @@ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Thomas Roell not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Roell makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS ROELL 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. + * + */ +/* + * Copyright (c) 1994-2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* [JCH-96/01/21] Extended std reverse map to four buttons. */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xpoll.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "compiler.h" +#include "xf86.h" +#include "xf86Priv.h" +#define XF86_OS_PRIVS +#include "xf86_OSlib.h" +#include <X11/keysym.h> + +#ifdef XFreeXDGA +#include "dgaproc.h" +#endif + +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include "inputstr.h" +#include "xf86Xinput.h" + +#include "mi.h" +#include "mipointer.h" + +#include "xkbsrv.h" +#include "xkbstr.h" + +#ifdef DPMSExtension +#include <X11/extensions/dpmsconst.h> +#include "dpmsproc.h" +#endif + +/* + * This is a toggling variable: + * FALSE = No VT switching keys have been pressed last time around + * TRUE = Possible VT switch Pending + * (DWH - 12/2/93) + * + * This has been generalised to work with Linux and *BSD+syscons (DHD) + */ + +Bool VTSwitchEnabled = TRUE; /* Allows run-time disabling for + *BSD and for avoiding VT + switches when using the DRI + automatic full screen mode.*/ + +extern fd_set EnabledDevices; + +#ifdef XF86PM +extern void (*xf86OSPMClose)(void); +#endif + +static void xf86VTSwitch(void); + +/* + * Allow arbitrary drivers or other XFree86 code to register with our main + * Wakeup handler. + */ +typedef struct x_IHRec { + int fd; + InputHandlerProc ihproc; + pointer data; + Bool enabled; + struct x_IHRec * next; +} IHRec, *IHPtr; + +static IHPtr InputHandlers = NULL; + + +Bool +LegalModifier(unsigned int key, DeviceIntPtr pDev) +{ + return TRUE; +} + +/* + * TimeSinceLastInputEvent -- + * Function used for screensaver purposes by the os module. Returns the + * time in milliseconds since there last was any input. + */ +int +TimeSinceLastInputEvent(void) +{ + if (xf86Info.lastEventTime == 0) { + xf86Info.lastEventTime = GetTimeInMillis(); + } + return GetTimeInMillis() - xf86Info.lastEventTime; +} + +/* + * SetTimeSinceLastInputEvent -- + * Set the lastEventTime to now. + */ +void +SetTimeSinceLastInputEvent(void) +{ + xf86Info.lastEventTime = GetTimeInMillis(); +} + +/* + * ProcessInputEvents -- + * Retrieve all waiting input events and pass them to DIX in their + * correct chronological order. Only reads from the system pointer + * and keyboard. + */ +void +ProcessInputEvents (void) +{ + int x, y; + + mieqProcessInputEvents(); + + /* FIXME: This is a problem if we have multiple pointers */ + miPointerGetPosition(inputInfo.pointer, &x, &y); + xf86SetViewport(xf86Info.currentScreen, x, y); +} + +/* + * Handle keyboard events that cause some kind of "action" + * (i.e., server termination, video mode changes, VT switches, etc.) + */ +void +xf86ProcessActionEvent(ActionEvent action, void *arg) +{ + DebugF("ProcessActionEvent(%d,%x)\n", (int) action, arg); + switch (action) { + case ACTION_TERMINATE: + if (!xf86Info.dontZap) { +#ifdef XFreeXDGA + DGAShutdown(); +#endif + GiveUp(0); + } + break; + case ACTION_NEXT_MODE: + if (!xf86Info.dontZoom) + xf86ZoomViewport(xf86Info.currentScreen, 1); + break; + case ACTION_PREV_MODE: + if (!xf86Info.dontZoom) + xf86ZoomViewport(xf86Info.currentScreen, -1); + break; + case ACTION_SWITCHSCREEN: + if (VTSwitchEnabled && !xf86Info.dontVTSwitch && arg) { + int vtno = *((int *) arg); + + if (vtno != xf86Info.vtno) { + if (!xf86VTActivate(vtno)) { + ErrorF("Failed to switch from vt%02d to vt%02d: %s\n", + xf86Info.vtno, vtno, strerror(errno)); + } + } + } + break; + case ACTION_SWITCHSCREEN_NEXT: + if (VTSwitchEnabled && !xf86Info.dontVTSwitch) { + if (!xf86VTActivate(xf86Info.vtno + 1)) { + /* If first try failed, assume this is the last VT and + * try wrapping around to the first vt. + */ + if (!xf86VTActivate(1)) { + ErrorF("Failed to switch from vt%02d to next vt: %s\n", + xf86Info.vtno, strerror(errno)); + } + } + } + break; + case ACTION_SWITCHSCREEN_PREV: + if (VTSwitchEnabled && !xf86Info.dontVTSwitch && xf86Info.vtno > 0) { + if (!xf86VTActivate(xf86Info.vtno - 1)) { + /* Don't know what the maximum VT is, so can't wrap around */ + ErrorF("Failed to switch from vt%02d to previous vt: %s\n", + xf86Info.vtno, strerror(errno)); + } + } + break; + default: + break; + } +} + +/* + * xf86Wakeup -- + * Os wakeup handler. + */ + +/* ARGSUSED */ +void +xf86Wakeup(pointer blockData, int err, pointer pReadmask) +{ + fd_set* LastSelectMask = (fd_set*)pReadmask; + fd_set devicesWithInput; + InputInfoPtr pInfo; + + if (err >= 0) { + + XFD_ANDSET(&devicesWithInput, LastSelectMask, &EnabledDevices); + if (XFD_ANYSET(&devicesWithInput)) { + pInfo = xf86InputDevs; + while (pInfo) { + if (pInfo->read_input && pInfo->fd >= 0 && + (FD_ISSET(pInfo->fd, &devicesWithInput) != 0)) { + int sigstate = xf86BlockSIGIO(); + + /* + * Remove the descriptior from the set because more than one + * device may share the same file descriptor. + */ + FD_CLR(pInfo->fd, &devicesWithInput); + + pInfo->read_input(pInfo); + xf86UnblockSIGIO(sigstate); + } + pInfo = pInfo->next; + } + } + } + + if (err >= 0) { /* we don't want the handlers called if select() */ + IHPtr ih; /* returned with an error condition, do we? */ + + for (ih = InputHandlers; ih; ih = ih->next) { + if (ih->enabled && ih->fd >= 0 && ih->ihproc && + (FD_ISSET(ih->fd, ((fd_set *)pReadmask)) != 0)) { + ih->ihproc(ih->fd, ih->data); + } + } + } + + if (xf86VTSwitchPending()) xf86VTSwitch(); +} + + +/* + * xf86SigioReadInput -- + * signal handler for the SIGIO signal. + */ +static void +xf86SigioReadInput(int fd, void *closure) +{ + int errno_save = errno; + InputInfoPtr pInfo = closure; + + pInfo->read_input(pInfo); + + errno = errno_save; +} + +/* + * xf86AddEnabledDevice -- + * + */ +void +xf86AddEnabledDevice(InputInfoPtr pInfo) +{ + if (!xf86InstallSIGIOHandler (pInfo->fd, xf86SigioReadInput, pInfo)) { + AddEnabledDevice(pInfo->fd); + } +} + +/* + * xf86RemoveEnabledDevice -- + * + */ +void +xf86RemoveEnabledDevice(InputInfoPtr pInfo) +{ + if (!xf86RemoveSIGIOHandler (pInfo->fd)) { + RemoveEnabledDevice(pInfo->fd); + } +} + +static int *xf86SignalIntercept = NULL; + +void +xf86InterceptSignals(int *signo) +{ + if ((xf86SignalIntercept = signo)) + *signo = -1; +} + +static void (*xf86SigIllHandler)(void) = NULL; + +void +xf86InterceptSigIll(void (*sigillhandler)(void)) +{ + xf86SigIllHandler = sigillhandler; +} + +/* + * xf86SigWrapper -- + * Catch unexpected signals and exit or continue cleanly. + */ +int +xf86SigWrapper(int signo) +{ + if ((signo == SIGILL) && xf86SigIllHandler) { + (*xf86SigIllHandler)(); + return 0; /* continue */ + } + + if (xf86SignalIntercept && (*xf86SignalIntercept < 0)) { + *xf86SignalIntercept = signo; + return 0; /* continue */ + } + + xf86Info.caughtSignal = TRUE; + return 1; /* abort */ +} + +/* + * xf86PrintBacktrace -- + * Print a stack backtrace for debugging purposes. + */ +void +xf86PrintBacktrace(void) +{ + xorg_backtrace(); +} + +static void +xf86ReleaseKeys(DeviceIntPtr pDev) +{ + KeyClassPtr keyc; + int i, j, nevents, sigstate; + + if (!pDev || !pDev->key) + return; + + keyc = pDev->key; + + /* + * Hmm... here is the biggest hack of every time ! + * It may be possible that a switch-vt procedure has finished BEFORE + * you released all keys neccessary to do this. That peculiar behavior + * can fool the X-server pretty much, cause it assumes that some keys + * were not released. TWM may stuck alsmost completly.... + * OK, what we are doing here is after returning from the vt-switch + * exeplicitely unrelease all keyboard keys before the input-devices + * are reenabled. + */ + + for (i = keyc->xkbInfo->desc->min_key_code; + i < keyc->xkbInfo->desc->max_key_code; + i++) { + if (key_is_down(pDev, i, KEY_POSTED)) { + sigstate = xf86BlockSIGIO (); + nevents = GetKeyboardEvents(xf86Events, pDev, KeyRelease, i); + for (j = 0; j < nevents; j++) + mieqEnqueue(pDev, (InternalEvent*)(xf86Events + j)->event); + xf86UnblockSIGIO(sigstate); + } + } +} + +/* + * xf86VTSwitch -- + * Handle requests for switching the vt. + */ +static void +xf86VTSwitch(void) +{ + int i; + static int prevSIGIO; + InputInfoPtr pInfo; + IHPtr ih; + + DebugF("xf86VTSwitch()\n"); + +#ifdef XFreeXDGA + if(!DGAVTSwitch()) + return; +#endif + + /* + * Since all screens are currently all in the same state it is sufficient + * check the first. This might change in future. + */ + if (xf86Screens[0]->vtSema) { + + DebugF("xf86VTSwitch: Leaving, xf86Exiting is %s\n", + BOOLTOSTRING((dispatchException & DE_TERMINATE) ? TRUE : FALSE)); +#ifdef DPMSExtension + if (DPMSPowerLevel != DPMSModeOn) + DPMSSet(serverClient, DPMSModeOn); +#endif + for (i = 0; i < xf86NumScreens; i++) { + if (!(dispatchException & DE_TERMINATE)) + if (xf86Screens[i]->EnableDisableFBAccess) + (*xf86Screens[i]->EnableDisableFBAccess) (i, FALSE); + } + + /* + * Keep the order: Disable Device > LeaveVT + * EnterVT > EnableDevice + */ + for (ih = InputHandlers; ih; ih = ih->next) + xf86DisableInputHandler(ih); + for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next) { + if (pInfo->dev) { + xf86ReleaseKeys(pInfo->dev); + ProcessInputEvents(); + DisableDevice(pInfo->dev, TRUE); + } + } + + prevSIGIO = xf86BlockSIGIO(); + for (i = 0; i < xf86NumScreens; i++) + xf86Screens[i]->LeaveVT(i, 0); + + xf86AccessLeave(); /* We need this here, otherwise */ + + if (!xf86VTSwitchAway()) { + /* + * switch failed + */ + + DebugF("xf86VTSwitch: Leave failed\n"); + xf86AccessEnter(); + for (i = 0; i < xf86NumScreens; i++) { + if (!xf86Screens[i]->EnterVT(i, 0)) + FatalError("EnterVT failed for screen %d\n", i); + } + if (!(dispatchException & DE_TERMINATE)) { + for (i = 0; i < xf86NumScreens; i++) { + if (xf86Screens[i]->EnableDisableFBAccess) + (*xf86Screens[i]->EnableDisableFBAccess) (i, TRUE); + } + } + dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset); + + pInfo = xf86InputDevs; + while (pInfo) { + if (pInfo->dev) + EnableDevice(pInfo->dev, TRUE); + pInfo = pInfo->next; + } + for (ih = InputHandlers; ih; ih = ih->next) + xf86EnableInputHandler(ih); + + xf86UnblockSIGIO(prevSIGIO); + + } else { +#ifdef XF86PM + if (xf86OSPMClose) + xf86OSPMClose(); + xf86OSPMClose = NULL; +#endif + + for (i = 0; i < xf86NumScreens; i++) { + /* + * zero all access functions to + * trap calls when switched away. + */ + xf86Screens[i]->vtSema = FALSE; + } + if (xorgHWAccess) + xf86DisableIO(); + } + } else { + DebugF("xf86VTSwitch: Entering\n"); + if (!xf86VTSwitchTo()) return; + +#ifdef XF86PM + xf86OSPMClose = xf86OSPMOpen(); +#endif + + if (xorgHWAccess) + xf86EnableIO(); + xf86AccessEnter(); + for (i = 0; i < xf86NumScreens; i++) { + xf86Screens[i]->vtSema = TRUE; + if (!xf86Screens[i]->EnterVT(i, 0)) + FatalError("EnterVT failed for screen %d\n", i); + } + for (i = 0; i < xf86NumScreens; i++) { + if (xf86Screens[i]->EnableDisableFBAccess) + (*xf86Screens[i]->EnableDisableFBAccess)(i, TRUE); + } + + /* Turn screen saver off when switching back */ + dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset); + + pInfo = xf86InputDevs; + while (pInfo) { + if (pInfo->dev) + EnableDevice(pInfo->dev, TRUE); + pInfo = pInfo->next; + } + + for (ih = InputHandlers; ih; ih = ih->next) + xf86EnableInputHandler(ih); + + xf86UnblockSIGIO(prevSIGIO); + } +} + + +/* Input handler registration */ + +static pointer +addInputHandler(int fd, InputHandlerProc proc, pointer data) +{ + IHPtr ih; + + if (fd < 0 || !proc) + return NULL; + + ih = calloc(sizeof(*ih), 1); + if (!ih) + return NULL; + + ih->fd = fd; + ih->ihproc = proc; + ih->data = data; + ih->enabled = TRUE; + + ih->next = InputHandlers; + InputHandlers = ih; + + return ih; +} + +pointer +xf86AddInputHandler(int fd, InputHandlerProc proc, pointer data) +{ + IHPtr ih = addInputHandler(fd, proc, data); + + if (ih) + AddEnabledDevice(fd); + return ih; +} + +pointer +xf86AddGeneralHandler(int fd, InputHandlerProc proc, pointer data) +{ + IHPtr ih = addInputHandler(fd, proc, data); + + if (ih) + AddGeneralSocket(fd); + return ih; +} + +/** + * Set the handler for the console's fd. Replaces (and returns) the previous + * handler or NULL, whichever appropriate. + * proc may be NULL if the server should not handle events on the console. + */ +InputHandlerProc +xf86SetConsoleHandler(InputHandlerProc proc, pointer data) +{ + static InputHandlerProc handler = NULL; + InputHandlerProc old_handler = handler; + + if (old_handler) + xf86RemoveGeneralHandler(old_handler); + + xf86AddGeneralHandler(xf86Info.consoleFd, proc, data); + handler = proc; + + return old_handler; +} + +static void +removeInputHandler(IHPtr ih) +{ + IHPtr p; + + if (ih == InputHandlers) + InputHandlers = ih->next; + else { + p = InputHandlers; + while (p && p->next != ih) + p = p->next; + if (ih) + p->next = ih->next; + } + free(ih); +} + +int +xf86RemoveInputHandler(pointer handler) +{ + IHPtr ih; + int fd; + + if (!handler) + return -1; + + ih = handler; + fd = ih->fd; + + if (ih->fd >= 0) + RemoveEnabledDevice(ih->fd); + removeInputHandler(ih); + + return fd; +} + +int +xf86RemoveGeneralHandler(pointer handler) +{ + IHPtr ih; + int fd; + + if (!handler) + return -1; + + ih = handler; + fd = ih->fd; + + if (ih->fd >= 0) + RemoveGeneralSocket(ih->fd); + removeInputHandler(ih); + + return fd; +} + +void +xf86DisableInputHandler(pointer handler) +{ + IHPtr ih; + + if (!handler) + return; + + ih = handler; + ih->enabled = FALSE; + if (ih->fd >= 0) + RemoveEnabledDevice(ih->fd); +} + +void +xf86DisableGeneralHandler(pointer handler) +{ + IHPtr ih; + + if (!handler) + return; + + ih = handler; + ih->enabled = FALSE; + if (ih->fd >= 0) + RemoveGeneralSocket(ih->fd); +} + +void +xf86EnableInputHandler(pointer handler) +{ + IHPtr ih; + + if (!handler) + return; + + ih = handler; + ih->enabled = TRUE; + if (ih->fd >= 0) + AddEnabledDevice(ih->fd); +} + +void +xf86EnableGeneralHandler(pointer handler) +{ + IHPtr ih; + + if (!handler) + return; + + ih = handler; + ih->enabled = TRUE; + if (ih->fd >= 0) + AddGeneralSocket(ih->fd); +} + +/* + * As used currently by the DRI, the return value is ignored. + */ +Bool +xf86EnableVTSwitch(Bool new) +{ + static Bool def = TRUE; + Bool old; + + old = VTSwitchEnabled; + if (!new) { + /* Disable VT switching */ + def = VTSwitchEnabled; + VTSwitchEnabled = FALSE; + } else { + /* Restore VT switching to default */ + VTSwitchEnabled = def; + } + return old; +} + +void +DDXRingBell(int volume, int pitch, int duration) { + xf86OSRingBell(volume, pitch, duration); +} diff --git a/hw/xfree86/common/xf86Globals.c b/hw/xfree86/common/xf86Globals.c new file mode 100644 index 0000000..16d5557 --- /dev/null +++ b/hw/xfree86/common/xf86Globals.c @@ -0,0 +1,197 @@ + +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * This file contains all the XFree86 global variables. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <X11/X.h> +#include "os.h" +#include "windowstr.h" +#include "propertyst.h" +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86Parser.h" +#include "xf86Xinput.h" +#include "xf86InPriv.h" +#include "xf86Config.h" + +/* Globals that video drivers may access */ + +DevPrivateKeyRec xf86CreateRootWindowKeyRec; +DevPrivateKeyRec xf86ScreenKeyRec; + +ScrnInfoPtr *xf86Screens = NULL; /* List of ScrnInfos */ +const unsigned char byte_reversed[256] = +{ + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, +}; + +/* Globals that input drivers may access */ +InputInfoPtr xf86InputDevs = NULL; + + +/* Globals that video drivers may not access */ + +xf86InfoRec xf86Info = { + .consoleFd = -1, + .vtno = -1, + .vtSysreq = FALSE, + .lastEventTime = -1, + .vtRequestsPending = FALSE, +#ifdef sun + .vtPendingNum = -1, +#endif + .dontVTSwitch = FALSE, + .dontZap = FALSE, + .dontZoom = FALSE, + .notrapSignals = FALSE, + .caughtSignal = FALSE, + .currentScreen = NULL, +#ifdef CSRG_BASED + .screenFd = -1, + .consType = -1, +#endif + .allowMouseOpenFail = FALSE, + .vidModeEnabled = TRUE, + .vidModeAllowNonLocal = FALSE, + .miscModInDevEnabled = TRUE, + .miscModInDevAllowNonLocal = FALSE, + .pixmap24 = Pix24DontCare, + .pix24From = X_DEFAULT, +#ifdef SUPPORT_PC98 + .pc98 = FALSE, +#endif + .pmFlag = TRUE, + .log = LogNone, + .disableRandR = FALSE, + .randRFrom = X_DEFAULT, +#if defined(CONFIG_HAL) || defined(CONFIG_UDEV) + .forceInputDevices = FALSE, + .autoAddDevices = TRUE, + .autoEnableDevices = TRUE +#else + .forceInputDevices = TRUE, + .autoAddDevices = FALSE, + .autoEnableDevices = FALSE +#endif +}; +const char *xf86ConfigFile = NULL; +const char *xf86ConfigDir = NULL; +const char *xf86ModulePath = DEFAULT_MODULE_PATH; +MessageType xf86ModPathFrom = X_DEFAULT; +const char *xf86LogFile = DEFAULT_LOGPREFIX; +MessageType xf86LogFileFrom = X_DEFAULT; +Bool xf86LogFileWasOpened = FALSE; +serverLayoutRec xf86ConfigLayout = {NULL, }; +confDRIRec xf86ConfigDRI = {0, }; +XF86ConfigPtr xf86configptr = NULL; +Bool xf86Resetting = FALSE; +Bool xf86Initialising = FALSE; +Bool xf86DoConfigure = FALSE; +Bool xf86DoShowOptions = FALSE; +DriverPtr *xf86DriverList = NULL; +int xf86NumDrivers = 0; +InputDriverPtr *xf86InputDriverList = NULL; +int xf86NumInputDrivers = 0; +int xf86NumScreens = 0; + +const char *xf86VisualNames[] = { + "StaticGray", + "GrayScale", + "StaticColor", + "PseudoColor", + "TrueColor", + "DirectColor" +}; + +/* Parameters set only from the command line */ +char *xf86ServerName = "no-name"; +Bool xf86fpFlag = FALSE; +Bool xf86sFlag = FALSE; +Bool xf86bsEnableFlag = FALSE; +Bool xf86bsDisableFlag = FALSE; +Bool xf86silkenMouseDisableFlag = FALSE; +Bool xf86xkbdirFlag = FALSE; +#ifdef HAVE_ACPI +Bool xf86acpiDisableFlag = FALSE; +#endif +char *xf86LayoutName = NULL; +char *xf86ScreenName = NULL; +char *xf86PointerName = NULL; +char *xf86KeyboardName = NULL; +int xf86Verbose = DEFAULT_VERBOSE; +int xf86LogVerbose = DEFAULT_LOG_VERBOSE; +int xf86FbBpp = -1; +Pix24Flags xf86Pix24 = Pix24DontCare; +int xf86Depth = -1; +rgb xf86Weight = {0, 0, 0}; +Bool xf86FlipPixels = FALSE; +Gamma xf86Gamma = {0.0, 0.0, 0.0}; +Bool xf86AllowMouseOpenFail = FALSE; +#ifdef XF86VIDMODE +Bool xf86VidModeDisabled = FALSE; +Bool xf86VidModeAllowNonLocal = FALSE; +#endif +RootWinPropPtr *xf86RegisteredPropertiesTable = NULL; +Bool xorgHWAccess = FALSE; diff --git a/hw/xfree86/common/xf86Helper.c b/hw/xfree86/common/xf86Helper.c new file mode 100644 index 0000000..62395ae --- /dev/null +++ b/hw/xfree86/common/xf86Helper.c @@ -0,0 +1,2049 @@ +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * Authors: Dirk Hohndel <hohndel@XFree86.Org> + * David Dawes <dawes@XFree86.Org> + * ... and others + * + * This file includes the helper functions that the server provides for + * different drivers. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <X11/X.h> +#include "os.h" +#include "servermd.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "propertyst.h" +#include "gcstruct.h" +#include "loaderProcs.h" +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" +#include "micmap.h" +#include "xf86DDC.h" +#include "xf86Xinput.h" +#include "xf86InPriv.h" +#include "mivalidate.h" +#include "xf86Crtc.h" + +/* For xf86GetClocks */ +#if defined(CSRG_BASED) || defined(__GNU__) +#define HAS_SETPRIORITY +#include <sys/resource.h> +#endif + +static int xf86ScrnInfoPrivateCount = 0; + + +/* Add a pointer to a new DriverRec to xf86DriverList */ + +void +xf86AddDriver(DriverPtr driver, pointer module, int flags) +{ + /* Don't add null entries */ + if (!driver) + return; + + if (xf86DriverList == NULL) + xf86NumDrivers = 0; + + xf86NumDrivers++; + xf86DriverList = xnfrealloc(xf86DriverList, + xf86NumDrivers * sizeof(DriverPtr)); + xf86DriverList[xf86NumDrivers - 1] = xnfalloc(sizeof(DriverRec)); + if (flags & HaveDriverFuncs) + *xf86DriverList[xf86NumDrivers - 1] = *driver; + else { + (void) memset( xf86DriverList[xf86NumDrivers - 1], 0, + sizeof( DriverRec ) ); + (void) memcpy( xf86DriverList[xf86NumDrivers - 1], driver, + sizeof(DriverRec1)); + + } + xf86DriverList[xf86NumDrivers - 1]->module = module; + xf86DriverList[xf86NumDrivers - 1]->refCount = 0; +} + +void +xf86DeleteDriver(int drvIndex) +{ + if (xf86DriverList[drvIndex] + && (!xf86DriverHasEntities(xf86DriverList[drvIndex]))) { + if (xf86DriverList[drvIndex]->module) + UnloadModule(xf86DriverList[drvIndex]->module); + free(xf86DriverList[drvIndex]); + xf86DriverList[drvIndex] = NULL; + } +} + +/* Add a pointer to a new InputDriverRec to xf86InputDriverList */ + +void +xf86AddInputDriver(InputDriverPtr driver, pointer module, int flags) +{ + /* Don't add null entries */ + if (!driver) + return; + + if (xf86InputDriverList == NULL) + xf86NumInputDrivers = 0; + + xf86NumInputDrivers++; + xf86InputDriverList = xnfrealloc(xf86InputDriverList, + xf86NumInputDrivers * sizeof(InputDriverPtr)); + xf86InputDriverList[xf86NumInputDrivers - 1] = + xnfalloc(sizeof(InputDriverRec)); + *xf86InputDriverList[xf86NumInputDrivers - 1] = *driver; + xf86InputDriverList[xf86NumInputDrivers - 1]->module = module; +} + +void +xf86DeleteInputDriver(int drvIndex) +{ + if (xf86InputDriverList[drvIndex] && xf86InputDriverList[drvIndex]->module) + UnloadModule(xf86InputDriverList[drvIndex]->module); + free(xf86InputDriverList[drvIndex]); + xf86InputDriverList[drvIndex] = NULL; +} + +InputDriverPtr +xf86LookupInputDriver(const char *name) +{ + int i; + + for (i = 0; i < xf86NumInputDrivers; i++) { + if (xf86InputDriverList[i] && xf86InputDriverList[i]->driverName && + xf86NameCmp(name, xf86InputDriverList[i]->driverName) == 0) + return xf86InputDriverList[i]; + } + return NULL; +} + +InputInfoPtr +xf86LookupInput(const char *name) +{ + InputInfoPtr p; + + for (p = xf86InputDevs; p != NULL; p = p->next) { + if (strcmp(name, p->name) == 0) + return p; + } + + return NULL; +} + +/* Allocate a new ScrnInfoRec in xf86Screens */ + +ScrnInfoPtr +xf86AllocateScreen(DriverPtr drv, int flags) +{ + int i; + + if (xf86Screens == NULL) + xf86NumScreens = 0; + + i = xf86NumScreens++; + xf86Screens = xnfrealloc(xf86Screens, xf86NumScreens * sizeof(ScrnInfoPtr)); + xf86Screens[i] = xnfcalloc(sizeof(ScrnInfoRec), 1); + xf86Screens[i]->scrnIndex = i; /* Changes when a screen is removed */ + xf86Screens[i]->origIndex = i; /* This never changes */ + xf86Screens[i]->privates = xnfcalloc(sizeof(DevUnion), + xf86ScrnInfoPrivateCount); + /* + * EnableDisableFBAccess now gets initialized in InitOutput() + * xf86Screens[i]->EnableDisableFBAccess = xf86EnableDisableFBAccess; + */ + + xf86Screens[i]->drv = drv; + drv->refCount++; + xf86Screens[i]->module = DuplicateModule(drv->module, NULL); + + xf86Screens[i]->DriverFunc = drv->driverFunc; + + return xf86Screens[i]; +} + + +/* + * Remove an entry from xf86Screens. Ideally it should free all allocated + * data. To do this properly may require a driver hook. + */ + +void +xf86DeleteScreen(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn; + int i; + + /* First check if the screen is valid */ + if (xf86NumScreens == 0 || xf86Screens == NULL) + return; + + if (scrnIndex > xf86NumScreens - 1) + return; + + if (!(pScrn = xf86Screens[scrnIndex])) + return; + + /* If a FreeScreen function is defined, call it here */ + if (pScrn->FreeScreen != NULL) + pScrn->FreeScreen(scrnIndex, 0); + + while (pScrn->modes) + xf86DeleteMode(&pScrn->modes, pScrn->modes); + + while (pScrn->modePool) + xf86DeleteMode(&pScrn->modePool, pScrn->modePool); + + xf86OptionListFree(pScrn->options); + + if (pScrn->module) + UnloadModule(pScrn->module); + + if (pScrn->drv) + pScrn->drv->refCount--; + + free(pScrn->privates); + + xf86ClearEntityListForScreen(scrnIndex); + + free(pScrn); + + /* Move the other entries down, updating their scrnIndex fields */ + + xf86NumScreens--; + + for (i = scrnIndex; i < xf86NumScreens; i++) { + xf86Screens[i] = xf86Screens[i + 1]; + xf86Screens[i]->scrnIndex = i; + /* Also need to take care of the screen layout settings */ + } +} + +/* + * Allocate a private in ScrnInfoRec. + */ + +int +xf86AllocateScrnInfoPrivateIndex(void) +{ + int idx, i; + ScrnInfoPtr pScr; + DevUnion *nprivs; + + idx = xf86ScrnInfoPrivateCount++; + for (i = 0; i < xf86NumScreens; i++) { + pScr = xf86Screens[i]; + nprivs = xnfrealloc(pScr->privates, + xf86ScrnInfoPrivateCount * sizeof(DevUnion)); + /* Zero the new private */ + memset(&nprivs[idx], 0, sizeof(DevUnion)); + pScr->privates = nprivs; + } + return idx; +} + +Bool +xf86AddPixFormat(ScrnInfoPtr pScrn, int depth, int bpp, int pad) +{ + int i; + + if (pScrn->numFormats >= MAXFORMATS) + return FALSE; + + if (bpp <= 0) { + if (depth == 1) + bpp = 1; + else if (depth <= 8) + bpp = 8; + else if (depth <= 16) + bpp = 16; + else if (depth <= 32) + bpp = 32; + else + return FALSE; + } + if (pad <= 0) + pad = BITMAP_SCANLINE_PAD; + + i = pScrn->numFormats++; + pScrn->formats[i].depth = depth; + pScrn->formats[i].bitsPerPixel = bpp; + pScrn->formats[i].scanlinePad = pad; + return TRUE; +} + +/* + * Set the depth we are using based on (in the following order of preference): + * - values given on the command line + * - values given in the config file + * - values provided by the driver + * - an overall default when nothing else is given + * + * Also find a Display subsection matching the depth/bpp found. + * + * Sets the following ScrnInfoRec fields: + * bitsPerPixel, pixmap24, depth, display, imageByteOrder, + * bitmapScanlinePad, bitmapScanlineUnit, bitmapBitOrder, numFormats, + * formats, fbFormat. + */ + +/* Can the screen handle 24 bpp pixmaps */ +#define DO_PIX24(f) ((f & Support24bppFb) || \ + ((f & Support32bppFb) && (f & SupportConvert24to32))) + +/* Can the screen handle 32 bpp pixmaps */ +#define DO_PIX32(f) ((f & Support32bppFb) || \ + ((f & Support24bppFb) && (f & SupportConvert32to24))) + +/* Does the screen prefer 32bpp fb for 24bpp pixmaps */ +#define CHOOSE32FOR24(f) ((f & Support32bppFb) && (f & SupportConvert24to32) \ + && (f & PreferConvert24to32)) + +/* Does the screen prefer 24bpp fb for 32bpp pixmaps */ +#define CHOOSE24FOR32(f) ((f & Support24bppFb) && (f & SupportConvert32to24) \ + && (f & PreferConvert32to24)) + +/* Can the screen handle 32bpp pixmaps for 24bpp fb */ +#define DO_PIX32FOR24(f) ((f & Support24bppFb) && (f & SupportConvert32to24)) + +/* Can the screen handle 24bpp pixmaps for 32bpp fb */ +#define DO_PIX24FOR32(f) ((f & Support32bppFb) && (f & SupportConvert24to32)) + +#ifndef GLOBAL_DEFAULT_DEPTH +#define GLOBAL_DEFAULT_DEPTH 24 +#endif + +Bool +xf86SetDepthBpp(ScrnInfoPtr scrp, int depth, int dummy, int fbbpp, + int depth24flags) +{ + int i; + DispPtr disp; + Pix24Flags pix24 = xf86Info.pixmap24; + Bool nomatch = FALSE; + + scrp->bitsPerPixel = -1; + scrp->depth = -1; + scrp->pixmap24 = Pix24DontCare; + scrp->bitsPerPixelFrom = X_DEFAULT; + scrp->depthFrom = X_DEFAULT; + + if (xf86FbBpp > 0) { + scrp->bitsPerPixel = xf86FbBpp; + scrp->bitsPerPixelFrom = X_CMDLINE; + } + + if (xf86Depth > 0) { + scrp->depth = xf86Depth; + scrp->depthFrom = X_CMDLINE; + } + + if (xf86FbBpp < 0 && xf86Depth < 0) { + if (scrp->confScreen->defaultfbbpp > 0) { + scrp->bitsPerPixel = scrp->confScreen->defaultfbbpp; + scrp->bitsPerPixelFrom = X_CONFIG; + } + if (scrp->confScreen->defaultdepth > 0) { + scrp->depth = scrp->confScreen->defaultdepth; + scrp->depthFrom = X_CONFIG; + } + + if (scrp->confScreen->defaultfbbpp <= 0 && + scrp->confScreen->defaultdepth <= 0) { + /* + * Check for DefaultDepth and DefaultFbBpp options in the + * Device sections. + */ + int i; + GDevPtr device; + Bool found = FALSE; + + for (i = 0; i < scrp->numEntities; i++) { + device = xf86GetDevFromEntity(scrp->entityList[i], + scrp->entityInstanceList[i]); + if (device && device->options) { + if (xf86FindOption(device->options, "DefaultDepth")) { + scrp->depth = xf86SetIntOption(device->options, + "DefaultDepth", -1); + scrp->depthFrom = X_CONFIG; + found = TRUE; + } + if (xf86FindOption(device->options, "DefaultFbBpp")) { + scrp->bitsPerPixel = xf86SetIntOption(device->options, + "DefaultFbBpp", + -1); + scrp->bitsPerPixelFrom = X_CONFIG; + found = TRUE; + } + } + if (found) + break; + } + } + } + + /* If none of these is set, pick a default */ + if (scrp->bitsPerPixel < 0 && scrp->depth < 0) { + if (fbbpp > 0 || depth > 0) { + if (fbbpp > 0) + scrp->bitsPerPixel = fbbpp; + if (depth > 0) + scrp->depth = depth; + } else { + scrp->depth = GLOBAL_DEFAULT_DEPTH; + } + } + + /* If any are not given, determine a default for the others */ + + if (scrp->bitsPerPixel < 0) { + /* The depth must be set */ + if (scrp->depth > -1) { + if (scrp->depth == 1) + scrp->bitsPerPixel = 1; + else if (scrp->depth <= 4) + scrp->bitsPerPixel = 4; + else if (scrp->depth <= 8) + scrp->bitsPerPixel = 8; + else if (scrp->depth <= 16) + scrp->bitsPerPixel = 16; + else if (scrp->depth <= 24) { + /* + * Figure out if a choice is possible based on the depth24 + * and pix24 flags. + */ + /* Check pix24 first */ + if (pix24 != Pix24DontCare) { + if (pix24 == Pix24Use32) { + if (DO_PIX32(depth24flags)) { + if (CHOOSE24FOR32(depth24flags)) + scrp->bitsPerPixel = 24; + else + scrp->bitsPerPixel = 32; + } else { + nomatch = TRUE; + } + } else if (pix24 == Pix24Use24) { + if (DO_PIX24(depth24flags)) { + if (CHOOSE32FOR24(depth24flags)) + scrp->bitsPerPixel = 32; + else + scrp->bitsPerPixel = 24; + } else { + nomatch = TRUE; + } + } + } else { + if (DO_PIX32(depth24flags)) { + if (CHOOSE24FOR32(depth24flags)) + scrp->bitsPerPixel = 24; + else + scrp->bitsPerPixel = 32; + } else if (DO_PIX24(depth24flags)) { + if (CHOOSE32FOR24(depth24flags)) + scrp->bitsPerPixel = 32; + else + scrp->bitsPerPixel = 24; + } + } + } else if (scrp->depth <= 32) + scrp->bitsPerPixel = 32; + else { + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Specified depth (%d) is greater than 32\n", + scrp->depth); + return FALSE; + } + } else { + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "xf86SetDepthBpp: internal error: depth and fbbpp" + " are both not set\n"); + return FALSE; + } + if (scrp->bitsPerPixel < 0) { + if (nomatch) + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Driver can't support depth 24 pixmap format (%d)\n", + PIX24TOBPP(pix24)); + else if ((depth24flags & (Support24bppFb | Support32bppFb)) == + NoDepth24Support) + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Driver can't support depth 24\n"); + else + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Can't find fbbpp for depth 24\n"); + return FALSE; + } + scrp->bitsPerPixelFrom = X_PROBED; + } + + if (scrp->depth <= 0) { + /* bitsPerPixel is already set */ + switch (scrp->bitsPerPixel) { + case 32: + scrp->depth = 24; + break; + default: + /* 1, 4, 8, 16 and 24 */ + scrp->depth = scrp->bitsPerPixel; + break; + } + scrp->depthFrom = X_PROBED; + } + + /* Sanity checks */ + if (scrp->depth < 1 || scrp->depth > 32) { + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Specified depth (%d) is not in the range 1-32\n", + scrp->depth); + return FALSE; + } + switch (scrp->bitsPerPixel) { + case 1: + case 4: + case 8: + case 16: + case 24: + case 32: + break; + default: + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Specified fbbpp (%d) is not a permitted value\n", + scrp->bitsPerPixel); + return FALSE; + } + if (scrp->depth > scrp->bitsPerPixel) { + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Specified depth (%d) is greater than the fbbpp (%d)\n", + scrp->depth, scrp->bitsPerPixel); + return FALSE; + } + + /* set scrp->pixmap24 if the driver isn't flexible */ + if (scrp->bitsPerPixel == 24 && !DO_PIX32FOR24(depth24flags)) { + scrp->pixmap24 = Pix24Use24; + } + if (scrp->bitsPerPixel == 32 && !DO_PIX24FOR32(depth24flags)) { + scrp->pixmap24 = Pix24Use32; + } + + /* + * Find the Display subsection matching the depth/fbbpp and initialise + * scrp->display with it. + */ + for (i = 0, disp = scrp->confScreen->displays; + i < scrp->confScreen->numdisplays; i++, disp++) { + if ((disp->depth == scrp->depth && disp->fbbpp == scrp->bitsPerPixel) + || (disp->depth == scrp->depth && disp->fbbpp <= 0) + || (disp->fbbpp == scrp->bitsPerPixel && disp->depth <= 0)) { + scrp->display = disp; + break; + } + } + + /* + * If an exact match can't be found, see if there is one with no + * depth or fbbpp specified. + */ + if (i == scrp->confScreen->numdisplays) { + for (i = 0, disp = scrp->confScreen->displays; + i < scrp->confScreen->numdisplays; i++, disp++) { + if (disp->depth <= 0 && disp->fbbpp <= 0) { + scrp->display = disp; + break; + } + } + } + + /* + * If all else fails, create a default one. + */ + if (i == scrp->confScreen->numdisplays) { + scrp->confScreen->numdisplays++; + scrp->confScreen->displays = + xnfrealloc(scrp->confScreen->displays, + scrp->confScreen->numdisplays * sizeof(DispRec)); + xf86DrvMsg(scrp->scrnIndex, X_INFO, + "Creating default Display subsection in Screen section\n" + "\t\"%s\" for depth/fbbpp %d/%d\n", + scrp->confScreen->id, scrp->depth, scrp->bitsPerPixel); + memset(&scrp->confScreen->displays[i], 0, sizeof(DispRec)); + scrp->confScreen->displays[i].blackColour.red = -1; + scrp->confScreen->displays[i].blackColour.green = -1; + scrp->confScreen->displays[i].blackColour.blue = -1; + scrp->confScreen->displays[i].whiteColour.red = -1; + scrp->confScreen->displays[i].whiteColour.green = -1; + scrp->confScreen->displays[i].whiteColour.blue = -1; + scrp->confScreen->displays[i].defaultVisual = -1; + scrp->confScreen->displays[i].modes = xnfalloc(sizeof(char *)); + scrp->confScreen->displays[i].modes[0] = NULL; + scrp->confScreen->displays[i].depth = depth; + scrp->confScreen->displays[i].fbbpp = fbbpp; + scrp->display = &scrp->confScreen->displays[i]; + } + + /* + * Setup defaults for the display-wide attributes the framebuffer will + * need. These defaults should eventually be set globally, and not + * dependent on the screens. + */ + scrp->imageByteOrder = IMAGE_BYTE_ORDER; + scrp->bitmapScanlinePad = BITMAP_SCANLINE_PAD; + if (scrp->depth < 8) { + /* Planar modes need these settings */ + scrp->bitmapScanlineUnit = 8; + scrp->bitmapBitOrder = MSBFirst; + } else { + scrp->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; + scrp->bitmapBitOrder = BITMAP_BIT_ORDER; + } + + /* + * If an unusual depth is required, add it to scrp->formats. The formats + * for the common depths are handled globally in InitOutput + */ + switch (scrp->depth) { + case 1: + case 4: + case 8: + case 15: + case 16: + case 24: + /* Common depths. Nothing to do for them */ + break; + default: + if (!xf86AddPixFormat(scrp, scrp->depth, 0, 0)) { + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Can't add pixmap format for depth %d\n", scrp->depth); + return FALSE; + } + } + + /* Initialise the framebuffer format for this screen */ + scrp->fbFormat.depth = scrp->depth; + scrp->fbFormat.bitsPerPixel = scrp->bitsPerPixel; + scrp->fbFormat.scanlinePad = BITMAP_SCANLINE_PAD; + + return TRUE; +} + +/* + * Print out the selected depth and bpp. + */ +void +xf86PrintDepthBpp(ScrnInfoPtr scrp) +{ + xf86DrvMsg(scrp->scrnIndex, scrp->depthFrom, "Depth %d, ", scrp->depth); + xf86Msg(scrp->bitsPerPixelFrom, "framebuffer bpp %d\n", scrp->bitsPerPixel); +} + +/* + * xf86SetWeight sets scrp->weight, scrp->mask, scrp->offset, and for depths + * greater than MAX_PSEUDO_DEPTH also scrp->rgbBits. + */ +Bool +xf86SetWeight(ScrnInfoPtr scrp, rgb weight, rgb mask) +{ + MessageType weightFrom = X_DEFAULT; + + scrp->weight.red = 0; + scrp->weight.green = 0; + scrp->weight.blue = 0; + + if (xf86Weight.red > 0 && xf86Weight.green > 0 && xf86Weight.blue > 0) { + scrp->weight = xf86Weight; + weightFrom = X_CMDLINE; + } else if (scrp->display->weight.red > 0 && scrp->display->weight.green > 0 + && scrp->display->weight.blue > 0) { + scrp->weight = scrp->display->weight; + weightFrom = X_CONFIG; + } else if (weight.red > 0 && weight.green > 0 && weight.blue > 0) { + scrp->weight = weight; + } else { + switch (scrp->depth) { + case 1: + case 4: + case 8: + scrp->weight.red = scrp->weight.green = + scrp->weight.blue = scrp->rgbBits; + break; + case 15: + scrp->weight.red = scrp->weight.green = scrp->weight.blue = 5; + break; + case 16: + scrp->weight.red = scrp->weight.blue = 5; + scrp->weight.green = 6; + break; + case 18: + scrp->weight.red = scrp->weight.green = scrp->weight.blue = 6; + break; + case 24: + scrp->weight.red = scrp->weight.green = scrp->weight.blue = 8; + break; + case 30: + scrp->weight.red = scrp->weight.green = scrp->weight.blue = 10; + break; + } + } + + if (scrp->weight.red) + xf86DrvMsg(scrp->scrnIndex, weightFrom, "RGB weight %d%d%d\n", + (int)scrp->weight.red, (int)scrp->weight.green, + (int)scrp->weight.blue); + + if (scrp->depth > MAX_PSEUDO_DEPTH && + (scrp->depth != scrp->weight.red + scrp->weight.green + + scrp->weight.blue)) { + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Weight given (%d%d%d) is inconsistent with the " + "depth (%d)\n", + (int)scrp->weight.red, (int)scrp->weight.green, + (int)scrp->weight.blue, scrp->depth); + return FALSE; + } + if (scrp->depth > MAX_PSEUDO_DEPTH && scrp->weight.red) { + /* + * XXX Does this even mean anything for TrueColor visuals? + * If not, we shouldn't even be setting it here. However, this + * matches the behaviour of 3.x versions of XFree86. + */ + scrp->rgbBits = scrp->weight.red; + if (scrp->weight.green > scrp->rgbBits) + scrp->rgbBits = scrp->weight.green; + if (scrp->weight.blue > scrp->rgbBits) + scrp->rgbBits = scrp->weight.blue; + } + + /* Set the mask and offsets */ + if (mask.red == 0 || mask.green == 0 || mask.blue == 0) { + /* Default to a setting common to PC hardware */ + scrp->offset.red = scrp->weight.green + scrp->weight.blue; + scrp->offset.green = scrp->weight.blue; + scrp->offset.blue = 0; + scrp->mask.red = ((1 << scrp->weight.red) - 1) << scrp->offset.red; + scrp->mask.green = ((1 << scrp->weight.green) - 1) + << scrp->offset.green; + scrp->mask.blue = (1 << scrp->weight.blue) - 1; + } else { + /* Initialise to the values passed */ + scrp->mask.red = mask.red; + scrp->mask.green = mask.green; + scrp->mask.blue = mask.blue; + scrp->offset.red = ffs(mask.red); + scrp->offset.green = ffs(mask.green); + scrp->offset.blue = ffs(mask.blue); + } + return TRUE; +} + +Bool +xf86SetDefaultVisual(ScrnInfoPtr scrp, int visual) +{ + MessageType visualFrom = X_DEFAULT; + + if (defaultColorVisualClass >= 0) { + scrp->defaultVisual = defaultColorVisualClass; + visualFrom = X_CMDLINE; + } else if (scrp->display->defaultVisual >= 0) { + scrp->defaultVisual = scrp->display->defaultVisual; + visualFrom = X_CONFIG; + } else if (visual >= 0) { + scrp->defaultVisual = visual; + } else { + if (scrp->depth == 1) + scrp->defaultVisual = StaticGray; + else if (scrp->depth == 4) + scrp->defaultVisual = StaticColor; + else if (scrp->depth <= MAX_PSEUDO_DEPTH) + scrp->defaultVisual = PseudoColor; + else + scrp->defaultVisual = TrueColor; + } + switch (scrp->defaultVisual) { + case StaticGray: + case GrayScale: + case StaticColor: + case PseudoColor: + case TrueColor: + case DirectColor: + xf86DrvMsg(scrp->scrnIndex, visualFrom, "Default visual is %s\n", + xf86VisualNames[scrp->defaultVisual]); + return TRUE; + default: + + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Invalid default visual class (%d)\n", scrp->defaultVisual); + return FALSE; + } +} + +#define TEST_GAMMA(g) \ + (g).red > GAMMA_ZERO || (g).green > GAMMA_ZERO || (g).blue > GAMMA_ZERO + +#define SET_GAMMA(g) \ + (g) > GAMMA_ZERO ? (g) : 1.0 + +Bool +xf86SetGamma(ScrnInfoPtr scrp, Gamma gamma) +{ + MessageType from = X_DEFAULT; +#if 0 + xf86MonPtr DDC = (xf86MonPtr)(scrp->monitor->DDC); +#endif + if (TEST_GAMMA(xf86Gamma)) { + from = X_CMDLINE; + scrp->gamma.red = SET_GAMMA(xf86Gamma.red); + scrp->gamma.green = SET_GAMMA(xf86Gamma.green); + scrp->gamma.blue = SET_GAMMA(xf86Gamma.blue); + } else if (TEST_GAMMA(scrp->monitor->gamma)) { + from = X_CONFIG; + scrp->gamma.red = SET_GAMMA(scrp->monitor->gamma.red); + scrp->gamma.green = SET_GAMMA(scrp->monitor->gamma.green); + scrp->gamma.blue = SET_GAMMA(scrp->monitor->gamma.blue); +#if 0 + } else if ( DDC && DDC->features.gamma > GAMMA_ZERO ) { + from = X_PROBED; + scrp->gamma.red = SET_GAMMA(DDC->features.gamma); + scrp->gamma.green = SET_GAMMA(DDC->features.gamma); + scrp->gamma.blue = SET_GAMMA(DDC->features.gamma); + /* EDID structure version 2 gives optional seperate red, green & blue gamma values + * in bytes 0x57-0x59 */ +#endif + } else if (TEST_GAMMA(gamma)) { + scrp->gamma.red = SET_GAMMA(gamma.red); + scrp->gamma.green = SET_GAMMA(gamma.green); + scrp->gamma.blue = SET_GAMMA(gamma.blue); + } else { + scrp->gamma.red = 1.0; + scrp->gamma.green = 1.0; + scrp->gamma.blue = 1.0; + } + /* Pretend we succeeded if we support better a gamma system. + * This avoids a confusing message. + */ + if (xf86_crtc_supports_gamma(scrp)) + return TRUE; + xf86DrvMsg(scrp->scrnIndex, from, + "Using gamma correction (%.1f, %.1f, %.1f)\n", + scrp->gamma.red, scrp->gamma.green, scrp->gamma.blue); + + return TRUE; +} + +#undef TEST_GAMMA +#undef SET_GAMMA + + +/* + * Set the DPI from the command line option. XXX should allow it to be + * calculated from the widthmm/heightmm values. + */ + +#undef MMPERINCH +#define MMPERINCH 25.4 + +void +xf86SetDpi(ScrnInfoPtr pScrn, int x, int y) +{ + MessageType from = X_DEFAULT; + xf86MonPtr DDC = (xf86MonPtr)(pScrn->monitor->DDC); + int ddcWidthmm, ddcHeightmm; + int widthErr, heightErr; + + /* XXX Maybe there is no need for widthmm/heightmm in ScrnInfoRec */ + pScrn->widthmm = pScrn->monitor->widthmm; + pScrn->heightmm = pScrn->monitor->heightmm; + + if (DDC && (DDC->features.hsize > 0 && DDC->features.vsize > 0) ) { + /* DDC gives display size in mm for individual modes, + * but cm for monitor + */ + ddcWidthmm = DDC->features.hsize * 10; /* 10mm in 1cm */ + ddcHeightmm = DDC->features.vsize * 10; /* 10mm in 1cm */ + } else { + ddcWidthmm = ddcHeightmm = 0; + } + + if (monitorResolution > 0) { + pScrn->xDpi = monitorResolution; + pScrn->yDpi = monitorResolution; + from = X_CMDLINE; + } else if (pScrn->widthmm > 0 || pScrn->heightmm > 0) { + from = X_CONFIG; + if (pScrn->widthmm > 0) { + pScrn->xDpi = + (int)((double)pScrn->virtualX * MMPERINCH / pScrn->widthmm); + } + if (pScrn->heightmm > 0) { + pScrn->yDpi = + (int)((double)pScrn->virtualY * MMPERINCH / pScrn->heightmm); + } + if (pScrn->xDpi > 0 && pScrn->yDpi <= 0) + pScrn->yDpi = pScrn->xDpi; + if (pScrn->yDpi > 0 && pScrn->xDpi <= 0) + pScrn->xDpi = pScrn->yDpi; + xf86DrvMsg(pScrn->scrnIndex, from, "Display dimensions: (%d, %d) mm\n", + pScrn->widthmm, pScrn->heightmm); + + /* Warn if config and probe disagree about display size */ + if ( ddcWidthmm && ddcHeightmm ) { + if (pScrn->widthmm > 0) { + widthErr = abs(ddcWidthmm - pScrn->widthmm); + } else { + widthErr = 0; + } + if (pScrn->heightmm > 0) { + heightErr = abs(ddcHeightmm - pScrn->heightmm); + } else { + heightErr = 0; + } + if (widthErr>10 || heightErr>10) { + /* Should include config file name for monitor here */ + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Probed monitor is %dx%d mm, using Displaysize %dx%d mm\n", + ddcWidthmm,ddcHeightmm, pScrn->widthmm,pScrn->heightmm); + } + } + } else if ( ddcWidthmm && ddcHeightmm ) { + from = X_PROBED; + xf86DrvMsg(pScrn->scrnIndex, from, "Display dimensions: (%d, %d) mm\n", + ddcWidthmm, ddcHeightmm ); + pScrn->widthmm = ddcWidthmm; + pScrn->heightmm = ddcHeightmm; + if (pScrn->widthmm > 0) { + pScrn->xDpi = + (int)((double)pScrn->virtualX * MMPERINCH / pScrn->widthmm); + } + if (pScrn->heightmm > 0) { + pScrn->yDpi = + (int)((double)pScrn->virtualY * MMPERINCH / pScrn->heightmm); + } + if (pScrn->xDpi > 0 && pScrn->yDpi <= 0) + pScrn->yDpi = pScrn->xDpi; + if (pScrn->yDpi > 0 && pScrn->xDpi <= 0) + pScrn->xDpi = pScrn->yDpi; + } else { + if (x > 0) + pScrn->xDpi = x; + else + pScrn->xDpi = DEFAULT_DPI; + if (y > 0) + pScrn->yDpi = y; + else + pScrn->yDpi = DEFAULT_DPI; + } + xf86DrvMsg(pScrn->scrnIndex, from, "DPI set to (%d, %d)\n", + pScrn->xDpi, pScrn->yDpi); +} + +#undef MMPERINCH + + +void +xf86SetBlackWhitePixels(ScreenPtr pScreen) +{ + if (xf86FlipPixels) { + pScreen->whitePixel = 0; + pScreen->blackPixel = 1; + } else { + pScreen->whitePixel = 1; + pScreen->blackPixel = 0; + } +} + +/* + * xf86SetRootClip -- + * Enable or disable rendering to the screen by + * setting the root clip list and revalidating + * all of the windows + */ + +static void +xf86SetRootClip (ScreenPtr pScreen, Bool enable) +{ + WindowPtr pWin = pScreen->root; + WindowPtr pChild; + Bool WasViewable = (Bool)(pWin->viewable); + Bool anyMarked = FALSE; + WindowPtr pLayerWin; + BoxRec box; + + if (WasViewable) + { + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + (void) (*pScreen->MarkOverlappedWindows)(pChild, + pChild, + &pLayerWin); + } + (*pScreen->MarkWindow) (pWin); + anyMarked = TRUE; + if (pWin->valdata) + { + if (HasBorder (pWin)) + { + RegionPtr borderVisible; + + borderVisible = RegionCreate(NullBox, 1); + RegionSubtract(borderVisible, + &pWin->borderClip, &pWin->winSize); + pWin->valdata->before.borderVisible = borderVisible; + } + pWin->valdata->before.resized = TRUE; + } + } + + /* + * Use REGION_BREAK to avoid optimizations in ValidateTree + * that assume the root borderClip can't change well, normally + * it doesn't...) + */ + if (enable) + { + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + RegionInit(&pWin->winSize, &box, 1); + RegionInit(&pWin->borderSize, &box, 1); + if (WasViewable) + RegionReset(&pWin->borderClip, &box); + pWin->drawable.width = pScreen->width; + pWin->drawable.height = pScreen->height; + RegionBreak(&pWin->clipList); + } + else + { + RegionEmpty(&pWin->borderClip); + RegionBreak(&pWin->clipList); + } + + ResizeChildrenWinSize (pWin, 0, 0, 0, 0); + + if (WasViewable) + { + if (pWin->firstChild) + { + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin->firstChild, + pWin->firstChild, + (WindowPtr *)NULL); + } + else + { + (*pScreen->MarkWindow) (pWin); + anyMarked = TRUE; + } + + + if (anyMarked) + (*pScreen->ValidateTree)(pWin, NullWindow, VTOther); + } + + if (WasViewable) + { + if (anyMarked) + (*pScreen->HandleExposures)(pWin); + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pWin, NullWindow, VTOther); + } + if (pWin->realized) + WindowsRestructured (); + FlushAllOutput (); +} + +/* + * Function to enable/disable access to the frame buffer + * + * This is used when VT switching and when entering/leaving DGA direct mode. + * + * This has been rewritten again to eliminate the saved pixmap. The + * devPrivate field in the screen pixmap is set to NULL to catch code + * accidentally referencing the frame buffer while the X server is not + * supposed to touch it. + * + * Here, we exchange the pixmap private data, rather than the pixmaps + * themselves to avoid having to find and change any references to the screen + * pixmap such as GC's, window privates etc. This also means that this code + * does not need to know exactly how the pixmap pixels are accessed. Further, + * this exchange is >not< done through the screen's ModifyPixmapHeader() + * vector. This means the called frame buffer code layers can determine + * whether they are switched in or out by keeping track of the root pixmap's + * private data, and therefore don't need to access pScrnInfo->vtSema. + */ +void +xf86EnableDisableFBAccess(int scrnIndex, Bool enable) +{ + ScrnInfoPtr pScrnInfo = xf86Screens[scrnIndex]; + ScreenPtr pScreen = pScrnInfo->pScreen; + PixmapPtr pspix; + + pspix = (*pScreen->GetScreenPixmap) (pScreen); + if (enable) + { + /* + * Restore all of the clip lists on the screen + */ + if (!xf86Resetting) + xf86SetRootClip (pScreen, TRUE); + + } + else + { + /* + * Empty all of the clip lists on the screen + */ + xf86SetRootClip (pScreen, FALSE); + } +} + +/* Print driver messages in the standard format */ + +#undef PREFIX_SIZE +#define PREFIX_SIZE 14 + +void +xf86VDrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format, + va_list args) +{ + char *tmpFormat; + + /* Prefix the scrnIndex name to the format string. */ + if (scrnIndex >= 0 && scrnIndex < xf86NumScreens && + xf86Screens[scrnIndex]->name) { + tmpFormat = malloc(strlen(format) + + strlen(xf86Screens[scrnIndex]->name) + + PREFIX_SIZE + 1); + if (!tmpFormat) + return; + + snprintf(tmpFormat, PREFIX_SIZE + 1, "%s(%d): ", + xf86Screens[scrnIndex]->name, scrnIndex); + + strcat(tmpFormat, format); + LogVMessageVerb(type, verb, tmpFormat, args); + free(tmpFormat); + } else + LogVMessageVerb(type, verb, format, args); +} +#undef PREFIX_SIZE + +/* Print driver messages, with verbose level specified directly */ +void +xf86DrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format, + ...) +{ + va_list ap; + + va_start(ap, format); + xf86VDrvMsgVerb(scrnIndex, type, verb, format, ap); + va_end(ap); +} + +/* Print driver messages, with verbose level of 1 (default) */ +void +xf86DrvMsg(int scrnIndex, MessageType type, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + xf86VDrvMsgVerb(scrnIndex, type, 1, format, ap); + va_end(ap); +} + +/* Print input driver messages in the standard format of + <driver>: <device name>: <message> */ +void +xf86VIDrvMsgVerb(InputInfoPtr dev, MessageType type, int verb, const char *format, + va_list args) +{ + char *msg; + + if (asprintf(&msg, "%s: %s: %s", dev->drv->driverName, dev->name, format) + == -1) { + LogVMessageVerb(type, verb, "%s", args); + } else { + LogVMessageVerb(type, verb, msg, args); + free(msg); + } +} + +/* Print input driver message, with verbose level specified directly */ +void +xf86IDrvMsgVerb(InputInfoPtr dev, MessageType type, int verb, const char *format, + ...) +{ + va_list ap; + + va_start(ap, format); + xf86VIDrvMsgVerb(dev, type, verb, format, ap); + va_end(ap); +} + +/* Print input driver messages, with verbose level of 1 (default) */ +void +xf86IDrvMsg(InputInfoPtr dev, MessageType type, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + xf86VIDrvMsgVerb(dev, type, 1, format, ap); + va_end(ap); +} + + +/* Print non-driver messages with verbose level specified directly */ +void +xf86MsgVerb(MessageType type, int verb, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + LogVMessageVerb(type, verb, format, ap); + va_end(ap); +} + +/* Print non-driver messages with verbose level of 1 (default) */ +void +xf86Msg(MessageType type, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + LogVMessageVerb(type, 1, format, ap); + va_end(ap); +} + +/* Just like ErrorF, but with the verbose level checked */ +void +xf86ErrorFVerb(int verb, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + if (xf86Verbose >= verb || xf86LogVerbose >= verb) + LogVWrite(verb, format, ap); + va_end(ap); +} + +/* Like xf86ErrorFVerb, but with an implied verbose level of 1 */ +void +xf86ErrorF(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + if (xf86Verbose >= 1 || xf86LogVerbose >= 1) + LogVWrite(1, format, ap); + va_end(ap); +} + + +void +xf86LogInit(void) +{ + char *lf = NULL; + +#define LOGSUFFIX ".log" +#define LOGOLDSUFFIX ".old" + + /* Get the log file name */ + if (xf86LogFileFrom == X_DEFAULT) { + /* Append the display number and ".log" */ + if (asprintf(&lf, "%s%%s" LOGSUFFIX, xf86LogFile) == -1) + FatalError("Cannot allocate space for the log file name\n"); + xf86LogFile = lf; + } + + xf86LogFile = LogInit(xf86LogFile, LOGOLDSUFFIX); + xf86LogFileWasOpened = TRUE; + + xf86SetVerbosity(xf86Verbose); + xf86SetLogVerbosity(xf86LogVerbose); + +#undef LOGSUFFIX +#undef LOGOLDSUFFIX + + free(lf); +} + +void +xf86CloseLog(void) +{ + LogClose(); +} + + +/* + * Drivers can use these for using their own SymTabRecs. + */ + +const char * +xf86TokenToString(SymTabPtr table, int token) +{ + int i; + + for (i = 0; table[i].token >= 0 && table[i].token != token; i++) + ; + + if (table[i].token < 0) + return NULL; + else + return table[i].name; +} + +int +xf86StringToToken(SymTabPtr table, const char *string) +{ + int i; + + if (string == NULL) + return -1; + + for (i = 0; table[i].token >= 0 && xf86NameCmp(string, table[i].name); i++) + ; + + return table[i].token; +} + +/* + * helper to display the clocks found on a card + */ +void +xf86ShowClocks(ScrnInfoPtr scrp, MessageType from) +{ + int j; + + xf86DrvMsg(scrp->scrnIndex, from, "Pixel clocks available:"); + for (j=0; j < scrp->numClocks; j++) { + if ((j % 4) == 0) { + xf86ErrorF("\n"); + xf86DrvMsg(scrp->scrnIndex, from, "pixel clocks:"); + } + xf86ErrorF(" %7.3f", (double)scrp->clock[j] / 1000.0); + } + xf86ErrorF("\n"); +} + + +/* + * This prints out the driver identify message, including the names of + * the supported chipsets. + * + * XXX This makes assumptions about the line width, etc. Maybe we could + * use a more general "pretty print" function for messages. + */ +void +xf86PrintChipsets(const char *drvname, const char *drvmsg, SymTabPtr chips) +{ + int len, i; + + len = 6 + strlen(drvname) + 2 + strlen(drvmsg) + 2; + xf86Msg(X_INFO, "%s: %s:", drvname, drvmsg); + for (i = 0; chips[i].name != NULL; i++) { + if (i != 0) { + xf86ErrorF(","); + len++; + } + if (len + 2 + strlen(chips[i].name) < 78) { + xf86ErrorF(" "); + len++; + } else { + xf86ErrorF("\n\t"); + len = 8; + } + xf86ErrorF("%s", chips[i].name); + len += strlen(chips[i].name); + } + xf86ErrorF("\n"); +} + + +int +xf86MatchDevice(const char *drivername, GDevPtr **sectlist) +{ + GDevPtr gdp, *pgdp = NULL; + confScreenPtr screensecptr; + int i,j; + + if (sectlist) + *sectlist = NULL; + + /* + * This can happen when running Xorg -showopts and a module like ati + * or vmware tries to load its submodules when xf86ConfigLayout is empty + */ + if (!xf86ConfigLayout.screens) + return 0; + + /* + * This is a very important function that matches the device sections + * as they show up in the config file with the drivers that the server + * loads at run time. + * + * ChipProbe can call + * int xf86MatchDevice(char * drivername, GDevPtr ** sectlist) + * with its driver name. The function allocates an array of GDevPtr and + * returns this via sectlist and returns the number of elements in + * this list as return value. 0 means none found, -1 means fatal error. + * + * It can figure out which of the Device sections to use for which card + * (using things like the Card statement, etc). For single headed servers + * there will of course be just one such Device section. + */ + i = 0; + + /* + * first we need to loop over all the Screens sections to get to all + * 'active' device sections + */ + for (j=0; xf86ConfigLayout.screens[j].screen != NULL; j++) { + screensecptr = xf86ConfigLayout.screens[j].screen; + if ((screensecptr->device->driver != NULL) + && (xf86NameCmp( screensecptr->device->driver,drivername) == 0) + && (! screensecptr->device->claimed)) { + /* + * we have a matching driver that wasn't claimed, yet + */ + pgdp = xnfrealloc(pgdp, (i + 2) * sizeof(GDevPtr)); + pgdp[i++] = screensecptr->device; + } + } + + /* Then handle the inactive devices */ + j = 0; + while (xf86ConfigLayout.inactives[j].identifier) { + gdp = &xf86ConfigLayout.inactives[j]; + if (gdp->driver && !gdp->claimed && + !xf86NameCmp(gdp->driver,drivername)) { + /* we have a matching driver that wasn't claimed yet */ + pgdp = xnfrealloc(pgdp, (i + 2) * sizeof(GDevPtr)); + pgdp[i++] = gdp; + } + j++; + } + + /* + * make the array NULL terminated and return its address + */ + if (i) + pgdp[i] = NULL; + + if (sectlist) + *sectlist = pgdp; + else + free(pgdp); + return i; +} + +/* + * xf86GetClocks -- get the dot-clocks via a BIG BAD hack ... + */ +void +xf86GetClocks(ScrnInfoPtr pScrn, int num, Bool (*ClockFunc)(ScrnInfoPtr, int), + void (*ProtectRegs)(ScrnInfoPtr, Bool), + void (*BlankScreen)(ScrnInfoPtr, Bool), IOADDRESS vertsyncreg, + int maskval, int knownclkindex, int knownclkvalue) +{ + register int status = vertsyncreg; + unsigned long i, cnt, rcnt, sync; + + /* First save registers that get written on */ + (*ClockFunc)(pScrn, CLK_REG_SAVE); + + if (num > MAXCLOCKS) + num = MAXCLOCKS; + + for (i = 0; i < num; i++) + { + if (ProtectRegs) + (*ProtectRegs)(pScrn, TRUE); + if (!(*ClockFunc)(pScrn, i)) + { + pScrn->clock[i] = -1; + continue; + } + if (ProtectRegs) + (*ProtectRegs)(pScrn, FALSE); + if (BlankScreen) + (*BlankScreen)(pScrn, FALSE); + + usleep(50000); /* let VCO stabilise */ + + cnt = 0; + sync = 200000; + + while ((inb(status) & maskval) == 0x00) + if (sync-- == 0) goto finish; + /* Something appears to be happening, so reset sync count */ + sync = 200000; + while ((inb(status) & maskval) == maskval) + if (sync-- == 0) goto finish; + /* Something appears to be happening, so reset sync count */ + sync = 200000; + while ((inb(status) & maskval) == 0x00) + if (sync-- == 0) goto finish; + + for (rcnt = 0; rcnt < 5; rcnt++) + { + while (!(inb(status) & maskval)) + cnt++; + while ((inb(status) & maskval)) + cnt++; + } + +finish: + pScrn->clock[i] = cnt ? cnt : -1; + if (BlankScreen) + (*BlankScreen)(pScrn, TRUE); + } + + for (i = 0; i < num; i++) + { + if (i != knownclkindex) + { + if (pScrn->clock[i] == -1) + { + pScrn->clock[i] = 0; + } + else + { + pScrn->clock[i] = (int)(0.5 + + (((float)knownclkvalue) * pScrn->clock[knownclkindex]) / + (pScrn->clock[i])); + /* Round to nearest 10KHz */ + pScrn->clock[i] += 5; + pScrn->clock[i] /= 10; + pScrn->clock[i] *= 10; + } + } + } + + pScrn->clock[knownclkindex] = knownclkvalue; + pScrn->numClocks = num; + + /* Restore registers that were written on */ + (*ClockFunc)(pScrn, CLK_REG_RESTORE); +} + +const char * +xf86GetVisualName(int visual) +{ + if (visual < 0 || visual > DirectColor) + return NULL; + + return xf86VisualNames[visual]; +} + + +int +xf86GetVerbosity(void) +{ + return max(xf86Verbose, xf86LogVerbose); +} + +Pix24Flags +xf86GetPix24(void) +{ + return xf86Info.pixmap24; +} + + +int +xf86GetDepth(void) +{ + return xf86Depth; +} + + +rgb +xf86GetWeight(void) +{ + return xf86Weight; +} + + +Gamma +xf86GetGamma(void) +{ + return xf86Gamma; +} + + +Bool +xf86GetFlipPixels(void) +{ + return xf86FlipPixels; +} + + +const char * +xf86GetServerName(void) +{ + return xf86ServerName; +} + + +Bool +xf86ServerIsExiting(void) +{ + return (dispatchException & DE_TERMINATE) == DE_TERMINATE; +} + + +Bool +xf86ServerIsResetting(void) +{ + return xf86Resetting; +} + + +Bool +xf86ServerIsInitialising(void) +{ + return xf86Initialising; +} + + +Bool +xf86ServerIsOnlyDetecting(void) +{ + return xf86DoConfigure; +} + + +Bool +xf86CaughtSignal(void) +{ + return xf86Info.caughtSignal; +} + + +Bool +xf86GetVidModeAllowNonLocal(void) +{ + return xf86Info.vidModeAllowNonLocal; +} + + +Bool +xf86GetVidModeEnabled(void) +{ + return xf86Info.vidModeEnabled; +} + +Bool +xf86GetModInDevAllowNonLocal(void) +{ + return xf86Info.miscModInDevAllowNonLocal; +} + + +Bool +xf86GetModInDevEnabled(void) +{ + return xf86Info.miscModInDevEnabled; +} + + +Bool +xf86GetAllowMouseOpenFail(void) +{ + return xf86Info.allowMouseOpenFail; +} + + +Bool +xf86IsPc98(void) +{ +#if SUPPORT_PC98 + return xf86Info.pc98; +#else + return FALSE; +#endif +} + +void +xf86DisableRandR(void) +{ + xf86Info.disableRandR = TRUE; + xf86Info.randRFrom = X_PROBED; +} + +CARD32 +xf86GetModuleVersion(pointer module) +{ + return (CARD32)LoaderGetModuleVersion(module); +} + +pointer +xf86LoadDrvSubModule(DriverPtr drv, const char *name) +{ + pointer ret; + int errmaj = 0, errmin = 0; + + ret = LoadSubModule(drv->module, name, NULL, NULL, NULL, NULL, + &errmaj, &errmin); + if (!ret) + LoaderErrorMsg(NULL, name, errmaj, errmin); + return ret; +} + +pointer +xf86LoadSubModule(ScrnInfoPtr pScrn, const char *name) +{ + pointer ret; + int errmaj = 0, errmin = 0; + + ret = LoadSubModule(pScrn->module, name, NULL, NULL, NULL, NULL, + &errmaj, &errmin); + if (!ret) + LoaderErrorMsg(pScrn->name, name, errmaj, errmin); + return ret; +} + +/* + * xf86LoadOneModule loads a single module. + */ +pointer +xf86LoadOneModule(char *name, pointer opt) +{ + int errmaj, errmin; + char *Name; + pointer mod; + + if (!name) + return NULL; + + /* Normalise the module name */ + Name = xf86NormalizeName(name); + + /* Skip empty names */ + if (Name == NULL) + return NULL; + if (*Name == '\0') { + free(Name); + return NULL; + } + + mod = LoadModule(Name, NULL, NULL, NULL, opt, NULL, &errmaj, &errmin); + if (!mod) + LoaderErrorMsg(NULL, Name, errmaj, errmin); + free(Name); + return mod; +} + +void +xf86UnloadSubModule(pointer mod) +{ + /* + * This is disabled for now. The loader isn't smart enough yet to undo + * relocations. + */ +#if 0 + UnloadSubModule(mod); +#endif +} + +Bool +xf86LoaderCheckSymbol(const char *name) +{ + return LoaderSymbol(name) != NULL; +} + +typedef enum { + OPTION_BACKING_STORE +} BSOpts; + +static const OptionInfoRec BSOptions[] = { + { OPTION_BACKING_STORE, "BackingStore", OPTV_BOOLEAN, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + +void +xf86SetBackingStore(ScreenPtr pScreen) +{ + Bool useBS = FALSE; + MessageType from = X_DEFAULT; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + OptionInfoPtr options; + + options = xnfalloc(sizeof(BSOptions)); + (void)memcpy(options, BSOptions, sizeof(BSOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); + + /* check for commandline option here */ + if (xf86bsEnableFlag) { + from = X_CMDLINE; + useBS = TRUE; + } else if (xf86bsDisableFlag) { + from = X_CMDLINE; + useBS = FALSE; + } else { + if (xf86GetOptValBool(options, OPTION_BACKING_STORE, &useBS)) + from = X_CONFIG; + } + free(options); + pScreen->backingStoreSupport = useBS ? Always : NotUseful; + if (serverGeneration == 1) + xf86DrvMsg(pScreen->myNum, from, "Backing store %s\n", + useBS ? "enabled" : "disabled"); +} + + +typedef enum { + OPTION_SILKEN_MOUSE +} SMOpts; + +static const OptionInfoRec SMOptions[] = { + { OPTION_SILKEN_MOUSE, "SilkenMouse", OPTV_BOOLEAN, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + +void +xf86SetSilkenMouse (ScreenPtr pScreen) +{ + Bool useSM = TRUE; + MessageType from = X_DEFAULT; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + OptionInfoPtr options; + + options = xnfalloc(sizeof(SMOptions)); + (void)memcpy(options, SMOptions, sizeof(SMOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); + + /* check for commandline option here */ + /* disable if screen shares resources */ + /* TODO VGA arb disable silken mouse */ + if (xf86silkenMouseDisableFlag) { + from = X_CMDLINE; + useSM = FALSE; + } else { + if (xf86GetOptValBool(options, OPTION_SILKEN_MOUSE, &useSM)) + from = X_CONFIG; + } + free(options); + /* + * XXX quick hack to report correctly for OSs that can't do SilkenMouse + * yet. Should handle this differently so that alternate async methods + * work correctly with this too. + */ + pScrn->silkenMouse = useSM && xf86Info.useSIGIO && xf86SIGIOSupported(); + if (serverGeneration == 1) + xf86DrvMsg(pScreen->myNum, from, "Silken mouse %s\n", + pScrn->silkenMouse ? "enabled" : "disabled"); +} + +/* Wrote this function for the PM2 Xv driver, preliminary. */ + +pointer +xf86FindXvOptions(int scrnIndex, int adaptor_index, char *port_name, + char **adaptor_name, pointer *adaptor_options) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + confXvAdaptorPtr adaptor; + int i; + + if (adaptor_index >= pScrn->confScreen->numxvadaptors) { + if (adaptor_name) *adaptor_name = NULL; + if (adaptor_options) *adaptor_options = NULL; + return NULL; + } + + adaptor = &pScrn->confScreen->xvadaptors[adaptor_index]; + if (adaptor_name) *adaptor_name = adaptor->identifier; + if (adaptor_options) *adaptor_options = adaptor->options; + + for (i = 0; i < adaptor->numports; i++) + if (!xf86NameCmp(adaptor->ports[i].identifier, port_name)) + return adaptor->ports[i].options; + + return NULL; +} + +/* Rather than duplicate loader's get OS function, just include it directly */ +#define LoaderGetOS xf86GetOS +#include "loader/os.c" + +static void +xf86ConfigFbEntityInactive(EntityInfoPtr pEnt, EntityProc init, + EntityProc enter, EntityProc leave, pointer private) +{ + ScrnInfoPtr pScrn; + + if ((pScrn = xf86FindScreenForEntity(pEnt->index))) + xf86RemoveEntityFromScreen(pScrn,pEnt->index); + xf86SetEntityFuncs(pEnt->index,init,enter,leave,private); +} + +ScrnInfoPtr +xf86ConfigFbEntity(ScrnInfoPtr pScrn, int scrnFlag, int entityIndex, + EntityProc init, EntityProc enter, EntityProc leave, + pointer private) +{ + EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex); + if (!pEnt) return pScrn; + + if (!(pEnt->location.type == BUS_NONE)) { + free(pEnt); + return pScrn; + } + + if (!pEnt->active) { + xf86ConfigFbEntityInactive(pEnt, init, enter, leave, private); + free(pEnt); + return pScrn; + } + + if (!pScrn) + pScrn = xf86AllocateScreen(pEnt->driver,scrnFlag); + xf86AddEntityToScreen(pScrn,entityIndex); + + xf86SetEntityFuncs(entityIndex,init,enter,leave,private); + + free(pEnt); + return pScrn; +} + +Bool +xf86IsScreenPrimary(int scrnIndex) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + int i; + + for (i=0 ; i < pScrn->numEntities; i++) { + if (xf86IsEntityPrimary(i)) + return TRUE; + } + return FALSE; +} + +int +xf86RegisterRootWindowProperty(int ScrnIndex, Atom property, Atom type, + int format, unsigned long len, pointer value ) +{ + RootWinPropPtr pNewProp = NULL, pRegProp; + int i; + Bool existing = FALSE; + + DebugF("xf86RegisterRootWindowProperty(%d, %ld, %ld, %d, %ld, %p)\n", + ScrnIndex, property, type, format, len, value); + + if (ScrnIndex<0 || ScrnIndex>=xf86NumScreens) { + return BadMatch; + } + + if (xf86RegisteredPropertiesTable && + xf86RegisteredPropertiesTable[ScrnIndex]) { + for (pNewProp = xf86RegisteredPropertiesTable[ScrnIndex]; + pNewProp; pNewProp = pNewProp->next) { + if (strcmp(pNewProp->name, NameForAtom(property)) == 0) + break; + } + } + + if (!pNewProp) { + if ((pNewProp = (RootWinPropPtr)malloc(sizeof(RootWinProp))) == NULL) { + return BadAlloc; + } + /* + * We will put this property at the end of the list so that + * the changes are made in the order they were requested. + */ + pNewProp->next = NULL; + } else { + free(pNewProp->name); + existing = TRUE; + } + + pNewProp->name = xnfstrdup(NameForAtom(property)); + pNewProp->type = type; + pNewProp->format = format; + pNewProp->size = len; + pNewProp->data = value; + + DebugF("new property filled\n"); + + if (NULL==xf86RegisteredPropertiesTable) { + DebugF("creating xf86RegisteredPropertiesTable[] size %d\n", + xf86NumScreens); + if ( NULL==(xf86RegisteredPropertiesTable=(RootWinPropPtr*)xnfcalloc(sizeof(RootWinProp),xf86NumScreens) )) { + return BadAlloc; + } + for (i=0; i<xf86NumScreens; i++) { + xf86RegisteredPropertiesTable[i] = NULL; + } + } + + DebugF("xf86RegisteredPropertiesTable %p\n", + (void *)xf86RegisteredPropertiesTable); + DebugF("xf86RegisteredPropertiesTable[%d] %p\n", + ScrnIndex, (void *)xf86RegisteredPropertiesTable[ScrnIndex]); + + if (!existing) { + if ( xf86RegisteredPropertiesTable[ScrnIndex] == NULL) { + xf86RegisteredPropertiesTable[ScrnIndex] = pNewProp; + } else { + pRegProp = xf86RegisteredPropertiesTable[ScrnIndex]; + while (pRegProp->next != NULL) { + DebugF("- next %p\n", (void *)pRegProp); + pRegProp = pRegProp->next; + } + pRegProp->next = pNewProp; + } + } + DebugF("xf86RegisterRootWindowProperty succeeded\n"); + return Success; +} + +Bool +xf86IsUnblank(int mode) +{ + switch(mode) { + case SCREEN_SAVER_OFF: + case SCREEN_SAVER_FORCER: + return TRUE; + case SCREEN_SAVER_ON: + case SCREEN_SAVER_CYCLE: + return FALSE; + default: + xf86MsgVerb(X_WARNING, 0, "Unexpected save screen mode: %d\n", mode); + return TRUE; + } +} + +void +xf86MotionHistoryAllocate(InputInfoPtr pInfo) +{ + AllocateMotionHistory(pInfo->dev); +} diff --git a/hw/xfree86/common/xf86InPriv.h b/hw/xfree86/common/xf86InPriv.h new file mode 100644 index 0000000..1b9b502 --- /dev/null +++ b/hw/xfree86/common/xf86InPriv.h @@ -0,0 +1,43 @@ + +/* + * Copyright (c) 1999 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#ifndef _xf86InPriv_h +#define _xf86InPriv_h + +/* xf86Globals.c */ +extern InputDriverPtr *xf86InputDriverList; +extern int xf86NumInputDrivers; + +/* xf86Helper.c */ +InputDriverPtr xf86LookupInputDriver(const char *name); + +#endif /* _xf86InPriv_h */ diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c new file mode 100644 index 0000000..0b36163 --- /dev/null +++ b/hw/xfree86/common/xf86Init.c @@ -0,0 +1,1499 @@ +/* + * Loosely based on code bearing the following copyright: + * + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + */ +/* + * Copyright (c) 1992-2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <stdlib.h> +#include <errno.h> + +#undef HAS_UTSNAME +#if !defined(WIN32) +#define HAS_UTSNAME 1 +#include <sys/utsname.h> +#endif + +#include <X11/X.h> +#include <X11/Xmd.h> +#include <X11/Xproto.h> +#include <X11/Xatom.h> +#include "input.h" +#include "servermd.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "site.h" +#include "mi.h" + +#include "compiler.h" + +#include "loaderProcs.h" +#ifdef XFreeXDGA +#include "dgaproc.h" +#endif + +#define XF86_OS_PRIVS +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86Config.h" +#include "xf86_OSlib.h" +#include "xf86cmap.h" +#include "xorgVersion.h" +#include "xf86Build.h" +#include "mipointer.h" +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include "xf86DDC.h" +#include "xf86Xinput.h" +#include "xf86InPriv.h" +#include "picturestr.h" + +#include "xf86Bus.h" +#include "xf86VGAarbiter.h" +#include "globals.h" + +#ifdef DPMSExtension +#include <X11/extensions/dpmsconst.h> +#include "dpmsproc.h" +#endif +#include <hotplug.h> + + +#ifdef XF86PM +void (*xf86OSPMClose)(void) = NULL; +#endif +static Bool xorgHWOpenConsole = FALSE; + +/* Common pixmap formats */ + +static PixmapFormatRec formats[MAXFORMATS] = { + { 1, 1, BITMAP_SCANLINE_PAD }, + { 4, 8, BITMAP_SCANLINE_PAD }, + { 8, 8, BITMAP_SCANLINE_PAD }, + { 15, 16, BITMAP_SCANLINE_PAD }, + { 16, 16, BITMAP_SCANLINE_PAD }, + { 24, 32, BITMAP_SCANLINE_PAD }, + { 32, 32, BITMAP_SCANLINE_PAD }, +}; +static int numFormats = 7; +static Bool formatsDone = FALSE; + +#ifndef OSNAME +#define OSNAME " unknown" +#endif +#ifndef OSVENDOR +#define OSVENDOR "" +#endif +#ifndef PRE_RELEASE +#define PRE_RELEASE XORG_VERSION_SNAP +#endif + +static void +xf86PrintBanner(void) +{ +#if PRE_RELEASE + xf86ErrorFVerb(0, "\n" + "This is a pre-release version of the X server from " XVENDORNAME ".\n" + "It is not supported in any way.\n" + "Bugs may be filed in the bugzilla at http://bugs.freedesktop.org/.\n" + "Select the \"xorg\" product for bugs you find in this release.\n" + "Before reporting bugs in pre-release versions please check the\n" + "latest version in the X.Org Foundation git repository.\n" + "See http://wiki.x.org/wiki/GitPage for git access instructions.\n"); +#endif + xf86ErrorFVerb(0, "\nX.Org X Server %d.%d.%d", + XORG_VERSION_MAJOR, + XORG_VERSION_MINOR, + XORG_VERSION_PATCH); +#if XORG_VERSION_SNAP > 0 + xf86ErrorFVerb(0, ".%d", XORG_VERSION_SNAP); +#endif + +#if XORG_VERSION_SNAP >= 900 + /* When the minor number is 99, that signifies that the we are making + * a release candidate for a major version. (X.0.0) + * When the patch number is 99, that signifies that the we are making + * a release candidate for a minor version. (X.Y.0) + * When the patch number is < 99, then we are making a release + * candidate for the next point release. (X.Y.Z) + */ +#if XORG_VERSION_MINOR >= 99 + xf86ErrorFVerb(0, " (%d.0.0 RC %d)", XORG_VERSION_MAJOR+1, + XORG_VERSION_SNAP - 900); +#elif XORG_VERSION_PATCH == 99 + xf86ErrorFVerb(0, " (%d.%d.0 RC %d)", XORG_VERSION_MAJOR, + XORG_VERSION_MINOR + 1, XORG_VERSION_SNAP - 900); +#else + xf86ErrorFVerb(0, " (%d.%d.%d RC %d)", XORG_VERSION_MAJOR, + XORG_VERSION_MINOR, XORG_VERSION_PATCH + 1, + XORG_VERSION_SNAP - 900); +#endif +#endif + +#ifdef XORG_CUSTOM_VERSION + xf86ErrorFVerb(0, " (%s)", XORG_CUSTOM_VERSION); +#endif +#ifndef XORG_DATE +# define XORG_DATE "Unknown" +#endif + xf86ErrorFVerb(0, "\nRelease Date: %s\n", XORG_DATE); + xf86ErrorFVerb(0, "X Protocol Version %d, Revision %d\n", + X_PROTOCOL, X_PROTOCOL_REVISION); + xf86ErrorFVerb(0, "Build Operating System: %s %s\n", OSNAME, OSVENDOR); +#ifdef HAS_UTSNAME + { + struct utsname name; + + /* Linux & BSD state that 0 is success, SysV (including Solaris, HP-UX, + and Irix) and Single Unix Spec 3 just say that non-negative is success. + All agree that failure is represented by a negative number. + */ + if (uname(&name) >= 0) { + xf86ErrorFVerb(0, "Current Operating System: %s %s %s %s %s\n", + name.sysname, name.nodename, name.release, name.version, name.machine); +#ifdef linux + do { + char buf[80]; + int fd = open("/proc/cmdline", O_RDONLY); + if (fd != -1) { + xf86ErrorFVerb(0, "Kernel command line: "); + memset(buf, 0, 80); + while (read(fd, buf, 80) > 0) { + xf86ErrorFVerb(0, "%.80s", buf); + memset(buf, 0, 80); + } + close(fd); + } + } while (0); +#endif + } + } +#endif +#if defined(BUILD_DATE) && (BUILD_DATE > 19000000) + { + struct tm t; + char buf[100]; + + memset(&t, 0, sizeof(t)); + memset(buf, 0, sizeof(buf)); + t.tm_mday = BUILD_DATE % 100; + t.tm_mon = (BUILD_DATE / 100) % 100 - 1; + t.tm_year = BUILD_DATE / 10000 - 1900; +#if defined(BUILD_TIME) + t.tm_sec = BUILD_TIME % 100; + t.tm_min = (BUILD_TIME / 100) % 100; + t.tm_hour = (BUILD_TIME / 10000) % 100; + if (strftime(buf, sizeof(buf), "%d %B %Y %I:%M:%S%p", &t)) + xf86ErrorFVerb(0, "Build Date: %s\n", buf); +#else + if (strftime(buf, sizeof(buf), "%d %B %Y", &t)) + xf86ErrorFVerb(0, "Build Date: %s\n", buf); +#endif + } +#endif +#if defined(BUILDERSTRING) + xf86ErrorFVerb(0, "%s \n", BUILDERSTRING); +#endif + xf86ErrorFVerb(0, "Current version of pixman: %s\n", + pixman_version_string()); + xf86ErrorFVerb(0, "\tBefore reporting problems, check " + ""__VENDORDWEBSUPPORT__"\n" + "\tto make sure that you have the latest version.\n"); +} + +static void +xf86PrintMarkers(void) +{ + LogPrintMarkers(); +} + +static Bool +xf86CreateRootWindow(WindowPtr pWin) +{ + int ret = TRUE; + int err = Success; + ScreenPtr pScreen = pWin->drawable.pScreen; + RootWinPropPtr pProp; + CreateWindowProcPtr CreateWindow = (CreateWindowProcPtr) + dixLookupPrivate(&pScreen->devPrivates, xf86CreateRootWindowKey); + + DebugF("xf86CreateRootWindow(%p)\n", pWin); + + if ( pScreen->CreateWindow != xf86CreateRootWindow ) { + /* Can't find hook we are hung on */ + xf86DrvMsg(pScreen->myNum, X_WARNING /* X_ERROR */, + "xf86CreateRootWindow %p called when not in pScreen->CreateWindow %p n", + (void *)xf86CreateRootWindow, + (void *)pScreen->CreateWindow ); + } + + /* Unhook this function ... */ + pScreen->CreateWindow = CreateWindow; + dixSetPrivate(&pScreen->devPrivates, xf86CreateRootWindowKey, NULL); + + /* ... and call the previous CreateWindow fuction, if any */ + if (NULL!=pScreen->CreateWindow) { + ret = (*pScreen->CreateWindow)(pWin); + } + + /* Now do our stuff */ + if (xf86RegisteredPropertiesTable != NULL) { + if (pWin->parent == NULL && xf86RegisteredPropertiesTable != NULL) { + for (pProp = xf86RegisteredPropertiesTable[pScreen->myNum]; + pProp != NULL && err==Success; + pProp = pProp->next ) + { + Atom prop; + + prop = MakeAtom(pProp->name, strlen(pProp->name), TRUE); + err = dixChangeWindowProperty(serverClient, pWin, + prop, pProp->type, + pProp->format, PropModeReplace, + pProp->size, pProp->data, + FALSE); + } + + /* Look at err */ + ret &= (err==Success); + + } else { + xf86Msg(X_ERROR, "xf86CreateRootWindow unexpectedly called with " + "non-root window %p (parent %p)\n", + (void *)pWin, (void *)pWin->parent); + ret = FALSE; + } + } + + DebugF("xf86CreateRootWindow() returns %d\n", ret); + return ret; +} + + +static void +InstallSignalHandlers(void) +{ + /* + * Install signal handler for unexpected signals + */ + xf86Info.caughtSignal=FALSE; + if (!xf86Info.notrapSignals) { + OsRegisterSigWrapper(xf86SigWrapper); + } else { + signal(SIGSEGV, SIG_DFL); + signal(SIGILL, SIG_DFL); +#ifdef SIGEMT + signal(SIGEMT, SIG_DFL); +#endif + signal(SIGFPE, SIG_DFL); + signal(SIGBUS, SIG_DFL); + signal(SIGSYS, SIG_DFL); + signal(SIGXCPU, SIG_DFL); + signal(SIGXFSZ, SIG_DFL); + } +} + +/* + * InitOutput -- + * Initialize screenInfo for all actually accessible framebuffers. + * That includes vt-manager setup, querying all possible devices and + * collecting the pixmap formats. + */ +void +InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv) +{ + int i, j, k, scr_index, was_blocked = 0; + char **modulelist; + pointer *optionlist; + Pix24Flags screenpix24, pix24; + MessageType pix24From = X_DEFAULT; + Bool pix24Fail = FALSE; + Bool autoconfig = FALSE; + GDevPtr configured_device; + + xf86Initialising = TRUE; + + if (serverGeneration == 1) { + if ((xf86ServerName = strrchr(argv[0], '/')) != 0) + xf86ServerName++; + else + xf86ServerName = argv[0]; + + xf86PrintBanner(); + xf86PrintMarkers(); + if (xf86LogFile) { + time_t t; + const char *ct; + t = time(NULL); + ct = ctime(&t); + xf86MsgVerb(xf86LogFileFrom, 0, "Log file: \"%s\", Time: %s", + xf86LogFile, ct); + } + + /* Read and parse the config file */ + if (!xf86DoConfigure && !xf86DoShowOptions) { + switch (xf86HandleConfigFile(FALSE)) { + case CONFIG_OK: + break; + case CONFIG_PARSE_ERROR: + xf86Msg(X_ERROR, "Error parsing the config file\n"); + return; + case CONFIG_NOFILE: + autoconfig = TRUE; + break; + } + } + + InstallSignalHandlers(); + + /* Initialise the loader */ + LoaderInit(); + + /* Tell the loader the default module search path */ + LoaderSetPath(xf86ModulePath); + + if (xf86Info.ignoreABI) { + LoaderSetOptions(LDR_OPT_ABI_MISMATCH_NONFATAL); + } + + if (xf86DoShowOptions) + DoShowOptions(); + + /* Do a general bus probe. This will be a PCI probe for x86 platforms */ + xf86BusProbe(); + + if (xf86DoConfigure) + DoConfigure(); + + if (autoconfig) { + if (!xf86AutoConfig()) { + xf86Msg(X_ERROR, "Auto configuration failed\n"); + return; + } + } + +#ifdef XF86PM + xf86OSPMClose = xf86OSPMOpen(); +#endif + + /* Load all modules specified explicitly in the config file */ + if ((modulelist = xf86ModulelistFromConfig(&optionlist))) { + xf86LoadModules(modulelist, optionlist); + free(modulelist); + free(optionlist); + } + + /* Load all driver modules specified in the config file */ + /* If there aren't any specified in the config file, autoconfig them */ + /* FIXME: Does not handle multiple active screen sections, but I'm not + * sure if we really want to handle that case*/ + configured_device = xf86ConfigLayout.screens->screen->device; + if ((!configured_device) || (!configured_device->driver)) { + if (!autoConfigDevice(configured_device)) { + xf86Msg(X_ERROR, "Automatic driver configuration failed\n"); + return ; + } + } + if ((modulelist = xf86DriverlistFromConfig())) { + xf86LoadModules(modulelist, NULL); + free(modulelist); + } + + /* Load all input driver modules specified in the config file. */ + if ((modulelist = xf86InputDriverlistFromConfig())) { + xf86LoadModules(modulelist, NULL); + free(modulelist); + } + + /* + * It is expected that xf86AddDriver()/xf86AddInputDriver will be + * called for each driver as it is loaded. Those functions save the + * module pointers for drivers. + * XXX Nothing keeps track of them for other modules. + */ + /* XXX What do we do if not all of these could be loaded? */ + + /* + * At this point, xf86DriverList[] is all filled in with entries for + * each of the drivers to try and xf86NumDrivers has the number of + * drivers. If there are none, return now. + */ + + if (xf86NumDrivers == 0) { + xf86Msg(X_ERROR, "No drivers available.\n"); + return; + } + + /* + * Call each of the Identify functions and call the driverFunc to check + * if HW access is required. The Identify functions print out some + * identifying information, and anything else that might be + * needed at this early stage. + */ + + for (i = 0; i < xf86NumDrivers; i++) { + if (xf86DriverList[i]->Identify != NULL) + xf86DriverList[i]->Identify(0); + + if (!xorgHWAccess || !xorgHWOpenConsole) { + xorgHWFlags flags; + if(!xf86DriverList[i]->driverFunc + || !xf86DriverList[i]->driverFunc(NULL, + GET_REQUIRED_HW_INTERFACES, + &flags)) + flags = HW_IO; + + if(NEED_IO_ENABLED(flags)) + xorgHWAccess = TRUE; + if(!(flags & HW_SKIP_CONSOLE)) + xorgHWOpenConsole = TRUE; + } + } + + if (xorgHWOpenConsole) + xf86OpenConsole(); + else + xf86Info.dontVTSwitch = TRUE; + + if (xf86BusConfig() == FALSE) + return; + + xf86PostProbe(); + + /* + * Sort the drivers to match the requested ording. Using a slow + * bubble sort. + */ + for (j = 0; j < xf86NumScreens - 1; j++) { + for (i = 0; i < xf86NumScreens - j - 1; i++) { + if (xf86Screens[i + 1]->confScreen->screennum < + xf86Screens[i]->confScreen->screennum) { + ScrnInfoPtr tmpScrn = xf86Screens[i + 1]; + xf86Screens[i + 1] = xf86Screens[i]; + xf86Screens[i] = tmpScrn; + } + } + } + /* Fix up the indexes */ + for (i = 0; i < xf86NumScreens; i++) { + xf86Screens[i]->scrnIndex = i; + } + + /* + * Call the driver's PreInit()'s to complete initialisation for the first + * generation. + */ + + for (i = 0; i < xf86NumScreens; i++) { + xf86VGAarbiterScrnInit(xf86Screens[i]); + xf86VGAarbiterLock(xf86Screens[i]); + if (xf86Screens[i]->PreInit && + xf86Screens[i]->PreInit(xf86Screens[i], 0)) + xf86Screens[i]->configured = TRUE; + xf86VGAarbiterUnlock(xf86Screens[i]); + } + for (i = 0; i < xf86NumScreens; i++) + if (!xf86Screens[i]->configured) + xf86DeleteScreen(i--, 0); + + /* + * If no screens left, return now. + */ + + if (xf86NumScreens == 0) { + xf86Msg(X_ERROR, + "Screen(s) found, but none have a usable configuration.\n"); + return; + } + + for (i = 0; i < xf86NumScreens; i++) { + if (xf86Screens[i]->name == NULL) { + XNFasprintf(&xf86Screens[i]->name, "screen%d", i); + xf86MsgVerb(X_WARNING, 0, + "Screen driver %d has no name set, using `%s'.\n", + i, xf86Screens[i]->name); + } + } + + /* Remove (unload) drivers that are not required */ + for (i = 0; i < xf86NumDrivers; i++) + if (xf86DriverList[i] && xf86DriverList[i]->refCount <= 0) + xf86DeleteDriver(i); + + /* + * At this stage we know how many screens there are. + */ + + for (i = 0; i < xf86NumScreens; i++) + xf86InitViewport(xf86Screens[i]); + + /* + * Collect all pixmap formats and check for conflicts at the display + * level. Should we die here? Or just delete the offending screens? + */ + screenpix24 = Pix24DontCare; + for (i = 0; i < xf86NumScreens; i++) { + if (xf86Screens[i]->imageByteOrder != + xf86Screens[0]->imageByteOrder) + FatalError("Inconsistent display bitmapBitOrder. Exiting\n"); + if (xf86Screens[i]->bitmapScanlinePad != + xf86Screens[0]->bitmapScanlinePad) + FatalError("Inconsistent display bitmapScanlinePad. Exiting\n"); + if (xf86Screens[i]->bitmapScanlineUnit != + xf86Screens[0]->bitmapScanlineUnit) + FatalError("Inconsistent display bitmapScanlineUnit. Exiting\n"); + if (xf86Screens[i]->bitmapBitOrder != + xf86Screens[0]->bitmapBitOrder) + FatalError("Inconsistent display bitmapBitOrder. Exiting\n"); + + /* Determine the depth 24 pixmap format the screens would like */ + if (xf86Screens[i]->pixmap24 != Pix24DontCare) { + if (screenpix24 == Pix24DontCare) + screenpix24 = xf86Screens[i]->pixmap24; + else if (screenpix24 != xf86Screens[i]->pixmap24) + FatalError("Inconsistent depth 24 pixmap format. Exiting\n"); + } + } + /* check if screenpix24 is consistent with the config/cmdline */ + if (xf86Info.pixmap24 != Pix24DontCare) { + pix24 = xf86Info.pixmap24; + pix24From = xf86Info.pix24From; + if (screenpix24 != Pix24DontCare && screenpix24 != xf86Info.pixmap24) + pix24Fail = TRUE; + } else if (screenpix24 != Pix24DontCare) { + pix24 = screenpix24; + pix24From = X_PROBED; + } else + pix24 = Pix24Use32; + + if (pix24Fail) + FatalError("Screen(s) can't use the required depth 24 pixmap format" + " (%d). Exiting\n", PIX24TOBPP(pix24)); + + /* Initialise the depth 24 format */ + for (j = 0; j < numFormats && formats[j].depth != 24; j++) + ; + formats[j].bitsPerPixel = PIX24TOBPP(pix24); + + /* Collect additional formats */ + for (i = 0; i < xf86NumScreens; i++) { + for (j = 0; j < xf86Screens[i]->numFormats; j++) { + for (k = 0; ; k++) { + if (k >= numFormats) { + if (k >= MAXFORMATS) + FatalError("Too many pixmap formats! Exiting\n"); + formats[k] = xf86Screens[i]->formats[j]; + numFormats++; + break; + } + if (formats[k].depth == xf86Screens[i]->formats[j].depth) { + if ((formats[k].bitsPerPixel == + xf86Screens[i]->formats[j].bitsPerPixel) && + (formats[k].scanlinePad == + xf86Screens[i]->formats[j].scanlinePad)) + break; + FatalError("Inconsistent pixmap format for depth %d." + " Exiting\n", formats[k].depth); + } + } + } + } + formatsDone = TRUE; + + if (xf86Info.vtno >= 0 ) { +#define VT_ATOM_NAME "XFree86_VT" + Atom VTAtom=-1; + CARD32 *VT = NULL; + int ret; + + /* This memory needs to stay available until the screen has been + initialized, and we can create the property for real. + */ + if ( (VT = malloc(sizeof(CARD32)))==NULL ) { + FatalError("Unable to make VT property - out of memory. Exiting...\n"); + } + *VT = xf86Info.vtno; + + VTAtom = MakeAtom(VT_ATOM_NAME, sizeof(VT_ATOM_NAME) - 1, TRUE); + + for (i = 0, ret = Success; i < xf86NumScreens && ret == Success; i++) { + ret = xf86RegisterRootWindowProperty(xf86Screens[i]->scrnIndex, + VTAtom, XA_INTEGER, 32, + 1, VT ); + if (ret != Success) + xf86DrvMsg(xf86Screens[i]->scrnIndex, X_WARNING, + "Failed to register VT property\n"); + } + } + + /* If a screen uses depth 24, show what the pixmap format is */ + for (i = 0; i < xf86NumScreens; i++) { + if (xf86Screens[i]->depth == 24) { + xf86Msg(pix24From, "Depth 24 pixmap format is %d bpp\n", + PIX24TOBPP(pix24)); + break; + } + } + } else { + /* + * serverGeneration != 1; some OSs have to do things here, too. + */ + if (xorgHWOpenConsole) + xf86OpenConsole(); + +#ifdef XF86PM + /* + should we reopen it here? We need to deal with an already opened + device. We could leave this to the OS layer. For now we simply + close it here + */ + if (xf86OSPMClose) + xf86OSPMClose(); + if ((xf86OSPMClose = xf86OSPMOpen()) != NULL) + xf86MsgVerb(X_INFO, 3, "APM registered successfully\n"); +#endif + + /* Make sure full I/O access is enabled */ + if (xorgHWAccess) + xf86EnableIO(); + } + + /* + * Use the previously collected parts to setup pScreenInfo + */ + + pScreenInfo->imageByteOrder = xf86Screens[0]->imageByteOrder; + pScreenInfo->bitmapScanlinePad = xf86Screens[0]->bitmapScanlinePad; + pScreenInfo->bitmapScanlineUnit = xf86Screens[0]->bitmapScanlineUnit; + pScreenInfo->bitmapBitOrder = xf86Screens[0]->bitmapBitOrder; + pScreenInfo->numPixmapFormats = numFormats; + for (i = 0; i < numFormats; i++) + pScreenInfo->formats[i] = formats[i]; + + /* Make sure the server's VT is active */ + + if (serverGeneration != 1) { + xf86Resetting = TRUE; + /* All screens are in the same state, so just check the first */ + if (!xf86Screens[0]->vtSema) { +#ifdef HAS_USL_VTS + ioctl(xf86Info.consoleFd, VT_RELDISP, VT_ACKACQ); +#endif + xf86AccessEnter(); + was_blocked = xf86BlockSIGIO(); + } + } + + for (i = 0; i < xf86NumScreens; i++) + if (!xf86ColormapAllocatePrivates(xf86Screens[i])) + FatalError("Cannot register DDX private keys"); + + if (!dixRegisterPrivateKey(&xf86ScreenKeyRec, PRIVATE_SCREEN, 0) || + !dixRegisterPrivateKey(&xf86CreateRootWindowKeyRec, PRIVATE_SCREEN, 0)) + FatalError("Cannot register DDX private keys"); + + for (i = 0; i < xf86NumScreens; i++) { + xf86VGAarbiterLock(xf86Screens[i]); + /* + * Almost everything uses these defaults, and many of those that + * don't, will wrap them. + */ + xf86Screens[i]->EnableDisableFBAccess = xf86EnableDisableFBAccess; +#ifdef XFreeXDGA + xf86Screens[i]->SetDGAMode = xf86SetDGAMode; +#endif + xf86Screens[i]->DPMSSet = NULL; + xf86Screens[i]->LoadPalette = NULL; + xf86Screens[i]->SetOverscan = NULL; + xf86Screens[i]->DriverFunc = NULL; + xf86Screens[i]->pScreen = NULL; + scr_index = AddScreen(xf86Screens[i]->ScreenInit, argc, argv); + xf86VGAarbiterUnlock(xf86Screens[i]); + if (scr_index == i) { + /* + * Hook in our ScrnInfoRec, and initialise some other pScreen + * fields. + */ + dixSetPrivate(&screenInfo.screens[scr_index]->devPrivates, + xf86ScreenKey, xf86Screens[i]); + xf86Screens[i]->pScreen = screenInfo.screens[scr_index]; + /* The driver should set this, but make sure it is set anyway */ + xf86Screens[i]->vtSema = TRUE; + } else { + /* This shouldn't normally happen */ + FatalError("AddScreen/ScreenInit failed for driver %d\n", i); + } + + DebugF("InitOutput - xf86Screens[%d]->pScreen = %p\n", + i, xf86Screens[i]->pScreen ); + DebugF("xf86Screens[%d]->pScreen->CreateWindow = %p\n", + i, xf86Screens[i]->pScreen->CreateWindow ); + + dixSetPrivate(&screenInfo.screens[scr_index]->devPrivates, + xf86CreateRootWindowKey, + xf86Screens[i]->pScreen->CreateWindow); + xf86Screens[i]->pScreen->CreateWindow = xf86CreateRootWindow; + + if (PictureGetSubpixelOrder (xf86Screens[i]->pScreen) == SubPixelUnknown) + { + xf86MonPtr DDC = (xf86MonPtr)(xf86Screens[i]->monitor->DDC); + PictureSetSubpixelOrder (xf86Screens[i]->pScreen, + DDC ? + (DDC->features.input_type ? + SubPixelHorizontalRGB : SubPixelNone) : + SubPixelUnknown); + } +#ifdef RANDR + if (!xf86Info.disableRandR) + xf86RandRInit (screenInfo.screens[scr_index]); + xf86Msg(xf86Info.randRFrom, "RandR %s\n", + xf86Info.disableRandR ? "disabled" : "enabled"); +#endif + } + + xf86VGAarbiterWrapFunctions(); + xf86UnblockSIGIO(was_blocked); + + xf86InitOrigins(); + + xf86Resetting = FALSE; + xf86Initialising = FALSE; + + RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, xf86Wakeup, + NULL); +} + +/* + * InitInput -- + * Initialize all supported input devices. + */ + +void +InitInput(int argc, char **argv) +{ + InputInfoPtr* pDev; + DeviceIntPtr dev; + + xf86Info.vtRequestsPending = FALSE; + + mieqInit(); + + GetEventList(&xf86Events); + + /* Initialize all configured input devices */ + for (pDev = xf86ConfigLayout.inputs; pDev && *pDev; pDev++) { + /* Replace obsolete keyboard driver with kbd */ + if (!xf86NameCmp((*pDev)->driver, "keyboard")) { + strcpy((*pDev)->driver, "kbd"); + } + + /* If one fails, the others will too */ + if (xf86NewInputDevice(*pDev, &dev, TRUE) == BadAlloc) + break; + } + + config_init(); +} + +void +CloseInput (void) +{ + config_fini(); +} + +/* + * OsVendorInit -- + * OS/Vendor-specific initialisations. Called from OsInit(), which + * is called by dix before establishing the well known sockets. + */ + +void +OsVendorInit(void) +{ + static Bool beenHere = FALSE; + + signal(SIGCHLD, SIG_DFL); /* Need to wait for child processes */ + + if (!beenHere) { + umask(022); + xf86LogInit(); + } + + /* Set stderr to non-blocking. */ +#ifndef O_NONBLOCK +#if defined(FNDELAY) +#define O_NONBLOCK FNDELAY +#elif defined(O_NDELAY) +#define O_NONBLOCK O_NDELAY +#endif + +#ifdef O_NONBLOCK + if (!beenHere) { + if (geteuid() == 0 && getuid() != geteuid()) + { + int status; + + status = fcntl(fileno(stderr), F_GETFL, 0); + if (status != -1) { + fcntl(fileno(stderr), F_SETFL, status | O_NONBLOCK); + } + } + } +#endif +#endif + + beenHere = TRUE; +} + +/* + * ddxGiveUp -- + * Device dependent cleanup. Called by by dix before normal server death. + * For SYSV386 we must switch the terminal back to normal mode. No error- + * checking here, since there should be restored as much as possible. + */ + +void +ddxGiveUp(void) +{ + int i; + + xf86VGAarbiterFini(); + +#ifdef XF86PM + if (xf86OSPMClose) + xf86OSPMClose(); + xf86OSPMClose = NULL; +#endif + + for (i = 0; i < xf86NumScreens; i++) { + /* + * zero all access functions to + * trap calls when switched away. + */ + xf86Screens[i]->vtSema = FALSE; + } + +#ifdef XFreeXDGA + DGAShutdown(); +#endif + + if (xorgHWOpenConsole) + xf86CloseConsole(); + + xf86CloseLog(); + + /* If an unexpected signal was caught, dump a core for debugging */ + if (xf86Info.caughtSignal) + OsAbort(); +} + + + +/* + * AbortDDX -- + * DDX - specific abort routine. Called by AbortServer(). The attempt is + * made to restore all original setting of the displays. Also all devices + * are closed. + */ + +void +AbortDDX(void) +{ + int i; + + xf86BlockSIGIO(); + + /* + * try to restore the original video state + */ +#ifdef DPMSExtension /* Turn screens back on */ + if (DPMSPowerLevel != DPMSModeOn) + DPMSSet(serverClient, DPMSModeOn); +#endif + if (xf86Screens) { + for (i = 0; i < xf86NumScreens; i++) + if (xf86Screens[i]->vtSema) { + /* + * if we are aborting before ScreenInit() has finished + * we might not have been wrapped yet. Therefore enable + * screen explicitely. + */ + xf86VGAarbiterLock(xf86Screens[i]); + (xf86Screens[i]->LeaveVT)(i, 0); + xf86VGAarbiterUnlock(xf86Screens[i]); + } + } + + xf86AccessLeave(); + + /* + * This is needed for an abnormal server exit, since the normal exit stuff + * MUST also be performed (i.e. the vt must be left in a defined state) + */ + ddxGiveUp(); +} + +void +OsVendorFatalError(void) +{ +#ifdef VENDORSUPPORT + ErrorF("\nPlease refer to your Operating System Vendor support pages\n" + "at %s for support on this crash.\n",VENDORSUPPORT); +#else + ErrorF("\nPlease consult the "XVENDORNAME" support \n" + "\t at "__VENDORDWEBSUPPORT__"\n for help. \n"); +#endif + if (xf86LogFile && xf86LogFileWasOpened) + ErrorF("Please also check the log file at \"%s\" for additional " + "information.\n", xf86LogFile); + ErrorF("\n"); +} + +int +xf86SetVerbosity(int verb) +{ + int save = xf86Verbose; + + xf86Verbose = verb; + LogSetParameter(XLOG_VERBOSITY, verb); + return save; +} + +int +xf86SetLogVerbosity(int verb) +{ + int save = xf86LogVerbose; + + xf86LogVerbose = verb; + LogSetParameter(XLOG_FILE_VERBOSITY, verb); + return save; +} + +static void +xf86PrintDefaultModulePath(void) +{ + ErrorF("%s\n", DEFAULT_MODULE_PATH); +} + +static void +xf86PrintDefaultLibraryPath(void) +{ + ErrorF("%s\n", DEFAULT_LIBRARY_PATH); +} + +/* + * ddxProcessArgument -- + * Process device-dependent command line args. Returns 0 if argument is + * not device dependent, otherwise Count of number of elements of argv + * that are part of a device dependent commandline option. + * + */ + +/* ARGSUSED */ +int +ddxProcessArgument(int argc, char **argv, int i) +{ +#define CHECK_FOR_REQUIRED_ARGUMENT() \ + if (((i + 1) >= argc) || (!argv[i + 1])) { \ + ErrorF("Required argument to %s not specified\n", argv[i]); \ + UseMsg(); \ + FatalError("Required argument to %s not specified\n", argv[i]); \ + } + + /* First the options that are only allowed for root */ + if (!strcmp(argv[i], "-modulepath") || !strcmp(argv[i], "-logfile")) { + if ( (geteuid() == 0) && (getuid() != 0) ) { + FatalError("The '%s' option can only be used by root.\n", argv[i]); + } + else if (!strcmp(argv[i], "-modulepath")) + { + char *mp; + CHECK_FOR_REQUIRED_ARGUMENT(); + mp = strdup(argv[i + 1]); + if (!mp) + FatalError("Can't allocate memory for ModulePath\n"); + xf86ModulePath = mp; + xf86ModPathFrom = X_CMDLINE; + return 2; + } + else if (!strcmp(argv[i], "-logfile")) + { + char *lf; + CHECK_FOR_REQUIRED_ARGUMENT(); + lf = strdup(argv[i + 1]); + if (!lf) + FatalError("Can't allocate memory for LogFile\n"); + xf86LogFile = lf; + xf86LogFileFrom = X_CMDLINE; + return 2; + } + } + if (!strcmp(argv[i], "-config") || !strcmp(argv[i], "-xf86config")) + { + CHECK_FOR_REQUIRED_ARGUMENT(); + if (getuid() != 0 && !xf86PathIsSafe(argv[i + 1])) { + FatalError("\nInvalid argument for %s\n" + "\tFor non-root users, the file specified with %s must be\n" + "\ta relative path and must not contain any \"..\" elements.\n" + "\tUsing default "__XCONFIGFILE__" search path.\n\n", + argv[i], argv[i]); + } + xf86ConfigFile = argv[i + 1]; + return 2; + } + if (!strcmp(argv[i], "-configdir")) + { + CHECK_FOR_REQUIRED_ARGUMENT(); + if (getuid() != 0 && !xf86PathIsSafe(argv[i + 1])) { + FatalError("\nInvalid argument for %s\n" + "\tFor non-root users, the file specified with %s must be\n" + "\ta relative path and must not contain any \"..\" elements.\n" + "\tUsing default "__XCONFIGDIR__" search path.\n\n", + argv[i], argv[i]); + } + xf86ConfigDir = argv[i + 1]; + return 2; + } + if (!strcmp(argv[i],"-flipPixels")) + { + xf86FlipPixels = TRUE; + return 1; + } +#ifdef XF86VIDMODE + if (!strcmp(argv[i],"-disableVidMode")) + { + xf86VidModeDisabled = TRUE; + return 1; + } + if (!strcmp(argv[i],"-allowNonLocalXvidtune")) + { + xf86VidModeAllowNonLocal = TRUE; + return 1; + } +#endif + if (!strcmp(argv[i],"-allowMouseOpenFail")) + { + xf86AllowMouseOpenFail = TRUE; + return 1; + } + if (!strcmp(argv[i],"-ignoreABI")) + { + LoaderSetOptions(LDR_OPT_ABI_MISMATCH_NONFATAL); + return 1; + } + if (!strcmp(argv[i],"-verbose")) + { + if (++i < argc && argv[i]) + { + char *end; + long val; + val = strtol(argv[i], &end, 0); + if (*end == '\0') + { + xf86SetVerbosity(val); + return 2; + } + } + xf86SetVerbosity(++xf86Verbose); + return 1; + } + if (!strcmp(argv[i],"-logverbose")) + { + if (++i < argc && argv[i]) + { + char *end; + long val; + val = strtol(argv[i], &end, 0); + if (*end == '\0') + { + xf86SetLogVerbosity(val); + return 2; + } + } + xf86SetLogVerbosity(++xf86LogVerbose); + return 1; + } + if (!strcmp(argv[i],"-quiet")) + { + xf86SetVerbosity(-1); + return 1; + } + if (!strcmp(argv[i],"-showconfig") || !strcmp(argv[i],"-version")) + { + xf86PrintBanner(); + exit(0); + } + if (!strcmp(argv[i],"-showDefaultModulePath")) + { + xf86PrintDefaultModulePath(); + exit(0); + } + if (!strcmp(argv[i],"-showDefaultLibPath")) + { + xf86PrintDefaultLibraryPath(); + exit(0); + } + /* Notice the -fp flag, but allow it to pass to the dix layer */ + if (!strcmp(argv[i], "-fp")) + { + xf86fpFlag = TRUE; + return 0; + } + /* Notice the -bs flag, but allow it to pass to the dix layer */ + if (!strcmp(argv[i], "-bs")) + { + xf86bsDisableFlag = TRUE; + return 0; + } + /* Notice the +bs flag, but allow it to pass to the dix layer */ + if (!strcmp(argv[i], "+bs")) + { + xf86bsEnableFlag = TRUE; + return 0; + } + /* Notice the -s flag, but allow it to pass to the dix layer */ + if (!strcmp(argv[i], "-s")) + { + xf86sFlag = TRUE; + return 0; + } + if (!strcmp(argv[i], "-pixmap24")) + { + xf86Pix24 = Pix24Use24; + return 1; + } + if (!strcmp(argv[i], "-pixmap32")) + { + xf86Pix24 = Pix24Use32; + return 1; + } + if (!strcmp(argv[i], "-fbbpp")) + { + int bpp; + CHECK_FOR_REQUIRED_ARGUMENT(); + if (sscanf(argv[++i], "%d", &bpp) == 1) + { + xf86FbBpp = bpp; + return 2; + } + else + { + ErrorF("Invalid fbbpp\n"); + return 0; + } + } + if (!strcmp(argv[i], "-depth")) + { + int depth; + CHECK_FOR_REQUIRED_ARGUMENT(); + if (sscanf(argv[++i], "%d", &depth) == 1) + { + xf86Depth = depth; + return 2; + } + else + { + ErrorF("Invalid depth\n"); + return 0; + } + } + if (!strcmp(argv[i], "-weight")) + { + int red, green, blue; + CHECK_FOR_REQUIRED_ARGUMENT(); + if (sscanf(argv[++i], "%1d%1d%1d", &red, &green, &blue) == 3) + { + xf86Weight.red = red; + xf86Weight.green = green; + xf86Weight.blue = blue; + return 2; + } + else + { + ErrorF("Invalid weighting\n"); + return 0; + } + } + if (!strcmp(argv[i], "-gamma") || !strcmp(argv[i], "-rgamma") || + !strcmp(argv[i], "-ggamma") || !strcmp(argv[i], "-bgamma")) + { + double gamma; + CHECK_FOR_REQUIRED_ARGUMENT(); + if (sscanf(argv[++i], "%lf", &gamma) == 1) { + if (gamma < GAMMA_MIN || gamma > GAMMA_MAX) { + ErrorF("gamma out of range, only %.2f <= gamma_value <= %.1f" + " is valid\n", GAMMA_MIN, GAMMA_MAX); + return 0; + } + if (!strcmp(argv[i-1], "-gamma")) + xf86Gamma.red = xf86Gamma.green = xf86Gamma.blue = gamma; + else if (!strcmp(argv[i-1], "-rgamma")) xf86Gamma.red = gamma; + else if (!strcmp(argv[i-1], "-ggamma")) xf86Gamma.green = gamma; + else if (!strcmp(argv[i-1], "-bgamma")) xf86Gamma.blue = gamma; + return 2; + } + } + if (!strcmp(argv[i], "-layout")) + { + CHECK_FOR_REQUIRED_ARGUMENT(); + xf86LayoutName = argv[++i]; + return 2; + } + if (!strcmp(argv[i], "-screen")) + { + CHECK_FOR_REQUIRED_ARGUMENT(); + xf86ScreenName = argv[++i]; + return 2; + } + if (!strcmp(argv[i], "-pointer")) + { + CHECK_FOR_REQUIRED_ARGUMENT(); + xf86PointerName = argv[++i]; + return 2; + } + if (!strcmp(argv[i], "-keyboard")) + { + CHECK_FOR_REQUIRED_ARGUMENT(); + xf86KeyboardName = argv[++i]; + return 2; + } + if (!strcmp(argv[i], "-nosilk")) + { + xf86silkenMouseDisableFlag = TRUE; + return 1; + } +#ifdef HAVE_ACPI + if (!strcmp(argv[i], "-noacpi")) + { + xf86acpiDisableFlag = TRUE; + return 1; + } +#endif + if (!strcmp(argv[i], "-configure")) + { + if (getuid() != 0 && geteuid() == 0) { + ErrorF("The '-configure' option can only be used by root.\n"); + exit(1); + } + xf86DoConfigure = TRUE; + xf86AllowMouseOpenFail = TRUE; + return 1; + } + if (!strcmp(argv[i], "-showopts")) + { + if (getuid() != 0 && geteuid() == 0) { + ErrorF("The '-showopts' option can only be used by root.\n"); + exit(1); + } + xf86DoShowOptions = TRUE; + return 1; + } + if (!strcmp(argv[i], "-isolateDevice")) + { + CHECK_FOR_REQUIRED_ARGUMENT(); + if (strncmp(argv[++i], "PCI:", 4)) { + FatalError("Bus types other than PCI not yet isolable\n"); + } + xf86PciIsolateDevice(argv[i]); + return 2; + } + /* Notice cmdline xkbdir, but pass to dix as well */ + if (!strcmp(argv[i], "-xkbdir")) + { + xf86xkbdirFlag = TRUE; + return 0; + } + + /* OS-specific processing */ + return xf86ProcessArgument(argc, argv, i); +} + +/* + * ddxUseMsg -- + * Print out correct use of device dependent commandline options. + * Maybe the user now knows what really to do ... + */ + +void +ddxUseMsg(void) +{ + ErrorF("\n"); + ErrorF("\n"); + ErrorF("Device Dependent Usage\n"); + if (getuid() == 0 || geteuid() != 0) + { + ErrorF("-modulepath paths specify the module search path\n"); + ErrorF("-logfile file specify a log file name\n"); + ErrorF("-configure probe for devices and write an "__XCONFIGFILE__"\n"); + ErrorF("-showopts print available options for all installed drivers\n"); + } + ErrorF("-config file specify a configuration file, relative to the\n"); + ErrorF(" "__XCONFIGFILE__" search path, only root can use absolute\n"); + ErrorF("-configdir dir specify a configuration directory, relative to the\n"); + ErrorF(" "__XCONFIGDIR__" search path, only root can use absolute\n"); + ErrorF("-verbose [n] verbose startup messages\n"); + ErrorF("-logverbose [n] verbose log messages\n"); + ErrorF("-quiet minimal startup messages\n"); + ErrorF("-pixmap24 use 24bpp pixmaps for depth 24\n"); + ErrorF("-pixmap32 use 32bpp pixmaps for depth 24\n"); + ErrorF("-fbbpp n set bpp for the framebuffer. Default: 8\n"); + ErrorF("-depth n set colour depth. Default: 8\n"); + ErrorF("-gamma f set gamma value (0.1 < f < 10.0) Default: 1.0\n"); + ErrorF("-rgamma f set gamma value for red phase\n"); + ErrorF("-ggamma f set gamma value for green phase\n"); + ErrorF("-bgamma f set gamma value for blue phase\n"); + ErrorF("-weight nnn set RGB weighting at 16 bpp. Default: 565\n"); + ErrorF("-layout name specify the ServerLayout section name\n"); + ErrorF("-screen name specify the Screen section name\n"); + ErrorF("-keyboard name specify the core keyboard InputDevice name\n"); + ErrorF("-pointer name specify the core pointer InputDevice name\n"); + ErrorF("-nosilk disable Silken Mouse\n"); + ErrorF("-flipPixels swap default black/white Pixel values\n"); +#ifdef XF86VIDMODE + ErrorF("-disableVidMode disable mode adjustments with xvidtune\n"); + ErrorF("-allowNonLocalXvidtune allow xvidtune to be run as a non-local client\n"); +#endif + ErrorF("-allowMouseOpenFail start server even if the mouse can't be initialized\n"); + ErrorF("-ignoreABI make module ABI mismatches non-fatal\n"); + ErrorF("-isolateDevice bus_id restrict device resets to bus_id (PCI only)\n"); + ErrorF("-version show the server version\n"); + ErrorF("-showDefaultModulePath show the server default module path\n"); + ErrorF("-showDefaultLibPath show the server default library path\n"); + /* OS-specific usage */ + xf86UseMsg(); + ErrorF("\n"); +} + + +/* + * xf86LoadModules iterates over a list that is being passed in. + */ +Bool +xf86LoadModules(char **list, pointer *optlist) +{ + int errmaj, errmin; + pointer opt; + int i; + char *name; + Bool failed = FALSE; + + if (!list) + return TRUE; + + for (i = 0; list[i] != NULL; i++) { + + /* Normalise the module name */ + name = xf86NormalizeName(list[i]); + + /* Skip empty names */ + if (name == NULL || *name == '\0') { + free(name); + continue; + } + + /* Replace obsolete keyboard driver with kbd */ + if (!xf86NameCmp(name, "keyboard")) { + strcpy(name, "kbd"); + } + + if (optlist) + opt = optlist[i]; + else + opt = NULL; + + if (!LoadModule(name, NULL, NULL, NULL, opt, NULL, &errmaj, &errmin)) { + LoaderErrorMsg(NULL, name, errmaj, errmin); + failed = TRUE; + } + free(name); + } + return !failed; +} + +/* Pixmap format stuff */ + +PixmapFormatPtr +xf86GetPixFormat(ScrnInfoPtr pScrn, int depth) +{ + int i; + static PixmapFormatRec format; /* XXX not reentrant */ + + /* + * When the formats[] list initialisation isn't complete, check the + * depth 24 pixmap config/cmdline options and screen-specified formats. + */ + + if (!formatsDone) { + if (depth == 24) { + Pix24Flags pix24 = Pix24DontCare; + + format.depth = 24; + format.scanlinePad = BITMAP_SCANLINE_PAD; + if (xf86Info.pixmap24 != Pix24DontCare) + pix24 = xf86Info.pixmap24; + else if (pScrn->pixmap24 != Pix24DontCare) + pix24 = pScrn->pixmap24; + if (pix24 == Pix24Use24) + format.bitsPerPixel = 24; + else + format.bitsPerPixel = 32; + return &format; + } + } + + for (i = 0; i < numFormats; i++) + if (formats[i].depth == depth) + break; + if (i != numFormats) + return &formats[i]; + else if (!formatsDone) { + /* Check for screen-specified formats */ + for (i = 0; i < pScrn->numFormats; i++) + if (pScrn->formats[i].depth == depth) + break; + if (i != pScrn->numFormats) + return &pScrn->formats[i]; + } + return NULL; +} + +int +xf86GetBppFromDepth(ScrnInfoPtr pScrn, int depth) +{ + PixmapFormatPtr format; + + + format = xf86GetPixFormat(pScrn, depth); + if (format) + return format->bitsPerPixel; + else + return 0; +} diff --git a/hw/xfree86/common/xf86Mode.c b/hw/xfree86/common/xf86Mode.c new file mode 100644 index 0000000..644e5ce --- /dev/null +++ b/hw/xfree86/common/xf86Mode.c @@ -0,0 +1,2130 @@ +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * LCM() and scanLineWidth() are: + * + * Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of Marc Aurele La France not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Marc Aurele La France makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO + * EVENT SHALL MARC AURELE LA FRANCE 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. + * + * Copyright 1990,91,92,93 by Thomas Roell, Germany. + * Copyright 1991,92,93 by SGCS (Snitily Graphics Consulting Services), USA. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation, and that the name of Thomas Roell nor + * SGCS be used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Thomas Roell nor SGCS makes no representations about the suitability + * of this software for any purpose. It is provided "as is" without + * express or implied warranty. + * + * THOMAS ROELL AND SGCS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THOMAS ROELL OR SGCS 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. + */ + +/* + * Authors: Dirk Hohndel <hohndel@XFree86.Org> + * David Dawes <dawes@XFree86.Org> + * Marc La France <tsi@XFree86.Org> + * ... and others + * + * This file includes helper functions for mode related things. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <X11/X.h> +#include "xf86Modes.h" +#include "os.h" +#include "servermd.h" +#include "globals.h" +#include "xf86.h" +#include "xf86Priv.h" +#include "edid.h" + +static void +printModeRejectMessage(int index, DisplayModePtr p, int status) +{ + char *type; + + if (p->type & M_T_BUILTIN) + type = "built-in "; + else if (p->type & M_T_DEFAULT) + type = "default "; + else if (p->type & M_T_DRIVER) + type = "driver "; + else + type = ""; + + xf86DrvMsg(index, X_INFO, "Not using %smode \"%s\" (%s)\n", type, p->name, + xf86ModeStatusToString(status)); +} + +/* + * xf86GetNearestClock -- + * Find closest clock to given frequency (in kHz). This assumes the + * number of clocks is greater than zero. + */ +int +xf86GetNearestClock(ScrnInfoPtr scrp, int freq, Bool allowDiv2, + int DivFactor, int MulFactor, int *divider) +{ + int nearestClock = 0, nearestDiv = 1; + int minimumGap = abs(freq - scrp->clock[0]); + int i, j, k, gap; + + if (allowDiv2) + k = 2; + else + k = 1; + + /* Must set this here in case the best match is scrp->clock[0] */ + if (divider != NULL) + *divider = 0; + + for (i = 0; i < scrp->numClocks; i++) { + for (j = 1; j <= k; j++) { + gap = abs((freq * j) - ((scrp->clock[i] * DivFactor) / MulFactor)); + if ((gap < minimumGap) || + ((gap == minimumGap) && (j < nearestDiv))) { + minimumGap = gap; + nearestClock = i; + nearestDiv = j; + if (divider != NULL) + *divider = (j - 1) * V_CLKDIV2; + } + } + } + return nearestClock; +} + +/* + * xf86ModeStatusToString + * + * Convert a ModeStatus value to a printable message + */ + +const char * +xf86ModeStatusToString(ModeStatus status) +{ + switch (status) { + case MODE_OK: + return "Mode OK"; + case MODE_HSYNC: + return "hsync out of range"; + case MODE_VSYNC: + return "vrefresh out of range"; + case MODE_H_ILLEGAL: + return "illegal horizontal timings"; + case MODE_V_ILLEGAL: + return "illegal vertical timings"; + case MODE_BAD_WIDTH: + return "width requires unsupported line pitch"; + case MODE_NOMODE: + return "no mode of this name"; + case MODE_NO_INTERLACE: + return "interlace mode not supported"; + case MODE_NO_DBLESCAN: + return "doublescan mode not supported"; + case MODE_NO_VSCAN: + return "multiscan mode not supported"; + case MODE_MEM: + return "insufficient memory for mode"; + case MODE_VIRTUAL_X: + return "width too large for virtual size"; + case MODE_VIRTUAL_Y: + return "height too large for virtual size"; + case MODE_MEM_VIRT: + return "insufficient memory given virtual size"; + case MODE_NOCLOCK: + return "no clock available for mode"; + case MODE_CLOCK_HIGH: + return "mode clock too high"; + case MODE_CLOCK_LOW: + return "mode clock too low"; + case MODE_CLOCK_RANGE: + return "bad mode clock/interlace/doublescan"; + case MODE_BAD_HVALUE: + return "horizontal timing out of range"; + case MODE_BAD_VVALUE: + return "vertical timing out of range"; + case MODE_BAD_VSCAN: + return "VScan value out of range"; + case MODE_HSYNC_NARROW: + return "horizontal sync too narrow"; + case MODE_HSYNC_WIDE: + return "horizontal sync too wide"; + case MODE_HBLANK_NARROW: + return "horizontal blanking too narrow"; + case MODE_HBLANK_WIDE: + return "horizontal blanking too wide"; + case MODE_VSYNC_NARROW: + return "vertical sync too narrow"; + case MODE_VSYNC_WIDE: + return "vertical sync too wide"; + case MODE_VBLANK_NARROW: + return "vertical blanking too narrow"; + case MODE_VBLANK_WIDE: + return "vertical blanking too wide"; + case MODE_PANEL: + return "exceeds panel dimensions"; + case MODE_INTERLACE_WIDTH: + return "width too large for interlaced mode"; + case MODE_ONE_WIDTH: + return "all modes must have the same width"; + case MODE_ONE_HEIGHT: + return "all modes must have the same height"; + case MODE_ONE_SIZE: + return "all modes must have the same resolution"; + case MODE_NO_REDUCED: + return "monitor doesn't support reduced blanking"; + case MODE_BANDWIDTH: + return "mode requires too much memory bandwidth"; + case MODE_BAD: + return "unknown reason"; + case MODE_ERROR: + return "internal error"; + default: + return "unknown"; + } +} + +/* + * xf86ShowClockRanges() -- Print the clock ranges allowed + * and the clock values scaled by ClockMulFactor and ClockDivFactor + */ +void +xf86ShowClockRanges(ScrnInfoPtr scrp, ClockRangePtr clockRanges) +{ + ClockRangePtr cp; + int MulFactor = 1; + int DivFactor = 1; + int i, j; + int scaledClock; + + for (cp = clockRanges; cp != NULL; cp = cp->next) { + DivFactor = max(1, cp->ClockDivFactor); + MulFactor = max(1, cp->ClockMulFactor); + if (scrp->progClock) { + if (cp->minClock) { + if (cp->maxClock) { + xf86DrvMsg(scrp->scrnIndex, X_INFO, + "Clock range: %6.2f to %6.2f MHz\n", + (double)cp->minClock / 1000.0, + (double)cp->maxClock / 1000.0); + } else { + xf86DrvMsg(scrp->scrnIndex, X_INFO, + "Minimum clock: %6.2f MHz\n", + (double)cp->minClock / 1000.0); + } + } else { + if (cp->maxClock) { + xf86DrvMsg(scrp->scrnIndex, X_INFO, + "Maximum clock: %6.2f MHz\n", + (double)cp->maxClock / 1000.0); + } + } + } else if (DivFactor > 1 || MulFactor > 1) { + j = 0; + for (i = 0; i < scrp->numClocks; i++) { + scaledClock = (scrp->clock[i] * DivFactor) / MulFactor; + if (scaledClock >= cp->minClock && scaledClock <= cp->maxClock) { + if ((j % 8) == 0) { + if (j > 0) + xf86ErrorF("\n"); + xf86DrvMsg(scrp->scrnIndex, X_INFO, "scaled clocks:"); + } + xf86ErrorF(" %6.2f", (double)scaledClock / 1000.0); + j++; + } + } + xf86ErrorF("\n"); + } + } +} + +static Bool +modeInClockRange(ClockRangePtr cp, DisplayModePtr p) +{ + return ((p->Clock >= cp->minClock) && + (p->Clock <= cp->maxClock) && + (cp->interlaceAllowed || !(p->Flags & V_INTERLACE)) && + (cp->doubleScanAllowed || + ((p->VScan <= 1) && !(p->Flags & V_DBLSCAN)))); +} + +/* + * xf86FindClockRangeForMode() [... like the name says ...] + */ +static ClockRangePtr +xf86FindClockRangeForMode(ClockRangePtr clockRanges, DisplayModePtr p) +{ + ClockRangePtr cp; + + for (cp = clockRanges; ; cp = cp->next) + if (!cp || modeInClockRange(cp, p)) + return cp; +} + + +/* + * xf86HandleBuiltinMode() - handles built-in modes + */ +static ModeStatus +xf86HandleBuiltinMode(ScrnInfoPtr scrp, + DisplayModePtr p, + DisplayModePtr modep, + ClockRangePtr clockRanges, + Bool allowDiv2) +{ + ClockRangePtr cp; + int extraFlags = 0; + int MulFactor = 1; + int DivFactor = 1; + int clockIndex; + + /* Reject previously rejected modes */ + if (p->status != MODE_OK) + return p->status; + + /* Reject previously considered modes */ + if (p->prev) + return MODE_NOMODE; + + if ((p->type & M_T_CLOCK_C) == M_T_CLOCK_C) { + /* Check clock is in range */ + cp = xf86FindClockRangeForMode(clockRanges, p); + if (cp == NULL){ + modep->type = p->type; + p->status = MODE_CLOCK_RANGE; + return MODE_CLOCK_RANGE; + } + DivFactor = cp->ClockDivFactor; + MulFactor = cp->ClockMulFactor; + if (!scrp->progClock) { + clockIndex = xf86GetNearestClock(scrp, p->Clock, allowDiv2, + cp->ClockDivFactor, + cp->ClockMulFactor, &extraFlags); + modep->Clock = (scrp->clock[clockIndex] * DivFactor) + / MulFactor; + modep->ClockIndex = clockIndex; + modep->SynthClock = scrp->clock[clockIndex]; + if (extraFlags & V_CLKDIV2) { + modep->Clock /= 2; + modep->SynthClock /= 2; + } + } else { + modep->Clock = p->Clock; + modep->ClockIndex = -1; + modep->SynthClock = (modep->Clock * MulFactor) + / DivFactor; + } + modep->PrivFlags = cp->PrivFlags; + } else { + if(!scrp->progClock) { + modep->Clock = p->Clock; + modep->ClockIndex = p->ClockIndex; + modep->SynthClock = p->SynthClock; + } else { + modep->Clock = p->Clock; + modep->ClockIndex = -1; + modep->SynthClock = p->SynthClock; + } + modep->PrivFlags = p->PrivFlags; + } + modep->type = p->type; + modep->HDisplay = p->HDisplay; + modep->HSyncStart = p->HSyncStart; + modep->HSyncEnd = p->HSyncEnd; + modep->HTotal = p->HTotal; + modep->HSkew = p->HSkew; + modep->VDisplay = p->VDisplay; + modep->VSyncStart = p->VSyncStart; + modep->VSyncEnd = p->VSyncEnd; + modep->VTotal = p->VTotal; + modep->VScan = p->VScan; + modep->Flags = p->Flags | extraFlags; + modep->CrtcHDisplay = p->CrtcHDisplay; + modep->CrtcHBlankStart = p->CrtcHBlankStart; + modep->CrtcHSyncStart = p->CrtcHSyncStart; + modep->CrtcHSyncEnd = p->CrtcHSyncEnd; + modep->CrtcHBlankEnd = p->CrtcHBlankEnd; + modep->CrtcHTotal = p->CrtcHTotal; + modep->CrtcHSkew = p->CrtcHSkew; + modep->CrtcVDisplay = p->CrtcVDisplay; + modep->CrtcVBlankStart = p->CrtcVBlankStart; + modep->CrtcVSyncStart = p->CrtcVSyncStart; + modep->CrtcVSyncEnd = p->CrtcVSyncEnd; + modep->CrtcVBlankEnd = p->CrtcVBlankEnd; + modep->CrtcVTotal = p->CrtcVTotal; + modep->CrtcHAdjusted = p->CrtcHAdjusted; + modep->CrtcVAdjusted = p->CrtcVAdjusted; + modep->HSync = p->HSync; + modep->VRefresh = p->VRefresh; + modep->Private = p->Private; + modep->PrivSize = p->PrivSize; + + p->prev = modep; + + return MODE_OK; +} + +/* + * xf86LookupMode + * + * This function returns a mode from the given list which matches the + * given name. When multiple modes with the same name are available, + * the method of picking the matching mode is determined by the + * strategy selected. + * + * This function takes the following parameters: + * scrp ScrnInfoPtr + * modep pointer to the returned mode, which must have the name + * field filled in. + * clockRanges a list of clock ranges. This is optional when all the + * modes are built-in modes. + * strategy how to decide which mode to use from multiple modes with + * the same name + * + * In addition, the following fields from the ScrnInfoRec are used: + * modePool the list of monitor modes compatible with the driver + * clocks a list of discrete clocks + * numClocks number of discrete clocks + * progClock clock is programmable + * + * If a mode was found, its values are filled in to the area pointed to + * by modep, If a mode was not found the return value indicates the + * reason. + */ + +ModeStatus +xf86LookupMode(ScrnInfoPtr scrp, DisplayModePtr modep, + ClockRangePtr clockRanges, LookupModeFlags strategy) +{ + DisplayModePtr p, bestMode = NULL; + ClockRangePtr cp; + int i, k, gap, minimumGap = CLOCK_TOLERANCE + 1; + double refresh, bestRefresh = 0.0; + Bool found = FALSE; + int extraFlags = 0; + int clockIndex = -1; + int MulFactor = 1; + int DivFactor = 1; + int ModePrivFlags = 0; + ModeStatus status = MODE_NOMODE; + Bool allowDiv2 = (strategy & LOOKUP_CLKDIV2) != 0; + int n; + const int types[] = { + M_T_BUILTIN | M_T_PREFERRED, + M_T_BUILTIN, + M_T_USERDEF | M_T_PREFERRED, + M_T_USERDEF, + M_T_DRIVER | M_T_PREFERRED, + M_T_DRIVER, + 0 + }; + const int ntypes = sizeof(types) / sizeof(int); + + strategy &= ~(LOOKUP_CLKDIV2 | LOOKUP_OPTIONAL_TOLERANCES); + + /* Some sanity checking */ + if (scrp == NULL || scrp->modePool == NULL || + (!scrp->progClock && scrp->numClocks == 0)) { + ErrorF("xf86LookupMode: called with invalid scrnInfoRec\n"); + return MODE_ERROR; + } + if (modep == NULL || modep->name == NULL) { + ErrorF("xf86LookupMode: called with invalid modep\n"); + return MODE_ERROR; + } + for (cp = clockRanges; cp != NULL; cp = cp->next) { + /* DivFactor and MulFactor must be > 0 */ + cp->ClockDivFactor = max(1, cp->ClockDivFactor); + cp->ClockMulFactor = max(1, cp->ClockMulFactor); + } + + /* Scan the mode pool for matching names */ + for (n = 0; n < ntypes; n++) { + int type = types[n]; + for (p = scrp->modePool; p != NULL; p = p->next) { + + /* scan through the modes in the sort order above */ + if ((p->type & type) != type) + continue; + + if (strcmp(p->name, modep->name) == 0) { + + /* Skip over previously rejected modes */ + if (p->status != MODE_OK) { + if (!found) + status = p->status; + continue; + } + + /* Skip over previously considered modes */ + if (p->prev) + continue; + + if (p->type & M_T_BUILTIN) { + return xf86HandleBuiltinMode(scrp, p,modep, clockRanges, + allowDiv2); + } + + /* Check clock is in range */ + cp = xf86FindClockRangeForMode(clockRanges, p); + if (cp == NULL) { + /* + * XXX Could do more here to provide a more detailed + * reason for not finding a mode. + */ + p->status = MODE_CLOCK_RANGE; + if (!found) + status = MODE_CLOCK_RANGE; + continue; + } + + /* + * If programmable clock and strategy is not + * LOOKUP_BEST_REFRESH, the required mode has been found, + * otherwise record the refresh and continue looking. + */ + if (scrp->progClock) { + found = TRUE; + if (strategy != LOOKUP_BEST_REFRESH) { + bestMode = p; + DivFactor = cp->ClockDivFactor; + MulFactor = cp->ClockMulFactor; + ModePrivFlags = cp->PrivFlags; + break; + } + refresh = xf86ModeVRefresh(p); + if (p->Flags & V_INTERLACE) + refresh /= INTERLACE_REFRESH_WEIGHT; + if (refresh > bestRefresh) { + bestMode = p; + DivFactor = cp->ClockDivFactor; + MulFactor = cp->ClockMulFactor; + ModePrivFlags = cp->PrivFlags; + bestRefresh = refresh; + } + continue; + } + + /* + * Clock is in range, so if it is not a programmable clock, find + * a matching clock. + */ + + i = xf86GetNearestClock(scrp, p->Clock, allowDiv2, + cp->ClockDivFactor, cp->ClockMulFactor, &k); + /* + * If the clock is too far from the requested clock, this + * mode is no good. + */ + if (k & V_CLKDIV2) + gap = abs((p->Clock * 2) - + ((scrp->clock[i] * cp->ClockDivFactor) / + cp->ClockMulFactor)); + else + gap = abs(p->Clock - + ((scrp->clock[i] * cp->ClockDivFactor) / + cp->ClockMulFactor)); + if (gap > minimumGap) { + p->status = MODE_NOCLOCK; + if (!found) + status = MODE_NOCLOCK; + continue; + } + found = TRUE; + + if (strategy == LOOKUP_BEST_REFRESH) { + refresh = xf86ModeVRefresh(p); + if (p->Flags & V_INTERLACE) + refresh /= INTERLACE_REFRESH_WEIGHT; + if (refresh > bestRefresh) { + bestMode = p; + DivFactor = cp->ClockDivFactor; + MulFactor = cp->ClockMulFactor; + ModePrivFlags = cp->PrivFlags; + extraFlags = k; + clockIndex = i; + bestRefresh = refresh; + } + continue; + } + if (strategy == LOOKUP_CLOSEST_CLOCK) { + if (gap < minimumGap) { + bestMode = p; + DivFactor = cp->ClockDivFactor; + MulFactor = cp->ClockMulFactor; + ModePrivFlags = cp->PrivFlags; + extraFlags = k; + clockIndex = i; + minimumGap = gap; + } + continue; + } + /* + * If strategy is neither LOOKUP_BEST_REFRESH or + * LOOKUP_CLOSEST_CLOCK the required mode has been found. + */ + bestMode = p; + DivFactor = cp->ClockDivFactor; + MulFactor = cp->ClockMulFactor; + ModePrivFlags = cp->PrivFlags; + extraFlags = k; + clockIndex = i; + break; + } + } + if (found) break; + } + if (!found || bestMode == NULL) + return status; + + /* Fill in the mode parameters */ + if (scrp->progClock) { + modep->Clock = bestMode->Clock; + modep->ClockIndex = -1; + modep->SynthClock = (modep->Clock * MulFactor) / DivFactor; + } else { + modep->Clock = (scrp->clock[clockIndex] * DivFactor) / + MulFactor; + modep->ClockIndex = clockIndex; + modep->SynthClock = scrp->clock[clockIndex]; + if (extraFlags & V_CLKDIV2) { + modep->Clock /= 2; + modep->SynthClock /= 2; + } + } + modep->type = bestMode->type; + modep->PrivFlags = ModePrivFlags; + modep->HDisplay = bestMode->HDisplay; + modep->HSyncStart = bestMode->HSyncStart; + modep->HSyncEnd = bestMode->HSyncEnd; + modep->HTotal = bestMode->HTotal; + modep->HSkew = bestMode->HSkew; + modep->VDisplay = bestMode->VDisplay; + modep->VSyncStart = bestMode->VSyncStart; + modep->VSyncEnd = bestMode->VSyncEnd; + modep->VTotal = bestMode->VTotal; + modep->VScan = bestMode->VScan; + modep->Flags = bestMode->Flags | extraFlags; + modep->CrtcHDisplay = bestMode->CrtcHDisplay; + modep->CrtcHBlankStart = bestMode->CrtcHBlankStart; + modep->CrtcHSyncStart = bestMode->CrtcHSyncStart; + modep->CrtcHSyncEnd = bestMode->CrtcHSyncEnd; + modep->CrtcHBlankEnd = bestMode->CrtcHBlankEnd; + modep->CrtcHTotal = bestMode->CrtcHTotal; + modep->CrtcHSkew = bestMode->CrtcHSkew; + modep->CrtcVDisplay = bestMode->CrtcVDisplay; + modep->CrtcVBlankStart = bestMode->CrtcVBlankStart; + modep->CrtcVSyncStart = bestMode->CrtcVSyncStart; + modep->CrtcVSyncEnd = bestMode->CrtcVSyncEnd; + modep->CrtcVBlankEnd = bestMode->CrtcVBlankEnd; + modep->CrtcVTotal = bestMode->CrtcVTotal; + modep->CrtcHAdjusted = bestMode->CrtcHAdjusted; + modep->CrtcVAdjusted = bestMode->CrtcVAdjusted; + modep->HSync = bestMode->HSync; + modep->VRefresh = bestMode->VRefresh; + modep->Private = bestMode->Private; + modep->PrivSize = bestMode->PrivSize; + + bestMode->prev = modep; + + return MODE_OK; +} + +/* + * xf86CheckModeForMonitor + * + * This function takes a mode and monitor description, and determines + * if the mode is valid for the monitor. + */ +ModeStatus +xf86CheckModeForMonitor(DisplayModePtr mode, MonPtr monitor) +{ + int i; + + /* Sanity checks */ + if (mode == NULL || monitor == NULL) { + ErrorF("xf86CheckModeForMonitor: called with invalid parameters\n"); + return MODE_ERROR; + } + + DebugF("xf86CheckModeForMonitor(%p %s, %p %s)\n", + mode, mode->name, monitor, monitor->id); + + /* Some basic mode validity checks */ + if (0 >= mode->HDisplay || mode->HDisplay > mode->HSyncStart || + mode->HSyncStart >= mode->HSyncEnd || mode->HSyncEnd >= mode->HTotal) + return MODE_H_ILLEGAL; + + if (0 >= mode->VDisplay || mode->VDisplay > mode->VSyncStart || + mode->VSyncStart >= mode->VSyncEnd || mode->VSyncEnd >= mode->VTotal) + return MODE_V_ILLEGAL; + + if (monitor->nHsync > 0) { + /* Check hsync against the allowed ranges */ + float hsync = xf86ModeHSync(mode); + for (i = 0; i < monitor->nHsync; i++) + if ((hsync > monitor->hsync[i].lo * (1.0 - SYNC_TOLERANCE)) && + (hsync < monitor->hsync[i].hi * (1.0 + SYNC_TOLERANCE))) + break; + + /* Now see whether we ran out of sync ranges without finding a match */ + if (i == monitor->nHsync) + return MODE_HSYNC; + } + + if (monitor->nVrefresh > 0) { + /* Check vrefresh against the allowed ranges */ + float vrefrsh = xf86ModeVRefresh(mode); + for (i = 0; i < monitor->nVrefresh; i++) + if ((vrefrsh > monitor->vrefresh[i].lo * (1.0 - SYNC_TOLERANCE)) && + (vrefrsh < monitor->vrefresh[i].hi * (1.0 + SYNC_TOLERANCE))) + break; + + /* Now see whether we ran out of refresh ranges without finding a match */ + if (i == monitor->nVrefresh) + return MODE_VSYNC; + } + + /* Force interlaced modes to have an odd VTotal */ + if (mode->Flags & V_INTERLACE) + mode->CrtcVTotal = mode->VTotal |= 1; + + /* + * This code stops cvt -r modes, and only cvt -r modes, from hitting 15y+ + * old CRTs which might, when there is a lot of solar flare activity and + * when the celestial bodies are unfavourably aligned, implode trying to + * sync to it. It's called "Protecting the user from doing anything stupid". + * -- libv + */ + + if (xf86ModeIsReduced(mode)) { + if (!monitor->reducedblanking && !(mode->type & M_T_DRIVER)) + return MODE_NO_REDUCED; + } + + if ((monitor->maxPixClock) && (mode->Clock > monitor->maxPixClock)) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +/* + * xf86CheckModeSize + * + * An internal routine to check if a mode fits in video memory. This tries to + * avoid overflows that would otherwise occur when video memory size is greater + * than 256MB. + */ +static Bool +xf86CheckModeSize(ScrnInfoPtr scrp, int w, int x, int y) +{ + int bpp = scrp->fbFormat.bitsPerPixel, + pad = scrp->fbFormat.scanlinePad; + int lineWidth, lastWidth; + + if (scrp->depth == 4) + pad *= 4; /* 4 planes */ + + /* Sanity check */ + if ((w < 0) || (x < 0) || (y <= 0)) + return FALSE; + + lineWidth = (((w * bpp) + pad - 1) / pad) * pad; + lastWidth = x * bpp; + + /* + * At this point, we need to compare + * + * (lineWidth * (y - 1)) + lastWidth + * + * against + * + * scrp->videoRam * (1024 * 8) + * + * These are bit quantities. To avoid overflows, do the comparison in + * terms of BITMAP_SCANLINE_PAD units. This assumes BITMAP_SCANLINE_PAD + * is a power of 2. We currently use 32, which limits us to a video + * memory size of 8GB. + */ + + lineWidth = (lineWidth + (BITMAP_SCANLINE_PAD - 1)) / BITMAP_SCANLINE_PAD; + lastWidth = (lastWidth + (BITMAP_SCANLINE_PAD - 1)) / BITMAP_SCANLINE_PAD; + + if ((lineWidth * (y - 1) + lastWidth) > + (scrp->videoRam * ((1024 * 8) / BITMAP_SCANLINE_PAD))) + return FALSE; + + return TRUE; +} + +/* + * xf86InitialCheckModeForDriver + * + * This function checks if a mode satisfies a driver's initial requirements: + * - mode size fits within the available pixel area (memory) + * - width lies within the range of supported line pitches + * - mode size fits within virtual size (if fixed) + * - horizontal timings are in range + * + * This function takes the following parameters: + * scrp ScrnInfoPtr + * mode mode to check + * maxPitch (optional) maximum line pitch + * virtualX (optional) virtual width requested + * virtualY (optional) virtual height requested + * + * In addition, the following fields from the ScrnInfoRec are used: + * monitor pointer to structure for monitor section + * fbFormat pixel format for the framebuffer + * videoRam video memory size (in kB) + * maxHValue maximum horizontal timing value + * maxVValue maximum vertical timing value + */ + +ModeStatus +xf86InitialCheckModeForDriver(ScrnInfoPtr scrp, DisplayModePtr mode, + ClockRangePtr clockRanges, + LookupModeFlags strategy, + int maxPitch, int virtualX, int virtualY) +{ + ClockRangePtr cp; + ModeStatus status; + Bool allowDiv2 = (strategy & LOOKUP_CLKDIV2) != 0; + int i, needDiv2; + + /* Sanity checks */ + if (!scrp || !mode || !clockRanges) { + ErrorF("xf86InitialCheckModeForDriver: " + "called with invalid parameters\n"); + return MODE_ERROR; + } + + DebugF("xf86InitialCheckModeForDriver(%p, %p %s, %p, 0x%x, %d, %d, %d)\n", + scrp, mode, mode->name , clockRanges, strategy, maxPitch, virtualX, virtualY); + + /* Some basic mode validity checks */ + if (0 >= mode->HDisplay || mode->HDisplay > mode->HSyncStart || + mode->HSyncStart >= mode->HSyncEnd || mode->HSyncEnd >= mode->HTotal) + return MODE_H_ILLEGAL; + + if (0 >= mode->VDisplay || mode->VDisplay > mode->VSyncStart || + mode->VSyncStart >= mode->VSyncEnd || mode->VSyncEnd >= mode->VTotal) + return MODE_V_ILLEGAL; + + if (!xf86CheckModeSize(scrp, mode->HDisplay, mode->HDisplay, + mode->VDisplay)) + return MODE_MEM; + + if (maxPitch > 0 && mode->HDisplay > maxPitch) + return MODE_BAD_WIDTH; + + if (virtualX > 0 && mode->HDisplay > virtualX) + return MODE_VIRTUAL_X; + + if (virtualY > 0 && mode->VDisplay > virtualY) + return MODE_VIRTUAL_Y; + + if (scrp->maxHValue > 0 && mode->HTotal > scrp->maxHValue) + return MODE_BAD_HVALUE; + + if (scrp->maxVValue > 0 && mode->VTotal > scrp->maxVValue) + return MODE_BAD_VVALUE; + + /* + * The use of the DisplayModeRec's Crtc* and SynthClock elements below is + * provisional, in that they are later reused by the driver at mode-set + * time. Here, they are temporarily enlisted to contain the mode timings + * as seen by the CRT or panel (rather than the CRTC). The driver's + * ValidMode() is allowed to modify these so it can deal with such things + * as mode stretching and/or centering. The driver should >NOT< modify the + * user-supplied values as these are reported back when mode validation is + * said and done. + */ + /* + * NOTE: We (ab)use the mode->Crtc* values here to store timing + * information for the calculation of Hsync and Vrefresh. Before + * these values are calculated the driver is given the opportunity + * to either set these HSync and VRefresh itself or modify the timing + * values. + * The difference to the final calculation is small but imortand: + * here we pass the flag INTERLACE_HALVE_V regardless if the driver + * sets it or not. This way our calculation of VRefresh has the same + * effect as if we do if (flags & V_INTERLACE) refresh *= 2.0 + * This dual use of the mode->Crtc* values will certainly create + * confusion and is bad software design. However since it's part of + * the driver API it's hard to change. + */ + + if (scrp->ValidMode) { + + xf86SetModeCrtc(mode, INTERLACE_HALVE_V); + + cp = xf86FindClockRangeForMode(clockRanges, mode); + if (!cp) + return MODE_CLOCK_RANGE; + + if (cp->ClockMulFactor < 1) + cp->ClockMulFactor = 1; + if (cp->ClockDivFactor < 1) + cp->ClockDivFactor = 1; + + /* + * XXX The effect of clock dividers and multipliers on the monitor's + * pixel clock needs to be verified. + */ + if (scrp->progClock) { + mode->SynthClock = mode->Clock; + } else { + i = xf86GetNearestClock(scrp, mode->Clock, allowDiv2, + cp->ClockDivFactor, cp->ClockMulFactor, + &needDiv2); + mode->SynthClock = (scrp->clock[i] * cp->ClockDivFactor) / + cp->ClockMulFactor; + if (needDiv2 & V_CLKDIV2) + mode->SynthClock /= 2; + } + + status = (*scrp->ValidMode)(scrp->scrnIndex, mode, FALSE, + MODECHECK_INITIAL); + if (status != MODE_OK) + return status; + + if (mode->HSync <= 0.0) + mode->HSync = (float)mode->SynthClock / (float)mode->CrtcHTotal; + if (mode->VRefresh <= 0.0) + mode->VRefresh = (mode->SynthClock * 1000.0) + / (mode->CrtcHTotal * mode->CrtcVTotal); + } + + mode->HSync = xf86ModeHSync(mode); + mode->VRefresh = xf86ModeVRefresh(mode); + + /* Assume it is OK */ + return MODE_OK; +} + +/* + * xf86CheckModeForDriver + * + * This function is for checking modes while the server is running (for + * use mainly by the VidMode extension). + * + * This function checks if a mode satisfies a driver's requirements: + * - width lies within the line pitch + * - mode size fits within virtual size + * - horizontal/vertical timings are in range + * + * This function takes the following parameters: + * scrp ScrnInfoPtr + * mode mode to check + * flags not (currently) used + * + * In addition, the following fields from the ScrnInfoRec are used: + * maxHValue maximum horizontal timing value + * maxVValue maximum vertical timing value + * virtualX virtual width + * virtualY virtual height + * clockRanges allowable clock ranges + */ + +ModeStatus +xf86CheckModeForDriver(ScrnInfoPtr scrp, DisplayModePtr mode, int flags) +{ + ClockRangePtr cp; + int i, k, gap, minimumGap = CLOCK_TOLERANCE + 1; + int extraFlags = 0; + int clockIndex = -1; + int MulFactor = 1; + int DivFactor = 1; + int ModePrivFlags = 0; + ModeStatus status = MODE_NOMODE; + + /* Some sanity checking */ + if (scrp == NULL || (!scrp->progClock && scrp->numClocks == 0)) { + ErrorF("xf86CheckModeForDriver: called with invalid scrnInfoRec\n"); + return MODE_ERROR; + } + if (mode == NULL) { + ErrorF("xf86CheckModeForDriver: called with invalid modep\n"); + return MODE_ERROR; + } + + /* Check the mode size */ + if (mode->HDisplay > scrp->virtualX) + return MODE_VIRTUAL_X; + + if (mode->VDisplay > scrp->virtualY) + return MODE_VIRTUAL_Y; + + if (scrp->maxHValue > 0 && mode->HTotal > scrp->maxHValue) + return MODE_BAD_HVALUE; + + if (scrp->maxVValue > 0 && mode->VTotal > scrp->maxVValue) + return MODE_BAD_VVALUE; + + for (cp = scrp->clockRanges; cp != NULL; cp = cp->next) { + /* DivFactor and MulFactor must be > 0 */ + cp->ClockDivFactor = max(1, cp->ClockDivFactor); + cp->ClockMulFactor = max(1, cp->ClockMulFactor); + } + + if (scrp->progClock) { + /* Check clock is in range */ + for (cp = scrp->clockRanges; cp != NULL; cp = cp->next) { + if (modeInClockRange(cp, mode)) + break; + } + if (cp == NULL) { + return MODE_CLOCK_RANGE; + } + /* + * If programmable clock the required mode has been found + */ + DivFactor = cp->ClockDivFactor; + MulFactor = cp->ClockMulFactor; + ModePrivFlags = cp->PrivFlags; + } else { + status = MODE_CLOCK_RANGE; + /* Check clock is in range */ + for (cp = scrp->clockRanges; cp != NULL; cp = cp->next) { + if (modeInClockRange(cp, mode)) { + /* + * Clock is in range, so if it is not a programmable clock, + * find a matching clock. + */ + + i = xf86GetNearestClock(scrp, mode->Clock, 0, + cp->ClockDivFactor, cp->ClockMulFactor, &k); + /* + * If the clock is too far from the requested clock, this + * mode is no good. + */ + if (k & V_CLKDIV2) + gap = abs((mode->Clock * 2) - + ((scrp->clock[i] * cp->ClockDivFactor) / + cp->ClockMulFactor)); + else + gap = abs(mode->Clock - + ((scrp->clock[i] * cp->ClockDivFactor) / + cp->ClockMulFactor)); + if (gap > minimumGap) { + status = MODE_NOCLOCK; + continue; + } + + DivFactor = cp->ClockDivFactor; + MulFactor = cp->ClockMulFactor; + ModePrivFlags = cp->PrivFlags; + extraFlags = k; + clockIndex = i; + break; + } + } + if (cp == NULL) + return status; + } + + /* Fill in the mode parameters */ + if (scrp->progClock) { + mode->ClockIndex = -1; + mode->SynthClock = (mode->Clock * MulFactor) / DivFactor; + } else { + mode->Clock = (scrp->clock[clockIndex] * DivFactor) / MulFactor; + mode->ClockIndex = clockIndex; + mode->SynthClock = scrp->clock[clockIndex]; + if (extraFlags & V_CLKDIV2) { + mode->Clock /= 2; + mode->SynthClock /= 2; + } + } + mode->PrivFlags = ModePrivFlags; + + return MODE_OK; +} + +static int +inferVirtualSize(ScrnInfoPtr scrp, DisplayModePtr modes, int *vx, int *vy) +{ + float aspect = 0.0; + MonPtr mon = scrp->monitor; + xf86MonPtr DDC; + int x = 0, y = 0; + DisplayModePtr mode; + + if (!mon) return 0; + DDC = mon->DDC; + + if (DDC && DDC->ver.revision >= 4) { + /* For 1.4, we might actually get native pixel format. How novel. */ + if (PREFERRED_TIMING_MODE(DDC->features.msc)) { + for (mode = modes; mode; mode = mode->next) { + if (mode->type & (M_T_DRIVER | M_T_PREFERRED)) { + x = mode->HDisplay; + y = mode->VDisplay; + goto found; + } + } + } + /* + * Even if we don't, we might get aspect ratio from extra CVT info + * or from the monitor size fields. TODO. + */ + } + + /* + * Technically this triggers if either is zero. That wasn't legal + * before EDID 1.4, but right now we'll get that wrong. TODO. + */ + if (!aspect) { + if (!mon->widthmm || !mon->heightmm) + aspect = 4.0/3.0; + else + aspect = (float)mon->widthmm / (float)mon->heightmm; + } + + /* find the largest M_T_DRIVER mode with that aspect ratio */ + for (mode = modes; mode; mode = mode->next) { + float mode_aspect, metaspect; + if (!(mode->type & (M_T_DRIVER|M_T_USERDEF))) + continue; + mode_aspect = (float)mode->HDisplay / (float)mode->VDisplay; + metaspect = aspect / mode_aspect; + /* 5% slop or so, since we only get size in centimeters */ + if (fabs(1.0 - metaspect) < 0.05) { + if ((mode->HDisplay > x) && (mode->VDisplay > y)) { + x = mode->HDisplay; + y = mode->VDisplay; + } + } + } + + if (!x || !y) { + xf86DrvMsg(scrp->scrnIndex, X_WARNING, + "Unable to estimate virtual size\n"); + return 0; + } + +found: + *vx = x; + *vy = y; + + xf86DrvMsg(scrp->scrnIndex, X_INFO, + "Estimated virtual size for aspect ratio %.4f is %dx%d\n", + aspect, *vx, *vy); + + return 1; +} + +/* Least common multiple */ +static unsigned int +LCM(unsigned int x, unsigned int y) +{ + unsigned int m = x, n = y, o; + + while ((o = m % n)) + { + m = n; + n = o; + } + + return (x / n) * y; +} + +/* + * Given various screen attributes, determine the minimum scanline width such + * that each scanline is server and DDX padded and any pixels with imbedded + * bank boundaries are off-screen. This function returns -1 if such a width + * cannot exist. + */ +static int +scanLineWidth( + unsigned int xsize, /* pixels */ + unsigned int ysize, /* pixels */ + unsigned int width, /* pixels */ + unsigned long BankSize, /* char's */ + PixmapFormatRec *pBankFormat, + unsigned int nWidthUnit /* bits */ +) +{ + unsigned long nBitsPerBank, nBitsPerScanline, nBitsPerScanlinePadUnit; + unsigned long minBitsPerScanline, maxBitsPerScanline; + + /* Sanity checks */ + + if (!nWidthUnit || !pBankFormat) + return -1; + + nBitsPerBank = BankSize * 8; + if (nBitsPerBank % pBankFormat->scanlinePad) + return -1; + + if (xsize > width) + width = xsize; + nBitsPerScanlinePadUnit = LCM(pBankFormat->scanlinePad, nWidthUnit); + nBitsPerScanline = + (((width * pBankFormat->bitsPerPixel) + nBitsPerScanlinePadUnit - 1) / + nBitsPerScanlinePadUnit) * nBitsPerScanlinePadUnit; + width = nBitsPerScanline / pBankFormat->bitsPerPixel; + + if (!xsize || !(nBitsPerBank % pBankFormat->bitsPerPixel)) + return (int)width; + + /* + * Scanlines will be server-pad aligned at this point. They will also be + * a multiple of nWidthUnit bits long. Ensure that pixels with imbedded + * bank boundaries are off-screen. + * + * It seems reasonable to limit total frame buffer size to 1/16 of the + * theoretical maximum address space size. On a machine with 32-bit + * addresses (to 8-bit quantities) this turns out to be 256MB. Not only + * does this provide a simple limiting condition for the loops below, but + * it also prevents unsigned long wraparounds. + */ + if (!ysize) + return -1; + + minBitsPerScanline = xsize * pBankFormat->bitsPerPixel; + if (minBitsPerScanline > nBitsPerBank) + return -1; + + if (ysize == 1) + return (int)width; + + maxBitsPerScanline = + (((unsigned long)(-1) >> 1) - minBitsPerScanline) / (ysize - 1); + while (nBitsPerScanline <= maxBitsPerScanline) + { + unsigned long BankBase, BankUnit; + + BankUnit = ((nBitsPerBank + nBitsPerScanline - 1) / nBitsPerBank) * + nBitsPerBank; + if (!(BankUnit % nBitsPerScanline)) + return (int)width; + + for (BankBase = BankUnit; ; BankBase += nBitsPerBank) + { + unsigned long x, y; + + y = BankBase / nBitsPerScanline; + if (y >= ysize) + return (int)width; + + x = BankBase % nBitsPerScanline; + if (!(x % pBankFormat->bitsPerPixel)) + continue; + + if (x < minBitsPerScanline) + { + /* + * Skip ahead certain widths by dividing the excess scanline + * amongst the y's. + */ + y *= nBitsPerScanlinePadUnit; + nBitsPerScanline += + ((x + y - 1) / y) * nBitsPerScanlinePadUnit; + width = nBitsPerScanline / pBankFormat->bitsPerPixel; + break; + } + + if (BankBase != BankUnit) + continue; + + if (!(nBitsPerScanline % x)) + return (int)width; + + BankBase = ((nBitsPerScanline - minBitsPerScanline) / + (nBitsPerScanline - x)) * BankUnit; + } + } + + return -1; +} + +/* + * xf86ValidateModes + * + * This function takes a set of mode names, modes and limiting conditions, + * and selects a set of modes and parameters based on those conditions. + * + * This function takes the following parameters: + * scrp ScrnInfoPtr + * availModes the list of modes available for the monitor + * modeNames (optional) list of mode names that the screen is requesting + * clockRanges a list of clock ranges + * linePitches (optional) a list of line pitches + * minPitch (optional) minimum line pitch (in pixels) + * maxPitch (optional) maximum line pitch (in pixels) + * pitchInc (mandatory) pitch increment (in bits) + * minHeight (optional) minimum virtual height (in pixels) + * maxHeight (optional) maximum virtual height (in pixels) + * virtualX (optional) virtual width requested (in pixels) + * virtualY (optional) virtual height requested (in pixels) + * apertureSize size of video aperture (in bytes) + * strategy how to decide which mode to use from multiple modes with + * the same name + * + * In addition, the following fields from the ScrnInfoRec are used: + * clocks a list of discrete clocks + * numClocks number of discrete clocks + * progClock clock is programmable + * monitor pointer to structure for monitor section + * fbFormat format of the framebuffer + * videoRam video memory size + * maxHValue maximum horizontal timing value + * maxVValue maximum vertical timing value + * xInc horizontal timing increment (defaults to 8 pixels) + * + * The function fills in the following ScrnInfoRec fields: + * modePool A subset of the modes available to the monitor which + * are compatible with the driver. + * modes one mode entry for each of the requested modes, with the + * status field filled in to indicate if the mode has been + * accepted or not. + * virtualX the resulting virtual width + * virtualY the resulting virtual height + * displayWidth the resulting line pitch + * + * The function's return value is the number of matching modes found, or -1 + * if an unrecoverable error was encountered. + */ + +int +xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes, + char **modeNames, ClockRangePtr clockRanges, + int *linePitches, int minPitch, int maxPitch, int pitchInc, + int minHeight, int maxHeight, int virtualX, int virtualY, + int apertureSize, LookupModeFlags strategy) +{ + DisplayModePtr p, q, r, new, last, *endp; + int i, numModes = 0; + ModeStatus status; + int linePitch = -1, virtX = 0, virtY = 0; + int newLinePitch, newVirtX, newVirtY; + int modeSize; /* in pixels */ + Bool validateAllDefaultModes = FALSE; + Bool userModes = FALSE; + int saveType; + PixmapFormatRec *BankFormat; + ClockRangePtr cp; + ClockRangePtr storeClockRanges; + int numTimings = 0; + range hsync[MAX_HSYNC]; + range vrefresh[MAX_VREFRESH]; + Bool inferred_virtual = FALSE; + + DebugF("xf86ValidateModes(%p, %p, %p, %p,\n\t\t %p, %d, %d, %d, %d, %d, %d, %d, %d, 0x%x)\n", + scrp, availModes, modeNames, clockRanges, + linePitches, minPitch, maxPitch, pitchInc, + minHeight, maxHeight, virtualX, virtualY, + apertureSize, strategy + ); + + /* Some sanity checking */ + if (scrp == NULL || scrp->name == NULL || !scrp->monitor || + (!scrp->progClock && scrp->numClocks == 0)) { + ErrorF("xf86ValidateModes: called with invalid scrnInfoRec\n"); + return -1; + } + if (linePitches != NULL && linePitches[0] <= 0) { + ErrorF("xf86ValidateModes: called with invalid linePitches\n"); + return -1; + } + if (pitchInc <= 0) { + ErrorF("xf86ValidateModes: called with invalid pitchInc\n"); + return -1; + } + if ((virtualX > 0) != (virtualY > 0)) { + ErrorF("xf86ValidateModes: called with invalid virtual resolution\n"); + return -1; + } + + /* + * If requested by the driver, allow missing hsync and/or vrefresh ranges + * in the monitor section. + */ + if (strategy & LOOKUP_OPTIONAL_TOLERANCES) { + strategy &= ~LOOKUP_OPTIONAL_TOLERANCES; + } else { + const char *type = ""; + Bool specified = FALSE; + + if (scrp->monitor->nHsync <= 0) { + if (numTimings > 0) { + scrp->monitor->nHsync = numTimings; + for (i = 0; i < numTimings; i++) { + scrp->monitor->hsync[i].lo = hsync[i].lo; + scrp->monitor->hsync[i].hi = hsync[i].hi; + } + } else { + scrp->monitor->hsync[0].lo = 31.5; + scrp->monitor->hsync[0].hi = 48.0; + scrp->monitor->nHsync = 1; + } + type = "default "; + } else { + specified = TRUE; + } + for (i = 0; i < scrp->monitor->nHsync; i++) { + if (scrp->monitor->hsync[i].lo == scrp->monitor->hsync[i].hi) + xf86DrvMsg(scrp->scrnIndex, X_INFO, + "%s: Using %shsync value of %.2f kHz\n", + scrp->monitor->id, type, + scrp->monitor->hsync[i].lo); + else + xf86DrvMsg(scrp->scrnIndex, X_INFO, + "%s: Using %shsync range of %.2f-%.2f kHz\n", + scrp->monitor->id, type, + scrp->monitor->hsync[i].lo, + scrp->monitor->hsync[i].hi); + } + + type = ""; + if (scrp->monitor->nVrefresh <= 0) { + if (numTimings > 0) { + scrp->monitor->nVrefresh = numTimings; + for (i = 0; i < numTimings; i++) { + scrp->monitor->vrefresh[i].lo = vrefresh[i].lo; + scrp->monitor->vrefresh[i].hi = vrefresh[i].hi; + } + } else { + scrp->monitor->vrefresh[0].lo = 50; + scrp->monitor->vrefresh[0].hi = 70; + scrp->monitor->nVrefresh = 1; + } + type = "default "; + } else { + specified = TRUE; + } + for (i = 0; i < scrp->monitor->nVrefresh; i++) { + if (scrp->monitor->vrefresh[i].lo == scrp->monitor->vrefresh[i].hi) + xf86DrvMsg(scrp->scrnIndex, X_INFO, + "%s: Using %svrefresh value of %.2f Hz\n", + scrp->monitor->id, type, + scrp->monitor->vrefresh[i].lo); + else + xf86DrvMsg(scrp->scrnIndex, X_INFO, + "%s: Using %svrefresh range of %.2f-%.2f Hz\n", + scrp->monitor->id, type, + scrp->monitor->vrefresh[i].lo, + scrp->monitor->vrefresh[i].hi); + } + + type = ""; + if (!scrp->monitor->maxPixClock && !specified) { + type = "default "; + scrp->monitor->maxPixClock = 65000.0; + } + if (scrp->monitor->maxPixClock) { + xf86DrvMsg(scrp->scrnIndex, X_INFO, + "%s: Using %smaximum pixel clock of %.2f MHz\n", + scrp->monitor->id, type, + (float)scrp->monitor->maxPixClock / 1000.0); + } + } + + /* + * Store the clockRanges for later use by the VidMode extension. + */ + storeClockRanges = scrp->clockRanges; + while (storeClockRanges != NULL) { + storeClockRanges = storeClockRanges->next; + } + for (cp = clockRanges; cp != NULL; cp = cp->next, + storeClockRanges = storeClockRanges->next) { + storeClockRanges = xnfalloc(sizeof(ClockRange)); + if (scrp->clockRanges == NULL) + scrp->clockRanges = storeClockRanges; + memcpy(storeClockRanges, cp, sizeof(ClockRange)); + } + + /* Determine which pixmap format to pass to scanLineWidth() */ + if (scrp->depth > 4) + BankFormat = &scrp->fbFormat; + else + BankFormat = xf86GetPixFormat(scrp, 1); /* >not< scrp->depth! */ + + if (scrp->xInc <= 0) + scrp->xInc = 8; /* Suitable for VGA and others */ + +#define _VIRTUALX(x) ((((x) + scrp->xInc - 1) / scrp->xInc) * scrp->xInc) + + /* + * Determine maxPitch if it wasn't given explicitly. Note linePitches + * always takes precedence if is non-NULL. In that case the minPitch and + * maxPitch values passed are ignored. + */ + if (linePitches) { + minPitch = maxPitch = linePitches[0]; + for (i = 1; linePitches[i] > 0; i++) { + if (linePitches[i] > maxPitch) + maxPitch = linePitches[i]; + if (linePitches[i] < minPitch) + minPitch = linePitches[i]; + } + } + + /* Initial check of virtual size against other constraints */ + scrp->virtualFrom = X_PROBED; + /* + * Initialise virtX and virtY if the values are fixed. + */ + if (virtualY > 0) { + if (maxHeight > 0 && virtualY > maxHeight) { + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Virtual height (%d) is too large for the hardware " + "(max %d)\n", virtualY, maxHeight); + return -1; + } + + if (minHeight > 0 && virtualY < minHeight) { + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Virtual height (%d) is too small for the hardware " + "(min %d)\n", virtualY, minHeight); + return -1; + } + + virtualX = _VIRTUALX(virtualX); + if (linePitches != NULL) { + for (i = 0; linePitches[i] != 0; i++) { + if ((linePitches[i] >= virtualX) && + (linePitches[i] == + scanLineWidth(virtualX, virtualY, linePitches[i], + apertureSize, BankFormat, pitchInc))) { + linePitch = linePitches[i]; + break; + } + } + } else { + linePitch = scanLineWidth(virtualX, virtualY, minPitch, + apertureSize, BankFormat, pitchInc); + } + + if ((linePitch < minPitch) || (linePitch > maxPitch)) { + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Virtual width (%d) is too large for the hardware " + "(max %d)\n", virtualX, maxPitch); + return -1; + } + + if (!xf86CheckModeSize(scrp, linePitch, virtualX, virtualY)) { + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Virtual size (%dx%d) (pitch %d) exceeds video memory\n", + virtualX, virtualY, linePitch); + return -1; + } + + virtX = virtualX; + virtY = virtualY; + scrp->virtualFrom = X_CONFIG; + } else if (!modeNames || !*modeNames) { + /* No virtual size given in the config, try to infer */ + /* XXX this doesn't take m{in,ax}Pitch into account; oh well */ + inferred_virtual = inferVirtualSize(scrp, availModes, &virtX, &virtY); + if (inferred_virtual) + linePitch = scanLineWidth(virtX, virtY, minPitch, apertureSize, + BankFormat, pitchInc); + } + + /* Print clock ranges and scaled clocks */ + xf86ShowClockRanges(scrp, clockRanges); + + /* + * If scrp->modePool hasn't been setup yet, set it up now. This allows the + * modes that the driver definitely can't use to be weeded out early. Note + * that a modePool mode's prev field is used to hold a pointer to the + * member of the scrp->modes list for which a match was considered. + */ + if (scrp->modePool == NULL) { + q = NULL; + for (p = availModes; p != NULL; p = p->next) { + status = xf86InitialCheckModeForDriver(scrp, p, clockRanges, + strategy, maxPitch, + virtX, virtY); + + if (status == MODE_OK) { + status = xf86CheckModeForMonitor(p, scrp->monitor); + } + + if (status == MODE_OK) { + new = xnfalloc(sizeof(DisplayModeRec)); + *new = *p; + new->next = NULL; + if (!q) { + scrp->modePool = new; + } else { + q->next = new; + } + new->prev = NULL; + q = new; + q->name = xnfstrdup(p->name); + q->status = MODE_OK; + } else { + printModeRejectMessage(scrp->scrnIndex, p, status); + } + } + + if (scrp->modePool == NULL) { + xf86DrvMsg(scrp->scrnIndex, X_WARNING, "Mode pool is empty\n"); + return 0; + } + } else { + for (p = scrp->modePool; p != NULL; p = p->next) { + p->prev = NULL; + p->status = MODE_OK; + } + } + + /* + * Allocate one entry in scrp->modes for each named mode. + */ + while (scrp->modes) + xf86DeleteMode(&scrp->modes, scrp->modes); + endp = &scrp->modes; + last = NULL; + if (modeNames != NULL) { + for (i = 0; modeNames[i] != NULL; i++) { + userModes = TRUE; + new = xnfcalloc(1, sizeof(DisplayModeRec)); + new->prev = last; + new->type = M_T_USERDEF; + new->name = xnfstrdup(modeNames[i]); + if (new->prev) + new->prev->next = new; + *endp = last = new; + endp = &new->next; + } + } + + /* Lookup each mode */ +#ifdef RANDR + if (!xf86Info.disableRandR +#ifdef PANORAMIX + && noPanoramiXExtension +#endif + ) + validateAllDefaultModes = TRUE; +#endif + + for (p = scrp->modes; ; p = p->next) { + Bool repeat; + + /* + * If the supplied mode names don't produce a valid mode, scan through + * unconsidered modePool members until one survives validation. This + * is done in decreasing order by mode pixel area. + */ + + if (p == NULL) { + if ((numModes > 0) && !validateAllDefaultModes) + break; + + validateAllDefaultModes = TRUE; + r = NULL; + modeSize = 0; + for (q = scrp->modePool; q != NULL; q = q->next) { + if ((q->prev == NULL) && (q->status == MODE_OK)) { + /* + * Deal with the case where this mode wasn't considered + * because of a builtin mode of the same name. + */ + for (p = scrp->modes; p != NULL; p = p->next) { + if ((p->status != MODE_OK) && + !strcmp(p->name, q->name)) + break; + } + + if (p != NULL) + q->prev = p; + else { + /* + * A quick check to not allow default modes with + * horizontal timing parameters that CRTs may have + * problems with. + */ + if (!scrp->monitor->reducedblanking && + (q->type & M_T_DEFAULT) && + ((double)q->HTotal / (double)q->HDisplay) < 1.15) + continue; + + if (modeSize < (q->HDisplay * q->VDisplay)) { + r = q; + modeSize = q->HDisplay * q->VDisplay; + } + } + } + } + + if (r == NULL) + break; + + p = xnfcalloc(1, sizeof(DisplayModeRec)); + p->prev = last; + p->name = xnfstrdup(r->name); + if (!userModes) + p->type = M_T_USERDEF; + if (p->prev) + p->prev->next = p; + *endp = last = p; + endp = &p->next; + } + + repeat = FALSE; + lookupNext: + if (repeat && ((status = p->status) != MODE_OK)) + printModeRejectMessage(scrp->scrnIndex, p, status); + saveType = p->type; + status = xf86LookupMode(scrp, p, clockRanges, strategy); + if (repeat && status == MODE_NOMODE) + continue; + if (status != MODE_OK) + printModeRejectMessage(scrp->scrnIndex, p, status); + if (status == MODE_ERROR) { + ErrorF("xf86ValidateModes: " + "unexpected result from xf86LookupMode()\n"); + return -1; + } + if (status != MODE_OK) { + if (p->status == MODE_OK) + p->status = status; + continue; + } + p->type |= saveType; + repeat = TRUE; + + newLinePitch = linePitch; + newVirtX = virtX; + newVirtY = virtY; + + /* + * Don't let non-user defined modes increase the virtual size + */ + if (!(p->type & M_T_USERDEF) && (numModes > 0)) { + if (p->HDisplay > virtX) { + p->status = MODE_VIRTUAL_X; + goto lookupNext; + } + if (p->VDisplay > virtY) { + p->status = MODE_VIRTUAL_Y; + goto lookupNext; + } + } + /* + * Adjust virtual width and height if the mode is too large for the + * current values and if they are not fixed. + */ + if (virtualX <= 0 && p->HDisplay > newVirtX) + newVirtX = _VIRTUALX(p->HDisplay); + if (virtualY <= 0 && p->VDisplay > newVirtY) { + if (maxHeight > 0 && p->VDisplay > maxHeight) { + p->status = MODE_VIRTUAL_Y; /* ? */ + goto lookupNext; + } + newVirtY = p->VDisplay; + } + + /* + * If virtual resolution is to be increased, revalidate it. + */ + if ((virtX != newVirtX) || (virtY != newVirtY)) { + if (linePitches != NULL) { + newLinePitch = -1; + for (i = 0; linePitches[i] != 0; i++) { + if ((linePitches[i] >= newVirtX) && + (linePitches[i] >= linePitch) && + (linePitches[i] == + scanLineWidth(newVirtX, newVirtY, linePitches[i], + apertureSize, BankFormat, pitchInc))) { + newLinePitch = linePitches[i]; + break; + } + } + } else { + if (linePitch < minPitch) + linePitch = minPitch; + newLinePitch = scanLineWidth(newVirtX, newVirtY, linePitch, + apertureSize, BankFormat, + pitchInc); + } + if ((newLinePitch < minPitch) || (newLinePitch > maxPitch)) { + p->status = MODE_BAD_WIDTH; + goto lookupNext; + } + + /* + * Check that the pixel area required by the new virtual height + * and line pitch isn't too large. + */ + if (!xf86CheckModeSize(scrp, newLinePitch, newVirtX, newVirtY)) { + p->status = MODE_MEM_VIRT; + goto lookupNext; + } + } + + if (scrp->ValidMode) { + /* + * Give the driver a final say, passing it the proposed virtual + * geometry. + */ + scrp->virtualX = newVirtX; + scrp->virtualY = newVirtY; + scrp->displayWidth = newLinePitch; + p->status = (scrp->ValidMode)(scrp->scrnIndex, p, FALSE, + MODECHECK_FINAL); + + if (p->status != MODE_OK) { + goto lookupNext; + } + } + + /* Mode has passed all the tests */ + virtX = newVirtX; + virtY = newVirtY; + linePitch = newLinePitch; + p->status = MODE_OK; + numModes++; + } + + /* + * If we estimated the virtual size above, we may have filtered away all + * the modes that maximally match that size; scan again to find out and + * fix up if so. + */ + if (inferred_virtual) { + int vx = 0, vy = 0; + for (p = scrp->modes; p; p = p->next) { + if (p->HDisplay > vx && p->VDisplay > vy) { + vx = p->HDisplay; + vy = p->VDisplay; + } + } + if (vx < virtX || vy < virtY) { + const int types[] = { + M_T_BUILTIN | M_T_PREFERRED, + M_T_BUILTIN, + M_T_DRIVER | M_T_PREFERRED, + M_T_DRIVER, + 0 + }; + const int ntypes = sizeof(types) / sizeof(int); + int n; + + /* + * We did not find the estimated virtual size. So now we want to + * find the largest mode available, but we want to search in the + * modes in the order of "types" listed above. + */ + for (n = 0; n < ntypes; n++) { + int type = types[n]; + + vx = 0; vy = 0; + for (p = scrp->modes; p; p = p->next) { + /* scan through the modes in the sort order above */ + if ((p->type & type) != type) + continue; + if (p->HDisplay > vx && p->VDisplay > vy) { + vx = p->HDisplay; + vy = p->VDisplay; + } + } + if (vx && vy) + /* Found one */ + break; + } + xf86DrvMsg(scrp->scrnIndex, X_WARNING, + "Shrinking virtual size estimate from %dx%d to %dx%d\n", + virtX, virtY, vx, vy); + virtX = _VIRTUALX(vx); + virtY = vy; + for (p = scrp->modes; p; p = p->next) { + if (numModes > 0) { + if (p->HDisplay > virtX) + p->status = MODE_VIRTUAL_X; + if (p->VDisplay > virtY) + p->status = MODE_VIRTUAL_Y; + if (p->status != MODE_OK) { + numModes--; + printModeRejectMessage(scrp->scrnIndex, p, p->status); + } + } + } + if (linePitches != NULL) { + for (i = 0; linePitches[i] != 0; i++) { + if ((linePitches[i] >= virtX) && + (linePitches[i] == + scanLineWidth(virtX, virtY, linePitches[i], + apertureSize, BankFormat, pitchInc))) { + linePitch = linePitches[i]; + break; + } + } + } else { + linePitch = scanLineWidth(virtX, virtY, minPitch, + apertureSize, BankFormat, pitchInc); + } + } + } + + /* Update the ScrnInfoRec parameters */ + + scrp->virtualX = virtX; + scrp->virtualY = virtY; + scrp->displayWidth = linePitch; + + if (numModes <= 0) + return 0; + + /* Make the mode list into a circular list by joining up the ends */ + p = scrp->modes; + while (p->next != NULL) + p = p->next; + /* p is now the last mode on the list */ + p->next = scrp->modes; + scrp->modes->prev = p; + + if (minHeight > 0 && virtY < minHeight) { + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Virtual height (%d) is too small for the hardware " + "(min %d)\n", virtY, minHeight); + return -1; + } + + return numModes; +} + +/* + * xf86DeleteMode + * + * This function removes a mode from a list of modes. + * + * There are different types of mode lists: + * + * - singly linked linear lists, ending in NULL + * - doubly linked linear lists, starting and ending in NULL + * - doubly linked circular lists + * + */ + +void +xf86DeleteMode(DisplayModePtr *modeList, DisplayModePtr mode) +{ + /* Catch the easy/insane cases */ + if (modeList == NULL || *modeList == NULL || mode == NULL) + return; + + /* If the mode is at the start of the list, move the start of the list */ + if (*modeList == mode) + *modeList = mode->next; + + /* If mode is the only one on the list, set the list to NULL */ + if ((mode == mode->prev) && (mode == mode->next)) { + *modeList = NULL; + } else { + if ((mode->prev != NULL) && (mode->prev->next == mode)) + mode->prev->next = mode->next; + if ((mode->next != NULL) && (mode->next->prev == mode)) + mode->next->prev = mode->prev; + } + + free(mode->name); + free(mode); +} + +/* + * xf86PruneDriverModes + * + * Remove modes from the driver's mode list which have been marked as + * invalid. + */ + +void +xf86PruneDriverModes(ScrnInfoPtr scrp) +{ + DisplayModePtr first, p, n; + + p = scrp->modes; + if (p == NULL) + return; + + do { + if (!(first = scrp->modes)) + return; + n = p->next; + if (p->status != MODE_OK) { + xf86DeleteMode(&(scrp->modes), p); + } + p = n; + } while (p != NULL && p != first); + + /* modePool is no longer needed, turf it */ + while (scrp->modePool) { + /* + * A modePool mode's prev field is used to hold a pointer to the + * member of the scrp->modes list for which a match was considered. + * Clear that pointer first, otherwise xf86DeleteMode might get + * confused + */ + scrp->modePool->prev = NULL; + xf86DeleteMode(&scrp->modePool, scrp->modePool); + } +} + + +/* + * xf86SetCrtcForModes + * + * Goes through the screen's mode list, and initialises the Crtc + * parameters for each mode. The initialisation includes adjustments + * for interlaced and double scan modes. + */ +void +xf86SetCrtcForModes(ScrnInfoPtr scrp, int adjustFlags) +{ + DisplayModePtr p; + + /* + * Store adjustFlags for use with the VidMode extension. There is an + * implicit assumption here that SetCrtcForModes is called once. + */ + scrp->adjustFlags = adjustFlags; + + p = scrp->modes; + if (p == NULL) + return; + + do { + xf86SetModeCrtc(p, adjustFlags); + DebugF("%sMode %s: %d (%d) %d %d (%d) %d %d (%d) %d %d (%d) %d\n", + (p->type & M_T_DEFAULT) ? "Default " : "", + p->name, p->CrtcHDisplay, p->CrtcHBlankStart, + p->CrtcHSyncStart, p->CrtcHSyncEnd, p->CrtcHBlankEnd, + p->CrtcHTotal, p->CrtcVDisplay, p->CrtcVBlankStart, + p->CrtcVSyncStart, p->CrtcVSyncEnd, p->CrtcVBlankEnd, + p->CrtcVTotal); + p = p->next; + } while (p != NULL && p != scrp->modes); +} + +void +xf86PrintModes(ScrnInfoPtr scrp) +{ + DisplayModePtr p; + float hsync, refresh = 0; + char *desc, *desc2, *prefix, *uprefix; + + if (scrp == NULL) + return; + + xf86DrvMsg(scrp->scrnIndex, scrp->virtualFrom, "Virtual size is %dx%d " + "(pitch %d)\n", scrp->virtualX, scrp->virtualY, + scrp->displayWidth); + + p = scrp->modes; + if (p == NULL) + return; + + do { + desc = desc2 = ""; + hsync = xf86ModeHSync(p); + refresh = xf86ModeVRefresh(p); + if (p->Flags & V_INTERLACE) { + desc = " (I)"; + } + if (p->Flags & V_DBLSCAN) { + desc = " (D)"; + } + if (p->VScan > 1) { + desc2 = " (VScan)"; + } + if (p->type & M_T_BUILTIN) + prefix = "Built-in mode"; + else if (p->type & M_T_DEFAULT) + prefix = "Default mode"; + else if (p->type & M_T_DRIVER) + prefix = "Driver mode"; + else + prefix = "Mode"; + if (p->type & M_T_USERDEF) + uprefix = "*"; + else + uprefix = " "; + if (hsync == 0 || refresh == 0) { + if (p->name) + xf86DrvMsg(scrp->scrnIndex, X_CONFIG, + "%s%s \"%s\"\n", uprefix, prefix, p->name); + else + xf86DrvMsg(scrp->scrnIndex, X_PROBED, + "%s%s %dx%d (unnamed)\n", + uprefix, prefix, p->HDisplay, p->VDisplay); + } else if (p->Clock == p->SynthClock) { + xf86DrvMsg(scrp->scrnIndex, X_CONFIG, + "%s%s \"%s\": %.1f MHz, %.1f kHz, %.1f Hz%s%s\n", + uprefix, prefix, p->name, p->Clock / 1000.0, + hsync, refresh, desc, desc2); + } else { + xf86DrvMsg(scrp->scrnIndex, X_CONFIG, + "%s%s \"%s\": %.1f MHz (scaled from %.1f MHz), " + "%.1f kHz, %.1f Hz%s%s\n", + uprefix, prefix, p->name, p->Clock / 1000.0, + p->SynthClock / 1000.0, hsync, refresh, desc, desc2); + } + if (hsync != 0 && refresh != 0) + xf86PrintModeline(scrp->scrnIndex,p); + p = p->next; + } while (p != NULL && p != scrp->modes); +} diff --git a/hw/xfree86/common/xf86Module.h b/hw/xfree86/common/xf86Module.h new file mode 100644 index 0000000..581047d --- /dev/null +++ b/hw/xfree86/common/xf86Module.h @@ -0,0 +1,212 @@ +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * This file contains the parts of the loader interface that are visible + * to modules. This is the only loader-related header that modules should + * include. + * + * It should include a bare minimum of other headers. + * + * Longer term, the module/loader code should probably live directly under + * Xserver/. + * + * XXX This file arguably belongs in xfree86/loader/. + */ + +#ifndef _XF86MODULE_H +#define _XF86MODULE_H + +#include "misc.h" +#ifndef NULL +#define NULL ((void *)0) +#endif + +typedef enum { + LD_RESOLV_IFDONE = 0, /* only check if no more + delays pending */ + LD_RESOLV_NOW = 1, /* finish one delay step */ + LD_RESOLV_FORCE = 2 /* force checking... */ +} LoaderResolveOptions; + +#define DEFAULT_LIST ((char *)-1) + +/* This indicates a special module that doesn't have the usual entry point */ +#define EXTERN_MODULE ((pointer)-1) + +/* Built-in ABI classes. These definitions must not be changed. */ +#define ABI_CLASS_NONE NULL +#define ABI_CLASS_ANSIC "X.Org ANSI C Emulation" +#define ABI_CLASS_VIDEODRV "X.Org Video Driver" +#define ABI_CLASS_XINPUT "X.Org XInput driver" +#define ABI_CLASS_EXTENSION "X.Org Server Extension" +#define ABI_CLASS_FONT "X.Org Font Renderer" + +#define ABI_MINOR_MASK 0x0000FFFF +#define ABI_MAJOR_MASK 0xFFFF0000 +#define GET_ABI_MINOR(v) ((v) & ABI_MINOR_MASK) +#define GET_ABI_MAJOR(v) (((v) & ABI_MAJOR_MASK) >> 16) +#define SET_ABI_VERSION(maj, min) \ + ((((maj) << 16) & ABI_MAJOR_MASK) | ((min) & ABI_MINOR_MASK)) + +/* + * ABI versions. Each version has a major and minor revision. Modules + * using lower minor revisions must work with servers of a higher minor + * revision. There is no compatibility between different major revisions. + * Whenever the ABI_ANSIC_VERSION is changed, the others must also be + * changed. The minor revision mask is 0x0000FFFF and the major revision + * mask is 0xFFFF0000. + */ +#define ABI_ANSIC_VERSION SET_ABI_VERSION(0, 4) +#define ABI_VIDEODRV_VERSION SET_ABI_VERSION(10, 0) +#define ABI_XINPUT_VERSION SET_ABI_VERSION(12, 2) +#define ABI_EXTENSION_VERSION SET_ABI_VERSION(5, 0) +#define ABI_FONT_VERSION SET_ABI_VERSION(0, 6) + +#define MODINFOSTRING1 0xef23fdc5 +#define MODINFOSTRING2 0x10dc023a + +#ifndef MODULEVENDORSTRING +#define MODULEVENDORSTRING "X.Org Foundation" +#endif + +/* Error return codes for errmaj. New codes must only be added at the end. */ +typedef enum { + LDR_NOERROR = 0, + LDR_NOMEM, /* memory allocation failed */ + LDR_NOENT, /* Module file does not exist */ + LDR_NOSUBENT, /* pre-requsite file to be sub-loaded does not exist */ + LDR_NOSPACE, /* internal module array full */ + LDR_NOMODOPEN, /* module file could not be opened (check errmin) */ + LDR_UNKTYPE, /* file is not a recognized module type */ + LDR_NOLOAD, /* type specific loader failed */ + LDR_ONCEONLY, /* Module should only be loaded once (not an error) */ + LDR_NOPORTOPEN, /* could not open port (check errmin) */ + LDR_NOHARDWARE, /* could not query/initialize the hardware device */ + LDR_MISMATCH, /* the module didn't match the spec'd requirments */ + LDR_BADUSAGE, /* LoadModule is called with bad arguments */ + LDR_INVALID, /* The module doesn't have a valid ModuleData object */ + LDR_BADOS, /* The module doesn't support the OS */ + LDR_MODSPECIFIC /* A module-specific error in the SetupProc */ +} LoaderErrorCode; + +/* + * Some common module classes. The moduleclass can be used to identify + * that modules loaded are of the correct type. This is a finer + * classification than the ABI classes even though the default set of + * classes have the same names. For example, not all modules that require + * the video driver ABI are themselves video drivers. + */ +#define MOD_CLASS_NONE NULL +#define MOD_CLASS_VIDEODRV "X.Org Video Driver" +#define MOD_CLASS_XINPUT "X.Org XInput Driver" +#define MOD_CLASS_FONT "X.Org Font Renderer" +#define MOD_CLASS_EXTENSION "X.Org Server Extension" + +/* This structure is expected to be returned by the initfunc */ +typedef struct { + const char * modname; /* name of module, e.g. "foo" */ + const char * vendor; /* vendor specific string */ + CARD32 _modinfo1_; /* constant MODINFOSTRING1/2 to find */ + CARD32 _modinfo2_; /* infoarea with a binary editor or sign tool */ + CARD32 xf86version; /* contains XF86_VERSION_CURRENT */ + CARD8 majorversion; /* module-specific major version */ + CARD8 minorversion; /* module-specific minor version */ + CARD16 patchlevel; /* module-specific patch level */ + const char * abiclass; /* ABI class that the module uses */ + CARD32 abiversion; /* ABI version */ + const char * moduleclass; /* module class description */ + CARD32 checksum[4]; /* contains a digital signature of the */ + /* version info structure */ +} XF86ModuleVersionInfo; + +/* + * This structure can be used to callers of LoadModule and LoadSubModule to + * specify version and/or ABI requirements. + */ +typedef struct { + CARD8 majorversion; /* module-specific major version */ + CARD8 minorversion; /* moudle-specific minor version */ + CARD16 patchlevel; /* module-specific patch level */ + const char * abiclass; /* ABI class that the module uses */ + CARD32 abiversion; /* ABI version */ + const char * moduleclass; /* module class */ +} XF86ModReqInfo; + +/* values to indicate unspecified fields in XF86ModReqInfo. */ +#define MAJOR_UNSPEC 0xFF +#define MINOR_UNSPEC 0xFF +#define PATCH_UNSPEC 0xFFFF +#define ABI_VERS_UNSPEC 0xFFFFFFFF + +#define MODULE_VERSION_NUMERIC(maj, min, patch) \ + ((((maj) & 0xFF) << 24) | (((min) & 0xFF) << 16) | (patch & 0xFFFF)) +#define GET_MODULE_MAJOR_VERSION(vers) (((vers) >> 24) & 0xFF) +#define GET_MODULE_MINOR_VERSION(vers) (((vers) >> 16) & 0xFF) +#define GET_MODULE_PATCHLEVEL(vers) ((vers) & 0xFFFF) + +#define INITARGS void + +typedef void (*InitExtension)(INITARGS); + +typedef struct { + InitExtension initFunc; + const char * name; + Bool *disablePtr; + InitExtension setupFunc; + const char ** initDependencies; +} ExtensionModule; + +extern _X_EXPORT ExtensionModule *ExtensionModuleList; + +/* Prototypes for Loader functions that are exported to modules */ +extern _X_EXPORT pointer LoadSubModule(pointer, const char *, const char **, + const char **, pointer, const XF86ModReqInfo *, + int *, int *); +extern _X_EXPORT void UnloadSubModule(pointer); +extern _X_EXPORT void UnloadModule (pointer); +extern _X_EXPORT pointer LoaderSymbol(const char *); +extern _X_EXPORT char **LoaderListDirs(const char **, const char **); +extern _X_EXPORT void LoaderFreeDirList(char **); +extern _X_EXPORT void LoaderErrorMsg(const char *, const char *, int, int); +extern _X_EXPORT void LoadExtension(ExtensionModule *, Bool); +extern _X_EXPORT void LoaderGetOS(const char **name, int *major, int *minor, int *teeny); +extern _X_EXPORT Bool LoaderShouldIgnoreABI(void); +extern _X_EXPORT int LoaderGetABIVersion(const char *abiclass); + +typedef pointer (*ModuleSetupProc)(pointer, pointer, int *, int *); +typedef void (*ModuleTearDownProc)(pointer); +#define MODULESETUPPROTO(func) pointer func(pointer, pointer, int*, int*) +#define MODULETEARDOWNPROTO(func) void func(pointer) + +typedef struct { + XF86ModuleVersionInfo * vers; + ModuleSetupProc setup; + ModuleTearDownProc teardown; +} XF86ModuleData; + +#endif /* _XF86STR_H */ diff --git a/hw/xfree86/common/xf86Opt.h b/hw/xfree86/common/xf86Opt.h new file mode 100644 index 0000000..9453f2a --- /dev/null +++ b/hw/xfree86/common/xf86Opt.h @@ -0,0 +1,118 @@ + +/* + * Copyright (c) 1998-2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* Option handling things that ModuleSetup procs can use */ + +#ifndef _XF86_OPT_H_ +#define _XF86_OPT_H_ + +typedef struct { + double freq; + int units; +} OptFrequency; + +typedef union { + unsigned long num; + char * str; + double realnum; + Bool bool; + OptFrequency freq; +} ValueUnion; + +typedef enum { + OPTV_NONE = 0, + OPTV_INTEGER, + OPTV_STRING, /* a non-empty string */ + OPTV_ANYSTR, /* Any string, including an empty one */ + OPTV_REAL, + OPTV_BOOLEAN, + OPTV_PERCENT, + OPTV_FREQ +} OptionValueType; + +typedef enum { + OPTUNITS_HZ = 1, + OPTUNITS_KHZ, + OPTUNITS_MHZ +} OptFreqUnits; + +typedef struct { + int token; + const char* name; + OptionValueType type; + ValueUnion value; + Bool found; +} OptionInfoRec, *OptionInfoPtr; + +extern _X_EXPORT int xf86SetIntOption(pointer optlist, const char *name, int deflt); +extern _X_EXPORT double xf86SetRealOption(pointer optlist, const char *name, double deflt); +extern _X_EXPORT char *xf86SetStrOption(pointer optlist, const char *name, char *deflt); +extern _X_EXPORT int xf86SetBoolOption(pointer list, const char *name, int deflt ); +extern _X_EXPORT double xf86SetPercentOption(pointer list, const char *name, double deflt ); +extern _X_EXPORT int xf86CheckIntOption(pointer optlist, const char *name, int deflt); +extern _X_EXPORT double xf86CheckRealOption(pointer optlist, const char *name, double deflt); +extern _X_EXPORT char *xf86CheckStrOption(pointer optlist, const char *name, char *deflt); +extern _X_EXPORT int xf86CheckBoolOption(pointer list, const char *name, int deflt ); +extern _X_EXPORT double xf86CheckPercentOption(pointer list, const char *name, double deflt ); +extern _X_EXPORT pointer xf86AddNewOption(pointer head, const char *name, const char *val ); +extern _X_EXPORT pointer xf86NewOption(char *name, char *value ); +extern _X_EXPORT pointer xf86NextOption(pointer list ); +extern _X_EXPORT pointer xf86OptionListCreate(const char **options, int count, int used); +extern _X_EXPORT pointer xf86OptionListMerge(pointer head, pointer tail); +extern _X_EXPORT pointer xf86OptionListDuplicate(pointer list); +extern _X_EXPORT void xf86OptionListFree(pointer opt); +extern _X_EXPORT char *xf86OptionName(pointer opt); +extern _X_EXPORT char *xf86OptionValue(pointer opt); +extern _X_EXPORT void xf86OptionListReport(pointer parm); +extern _X_EXPORT pointer xf86FindOption(pointer options, const char *name); +extern _X_EXPORT char *xf86FindOptionValue(pointer options, const char *name); +extern _X_EXPORT void xf86MarkOptionUsed(pointer option); +extern _X_EXPORT void xf86MarkOptionUsedByName(pointer options, const char *name); +extern _X_EXPORT Bool xf86CheckIfOptionUsed(pointer option); +extern _X_EXPORT Bool xf86CheckIfOptionUsedByName(pointer options, const char *name); +extern _X_EXPORT void xf86ShowUnusedOptions(int scrnIndex, pointer options); +extern _X_EXPORT void xf86ProcessOptions(int scrnIndex, pointer options, OptionInfoPtr optinfo); +extern _X_EXPORT OptionInfoPtr xf86TokenToOptinfo(const OptionInfoRec *table, int token); +extern _X_EXPORT const char *xf86TokenToOptName(const OptionInfoRec *table, int token); +extern _X_EXPORT Bool xf86IsOptionSet(const OptionInfoRec *table, int token); +extern _X_EXPORT char *xf86GetOptValString(const OptionInfoRec *table, int token); +extern _X_EXPORT Bool xf86GetOptValInteger(const OptionInfoRec *table, int token, int *value); +extern _X_EXPORT Bool xf86GetOptValULong(const OptionInfoRec *table, int token, unsigned long *value); +extern _X_EXPORT Bool xf86GetOptValReal(const OptionInfoRec *table, int token, double *value); +extern _X_EXPORT Bool xf86GetOptValFreq(const OptionInfoRec *table, int token, + OptFreqUnits expectedUnits, double *value); +extern _X_EXPORT Bool xf86GetOptValBool(const OptionInfoRec *table, int token, Bool *value); +extern _X_EXPORT Bool xf86ReturnOptValBool(const OptionInfoRec *table, int token, Bool def); +extern _X_EXPORT int xf86NameCmp(const char *s1, const char *s2); +extern _X_EXPORT char *xf86NormalizeName(const char *s); +extern _X_EXPORT pointer xf86ReplaceIntOption(pointer optlist, const char *name, const int val); +extern _X_EXPORT pointer xf86ReplaceRealOption(pointer optlist, const char *name, const double val); +extern _X_EXPORT pointer xf86ReplaceBoolOption(pointer optlist, const char *name, const Bool val); +extern _X_EXPORT pointer xf86ReplacePercentOption(pointer optlist, const char *name, const double val); +extern _X_EXPORT pointer xf86ReplaceStrOption(pointer optlist, const char *name, const char* val); +#endif diff --git a/hw/xfree86/common/xf86Option.c b/hw/xfree86/common/xf86Option.c new file mode 100644 index 0000000..480f386 --- /dev/null +++ b/hw/xfree86/common/xf86Option.c @@ -0,0 +1,916 @@ +/* + * Copyright (c) 1998-2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * Author: David Dawes <dawes@xfree86.org> + * + * This file includes public option handling functions. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <stdlib.h> +#include <ctype.h> +#include <X11/X.h> +#include "os.h" +#include "xf86.h" +#include "xf86Xinput.h" +#include "xf86Optrec.h" +#include "xf86Parser.h" + +static Bool ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p, + Bool markUsed); + +/* + * xf86CollectOptions collects the options from each of the config file + * sections used by the screen and puts the combined list in pScrn->options. + * This function requires that the following have been initialised: + * + * pScrn->confScreen + * pScrn->Entities[i]->device + * pScrn->display + * pScrn->monitor + * + * The extraOpts parameter may optionally contain a list of additional options + * to include. + * + * The order of precedence for options is: + * + * extraOpts, display, confScreen, monitor, device + */ + +void +xf86CollectOptions(ScrnInfoPtr pScrn, pointer extraOpts) +{ + XF86OptionPtr tmp; + XF86OptionPtr extras = (XF86OptionPtr)extraOpts; + GDevPtr device; + + int i; + + pScrn->options = NULL; + + for (i=pScrn->numEntities - 1; i >= 0; i--) { + device = xf86GetDevFromEntity(pScrn->entityList[i], + pScrn->entityInstanceList[i]); + if (device && device->options) { + tmp = xf86optionListDup(device->options); + if (pScrn->options) + xf86optionListMerge(pScrn->options,tmp); + else + pScrn->options = tmp; + } + } + if (pScrn->monitor->options) { + tmp = xf86optionListDup(pScrn->monitor->options); + if (pScrn->options) + pScrn->options = xf86optionListMerge(pScrn->options, tmp); + else + pScrn->options = tmp; + } + if (pScrn->confScreen->options) { + tmp = xf86optionListDup(pScrn->confScreen->options); + if (pScrn->options) + pScrn->options = xf86optionListMerge(pScrn->options, tmp); + else + pScrn->options = tmp; + } + if (pScrn->display->options) { + tmp = xf86optionListDup(pScrn->display->options); + if (pScrn->options) + pScrn->options = xf86optionListMerge(pScrn->options, tmp); + else + pScrn->options = tmp; + } + if (extras) { + tmp = xf86optionListDup(extras); + if (pScrn->options) + pScrn->options = xf86optionListMerge(pScrn->options, tmp); + else + pScrn->options = tmp; + } +} + +/* + * xf86CollectInputOptions collects extra options for an InputDevice (other + * than those added by the config backend). + * The options are merged into the existing ones and thus take precedence + * over the others. + */ + +void +xf86CollectInputOptions(InputInfoPtr pInfo, const char **defaultOpts) +{ + if (defaultOpts) { + XF86OptionPtr tmp =xf86optionListCreate(defaultOpts, -1, 0); + if (pInfo->options) + pInfo->options = xf86optionListMerge(tmp, pInfo->options); + else + pInfo->options = tmp; + } +} + +/** + * Duplicate the option list passed in. The returned pointer will be a newly + * allocated option list and must be freed by the caller. + */ +pointer +xf86OptionListDuplicate(pointer options) +{ + pointer o = NULL; + + while (options) + { + o = xf86AddNewOption(o, xf86OptionName(options), xf86OptionValue(options)); + options = xf86nextOption(options); + } + + return o; +} + + +/* Created for new XInput stuff -- essentially extensions to the parser */ + +static int +LookupIntOption(pointer optlist, const char *name, int deflt, Bool markUsed) +{ + OptionInfoRec o; + + o.name = name; + o.type = OPTV_INTEGER; + if (ParseOptionValue(-1, optlist, &o, markUsed)) + deflt = o.value.num; + return deflt; +} + + +static double +LookupRealOption(pointer optlist, const char *name, double deflt, + Bool markUsed) +{ + OptionInfoRec o; + + o.name = name; + o.type = OPTV_REAL; + if (ParseOptionValue(-1, optlist, &o, markUsed)) + deflt = o.value.realnum; + return deflt; +} + + +static char * +LookupStrOption(pointer optlist, const char *name, char *deflt, Bool markUsed) +{ + OptionInfoRec o; + + o.name = name; + o.type = OPTV_STRING; + if (ParseOptionValue(-1, optlist, &o, markUsed)) + deflt = o.value.str; + if (deflt) + return strdup(deflt); + else + return NULL; +} + + +static int +LookupBoolOption(pointer optlist, const char *name, int deflt, Bool markUsed) +{ + OptionInfoRec o; + + o.name = name; + o.type = OPTV_BOOLEAN; + if (ParseOptionValue(-1, optlist, &o, markUsed)) + deflt = o.value.bool; + return deflt; +} + +static double +LookupPercentOption(pointer optlist, const char *name, double deflt, Bool markUsed) +{ + OptionInfoRec o; + + o.name = name; + o.type = OPTV_PERCENT; + if (ParseOptionValue(-1, optlist, &o, markUsed)) + deflt = o.value.realnum; + return deflt; +} + +/* These xf86Set* functions are intended for use by non-screen specific code */ + +int +xf86SetIntOption(pointer optlist, const char *name, int deflt) +{ + return LookupIntOption(optlist, name, deflt, TRUE); +} + + +double +xf86SetRealOption(pointer optlist, const char *name, double deflt) +{ + return LookupRealOption(optlist, name, deflt, TRUE); +} + + +char * +xf86SetStrOption(pointer optlist, const char *name, char *deflt) +{ + return LookupStrOption(optlist, name, deflt, TRUE); +} + + +int +xf86SetBoolOption(pointer optlist, const char *name, int deflt) +{ + return LookupBoolOption(optlist, name, deflt, TRUE); +} + +double +xf86SetPercentOption(pointer optlist, const char *name, double deflt) +{ + return LookupPercentOption(optlist, name, deflt, TRUE); +} + +/* + * These are like the Set*Option functions, but they don't mark the options + * as used. + */ +int +xf86CheckIntOption(pointer optlist, const char *name, int deflt) +{ + return LookupIntOption(optlist, name, deflt, FALSE); +} + + +double +xf86CheckRealOption(pointer optlist, const char *name, double deflt) +{ + return LookupRealOption(optlist, name, deflt, FALSE); +} + + +char * +xf86CheckStrOption(pointer optlist, const char *name, char *deflt) +{ + return LookupStrOption(optlist, name, deflt, FALSE); +} + + +int +xf86CheckBoolOption(pointer optlist, const char *name, int deflt) +{ + return LookupBoolOption(optlist, name, deflt, FALSE); +} + + +double +xf86CheckPercentOption(pointer optlist, const char *name, double deflt) +{ + return LookupPercentOption(optlist, name, deflt, FALSE); +} +/* + * addNewOption() has the required property of replacing the option value + * if the option is already present. + */ +pointer +xf86ReplaceIntOption(pointer optlist, const char *name, const int val) +{ + char tmp[16]; + sprintf(tmp,"%i",val); + return xf86AddNewOption(optlist,name,tmp); +} + +pointer +xf86ReplaceRealOption(pointer optlist, const char *name, const double val) +{ + char tmp[32]; + snprintf(tmp,32,"%f",val); + return xf86AddNewOption(optlist,name,tmp); +} + +pointer +xf86ReplaceBoolOption(pointer optlist, const char *name, const Bool val) +{ + return xf86AddNewOption(optlist,name,val?"True":"False"); +} + +pointer +xf86ReplacePercentOption(pointer optlist, const char *name, const double val) +{ + char tmp[16]; + sprintf(tmp, "%lf%%", val); + return xf86AddNewOption(optlist,name,tmp); +} + +pointer +xf86ReplaceStrOption(pointer optlist, const char *name, const char* val) +{ + return xf86AddNewOption(optlist,name,val); +} + +pointer +xf86AddNewOption(pointer head, const char *name, const char *val) +{ + /* XXX These should actually be allocated in the parser library. */ + char *tmp = strdup(val); + char *tmp_name = strdup(name); + + return xf86addNewOption(head, tmp_name, tmp); +} + + +pointer +xf86NewOption(char *name, char *value) +{ + return xf86newOption(name, value); +} + + +pointer +xf86NextOption(pointer list) +{ + return xf86nextOption(list); +} + +pointer +xf86OptionListCreate(const char **options, int count, int used) +{ + return xf86optionListCreate(options, count, used); +} + +pointer +xf86OptionListMerge(pointer head, pointer tail) +{ + return xf86optionListMerge(head, tail); +} + +void +xf86OptionListFree(pointer opt) +{ + xf86optionListFree(opt); +} + +char * +xf86OptionName(pointer opt) +{ + return xf86optionName(opt); +} + +char * +xf86OptionValue(pointer opt) +{ + return xf86optionValue(opt); +} + +void +xf86OptionListReport(pointer parm) +{ + XF86OptionPtr opts = parm; + + while(opts) { + if (xf86optionValue(opts)) + xf86ErrorFVerb(5, "\tOption \"%s\" \"%s\"\n", + xf86optionName(opts), xf86optionValue(opts)); + else + xf86ErrorFVerb( 5, "\tOption \"%s\"\n", xf86optionName(opts)); + opts = xf86nextOption(opts); + } +} + +/* End of XInput-caused section */ + +pointer +xf86FindOption(pointer options, const char *name) +{ + return xf86findOption(options, name); +} + + +char * +xf86FindOptionValue(pointer options, const char *name) +{ + return xf86findOptionValue(options, name); +} + + +void +xf86MarkOptionUsed(pointer option) +{ + if (option != NULL) + ((XF86OptionPtr)option)->opt_used = TRUE; +} + + +void +xf86MarkOptionUsedByName(pointer options, const char *name) +{ + XF86OptionPtr opt; + + opt = xf86findOption(options, name); + if (opt != NULL) + opt->opt_used = TRUE; +} + +Bool +xf86CheckIfOptionUsed(pointer option) +{ + if (option != NULL) + return ((XF86OptionPtr)option)->opt_used; + else + return FALSE; +} + +Bool +xf86CheckIfOptionUsedByName(pointer options, const char *name) +{ + XF86OptionPtr opt; + + opt = xf86findOption(options, name); + if (opt != NULL) + return opt->opt_used; + else + return FALSE; +} + +void +xf86ShowUnusedOptions(int scrnIndex, pointer options) +{ + XF86OptionPtr opt = options; + + while (opt) { + if (opt->opt_name && !opt->opt_used) { + xf86DrvMsg(scrnIndex, X_WARNING, "Option \"%s\" is not used\n", + opt->opt_name); + } + opt = opt->list.next; + } +} + + +static Bool +GetBoolValue(OptionInfoPtr p, const char *s) +{ + return xf86getBoolValue(&p->value.bool, s); +} + +static Bool +ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p, + Bool markUsed) +{ + char *s, *end; + Bool wasUsed = FALSE; + + if ((s = xf86findOptionValue(options, p->name)) != NULL) { + if (markUsed) { + wasUsed = xf86CheckIfOptionUsedByName(options, p->name); + xf86MarkOptionUsedByName(options, p->name); + } + switch (p->type) { + case OPTV_INTEGER: + if (*s == '\0') { + if (markUsed) { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires an integer value\n", + p->name); + } + p->found = FALSE; + } else { + p->value.num = strtoul(s, &end, 0); + if (*end == '\0') { + p->found = TRUE; + } else { + if (markUsed) { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires an integer value\n", + p->name); + } + p->found = FALSE; + } + } + break; + case OPTV_STRING: + if (*s == '\0') { + if (markUsed) { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires an string value\n", + p->name); + } + p->found = FALSE; + } else { + p->value.str = s; + p->found = TRUE; + } + break; + case OPTV_ANYSTR: + p->value.str = s; + p->found = TRUE; + break; + case OPTV_REAL: + if (*s == '\0') { + if (markUsed) { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a floating point " + "value\n", p->name); + } + p->found = FALSE; + } else { + p->value.realnum = strtod(s, &end); + if (*end == '\0') { + p->found = TRUE; + } else { + if (markUsed) { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a floating point " + "value\n", p->name); + } + p->found = FALSE; + } + } + break; + case OPTV_BOOLEAN: + if (GetBoolValue(p, s)) { + p->found = TRUE; + } else { + if (markUsed) { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a boolean value\n", + p->name); + } + p->found = FALSE; + } + break; + case OPTV_PERCENT: + { + char tmp = 0; + /* awkward match, but %% doesn't increase the match counter, + * hence 100 looks the same as 100% to the caller of sccanf + */ + if (sscanf(s, "%lf%c", &p->value.realnum, &tmp) != 2 || tmp != '%') { + if (markUsed) { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a percent value\n", p->name); + } + p->found = FALSE; + } else { + p->found = TRUE; + } + } + break; + case OPTV_FREQ: + if (*s == '\0') { + if (markUsed) { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a frequency value\n", + p->name); + } + p->found = FALSE; + } else { + double freq = strtod(s, &end); + int units = 0; + + if (end != s) { + p->found = TRUE; + if (!xf86NameCmp(end, "Hz")) + units = 1; + else if (!xf86NameCmp(end, "kHz") || + !xf86NameCmp(end, "k")) + units = 1000; + else if (!xf86NameCmp(end, "MHz") || + !xf86NameCmp(end, "M")) + units = 1000000; + else { + if (markUsed) { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a frequency value\n", + p->name); + } + p->found = FALSE; + } + if (p->found) + freq *= (double)units; + } else { + if (markUsed) { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a frequency value\n", + p->name); + } + p->found = FALSE; + } + if (p->found) { + p->value.freq.freq = freq; + p->value.freq.units = units; + } + } + break; + case OPTV_NONE: + /* Should never get here */ + p->found = FALSE; + break; + } + if (p->found && markUsed) { + int verb = 2; + if (wasUsed) + verb = 4; + xf86DrvMsgVerb(scrnIndex, X_CONFIG, verb, "Option \"%s\"", p->name); + if (!(p->type == OPTV_BOOLEAN && *s == 0)) { + xf86ErrorFVerb(verb, " \"%s\"", s); + } + xf86ErrorFVerb(verb, "\n"); + } + } else if (p->type == OPTV_BOOLEAN) { + /* Look for matches with options with or without a "No" prefix. */ + char *n, *newn; + OptionInfoRec opt; + + n = xf86NormalizeName(p->name); + if (!n) { + p->found = FALSE; + return FALSE; + } + if (strncmp(n, "no", 2) == 0) { + newn = n + 2; + } else { + free(n); + if (asprintf(&n, "No%s", p->name) == -1) { + p->found = FALSE; + return FALSE; + } + newn = n; + } + if ((s = xf86findOptionValue(options, newn)) != NULL) { + if (markUsed) + xf86MarkOptionUsedByName(options, newn); + if (GetBoolValue(&opt, s)) { + p->value.bool = !opt.value.bool; + p->found = TRUE; + } else { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a boolean value\n", newn); + p->found = FALSE; + } + } else { + p->found = FALSE; + } + if (p->found && markUsed) { + xf86DrvMsgVerb(scrnIndex, X_CONFIG, 2, "Option \"%s\"", newn); + if (*s != 0) { + xf86ErrorFVerb(2, " \"%s\"", s); + } + xf86ErrorFVerb(2, "\n"); + } + free(n); + } else { + p->found = FALSE; + } + return p->found; +} + + +void +xf86ProcessOptions(int scrnIndex, pointer options, OptionInfoPtr optinfo) +{ + OptionInfoPtr p; + + for (p = optinfo; p->name != NULL; p++) { + ParseOptionValue(scrnIndex, options, p, TRUE); + } +} + + +OptionInfoPtr +xf86TokenToOptinfo(const OptionInfoRec *table, int token) +{ + const OptionInfoRec *p, *match = NULL, *set = NULL; + + if (!table) { + ErrorF("xf86TokenToOptinfo: table is NULL\n"); + return NULL; + } + + for (p = table; p->token >= 0; p++) { + if (p->token == token) { + match = p; + if (p->found) + set = p; + } + } + + if (set) + return (OptionInfoPtr)set; + else if (match) + return (OptionInfoPtr)match; + else + return NULL; +} + + +const char * +xf86TokenToOptName(const OptionInfoRec *table, int token) +{ + const OptionInfoRec *p; + + p = xf86TokenToOptinfo(table, token); + return p->name; +} + + +Bool +xf86IsOptionSet(const OptionInfoRec *table, int token) +{ + OptionInfoPtr p; + + p = xf86TokenToOptinfo(table, token); + return p && p->found; +} + + +char * +xf86GetOptValString(const OptionInfoRec *table, int token) +{ + OptionInfoPtr p; + + p = xf86TokenToOptinfo(table, token); + if (p && p->found) + return p->value.str; + else + return NULL; +} + + +Bool +xf86GetOptValInteger(const OptionInfoRec *table, int token, int *value) +{ + OptionInfoPtr p; + + p = xf86TokenToOptinfo(table, token); + if (p && p->found) { + *value = p->value.num; + return TRUE; + } else + return FALSE; +} + + +Bool +xf86GetOptValULong(const OptionInfoRec *table, int token, unsigned long *value) +{ + OptionInfoPtr p; + + p = xf86TokenToOptinfo(table, token); + if (p && p->found) { + *value = p->value.num; + return TRUE; + } else + return FALSE; +} + + +Bool +xf86GetOptValReal(const OptionInfoRec *table, int token, double *value) +{ + OptionInfoPtr p; + + p = xf86TokenToOptinfo(table, token); + if (p && p->found) { + *value = p->value.realnum; + return TRUE; + } else + return FALSE; +} + + +Bool +xf86GetOptValFreq(const OptionInfoRec *table, int token, + OptFreqUnits expectedUnits, double *value) +{ + OptionInfoPtr p; + + p = xf86TokenToOptinfo(table, token); + if (p && p->found) { + if (p->value.freq.units > 0) { + /* Units give, so the scaling is known. */ + switch (expectedUnits) { + case OPTUNITS_HZ: + *value = p->value.freq.freq; + break; + case OPTUNITS_KHZ: + *value = p->value.freq.freq / 1000.0; + break; + case OPTUNITS_MHZ: + *value = p->value.freq.freq / 1000000.0; + break; + } + } else { + /* No units given, so try to guess the scaling. */ + switch (expectedUnits) { + case OPTUNITS_HZ: + *value = p->value.freq.freq; + break; + case OPTUNITS_KHZ: + if (p->value.freq.freq > 1000.0) + *value = p->value.freq.freq / 1000.0; + else + *value = p->value.freq.freq; + break; + case OPTUNITS_MHZ: + if (p->value.freq.freq > 1000000.0) + *value = p->value.freq.freq / 1000000.0; + else if (p->value.freq.freq > 1000.0) + *value = p->value.freq.freq / 1000.0; + else + *value = p->value.freq.freq; + } + } + return TRUE; + } else + return FALSE; +} + + +Bool +xf86GetOptValBool(const OptionInfoRec *table, int token, Bool *value) +{ + OptionInfoPtr p; + + p = xf86TokenToOptinfo(table, token); + if (p && p->found) { + *value = p->value.bool; + return TRUE; + } else + return FALSE; +} + + +Bool +xf86ReturnOptValBool(const OptionInfoRec *table, int token, Bool def) +{ + OptionInfoPtr p; + + p = xf86TokenToOptinfo(table, token); + if (p && p->found) { + return p->value.bool; + } else + return def; +} + + +int +xf86NameCmp(const char *s1, const char *s2) +{ + return xf86nameCompare(s1, s2); +} + +char * +xf86NormalizeName(const char *s) +{ + char *ret, *q; + const char *p; + + if (s == NULL) + return NULL; + + ret = malloc(strlen(s) + 1); + for (p = s, q = ret; *p != 0; p++) { + switch (*p) { + case '_': + case ' ': + case '\t': + continue; + default: + if (isupper(*p)) + *q++ = tolower(*p); + else + *q++ = *p; + } + } + *q = '\0'; + return ret; +} diff --git a/hw/xfree86/common/xf86PM.c b/hw/xfree86/common/xf86PM.c new file mode 100644 index 0000000..16b6bdc --- /dev/null +++ b/hw/xfree86/common/xf86PM.c @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2000-2002 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <X11/X.h> +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86Xinput.h" +#include "xf86_OSproc.h" + +int (*xf86PMGetEventFromOs)(int fd,pmEvent *events,int num) = NULL; +pmWait (*xf86PMConfirmEventToOs)(int fd,pmEvent event) = NULL; + +static Bool suspended = FALSE; + +static int +eventName(pmEvent event, char **str) +{ + switch(event) { + case XF86_APM_SYS_STANDBY: *str="System Standby Request"; return 0; + case XF86_APM_SYS_SUSPEND: *str="System Suspend Request"; return 0; + case XF86_APM_CRITICAL_SUSPEND: *str="Critical Suspend"; return 0; + case XF86_APM_USER_STANDBY: *str="User System Standby Request"; return 0; + case XF86_APM_USER_SUSPEND: *str="User System Suspend Request"; return 0; + case XF86_APM_STANDBY_RESUME: *str="System Standby Resume"; return 0; + case XF86_APM_NORMAL_RESUME: *str="Normal Resume System"; return 0; + case XF86_APM_CRITICAL_RESUME: *str="Critical Resume System"; return 0; + case XF86_APM_LOW_BATTERY: *str="Battery Low"; return 3; + case XF86_APM_POWER_STATUS_CHANGE: *str="Power Status Change";return 3; + case XF86_APM_UPDATE_TIME: *str="Update Time";return 3; + case XF86_APM_CAPABILITY_CHANGED: *str="Capability Changed"; return 3; + case XF86_APM_STANDBY_FAILED: *str="Standby Request Failed"; return 0; + case XF86_APM_SUSPEND_FAILED: *str="Suspend Request Failed"; return 0; + default: *str="Unknown Event"; return 0; + } +} + +static int sigio_blocked_for_suspend; + +static void +suspend (pmEvent event, Bool undo) +{ + int i; + InputInfoPtr pInfo; + + for (i = 0; i < xf86NumScreens; i++) { + if (xf86Screens[i]->EnableDisableFBAccess) + (*xf86Screens[i]->EnableDisableFBAccess) (i, FALSE); + } + pInfo = xf86InputDevs; + while (pInfo) { + DisableDevice(pInfo->dev, TRUE); + pInfo = pInfo->next; + } + sigio_blocked_for_suspend = xf86BlockSIGIO(); + for (i = 0; i < xf86NumScreens; i++) { + if (xf86Screens[i]->PMEvent) + xf86Screens[i]->PMEvent(i,event,undo); + else { + xf86Screens[i]->LeaveVT(i, 0); + xf86Screens[i]->vtSema = FALSE; + } + } + xf86AccessLeave(); + +} + +static void +resume(pmEvent event, Bool undo) +{ + int i; + InputInfoPtr pInfo; + + xf86AccessEnter(); + for (i = 0; i < xf86NumScreens; i++) { + if (xf86Screens[i]->PMEvent) + xf86Screens[i]->PMEvent(i,event,undo); + else { + xf86Screens[i]->vtSema = TRUE; + xf86Screens[i]->EnterVT(i, 0); + } + } + xf86UnblockSIGIO(sigio_blocked_for_suspend); + for (i = 0; i < xf86NumScreens; i++) { + if (xf86Screens[i]->EnableDisableFBAccess) + (*xf86Screens[i]->EnableDisableFBAccess) (i, TRUE); + } + dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset); + pInfo = xf86InputDevs; + while (pInfo) { + EnableDevice(pInfo->dev, TRUE); + pInfo = pInfo->next; + } +} + +static void +DoApmEvent(pmEvent event, Bool undo) +{ + int i, was_blocked; + + switch(event) { +#if 0 + case XF86_APM_SYS_STANDBY: + case XF86_APM_USER_STANDBY: +#endif + case XF86_APM_SYS_SUSPEND: + case XF86_APM_CRITICAL_SUSPEND: /*do we want to delay a critical suspend?*/ + case XF86_APM_USER_SUSPEND: + /* should we do this ? */ + if (!undo && !suspended) { + suspend(event,undo); + suspended = TRUE; + } else if (undo && suspended) { + resume(event,undo); + suspended = FALSE; + } + break; +#if 0 + case XF86_APM_STANDBY_RESUME: +#endif + case XF86_APM_NORMAL_RESUME: + case XF86_APM_CRITICAL_RESUME: + if (suspended) { + resume(event,undo); + suspended = FALSE; + } + break; + default: + was_blocked = xf86BlockSIGIO(); + for (i = 0; i < xf86NumScreens; i++) { + if (xf86Screens[i]->PMEvent) { + xf86Screens[i]->PMEvent(i,event,undo); + } + } + xf86UnblockSIGIO(was_blocked); + break; + } +} + +#define MAX_NO_EVENTS 8 + +void +xf86HandlePMEvents(int fd, pointer data) +{ + pmEvent events[MAX_NO_EVENTS]; + int i,n; + Bool wait = FALSE; + + if (!xf86PMGetEventFromOs) + return; + + if ((n = xf86PMGetEventFromOs(fd,events,MAX_NO_EVENTS))) { + do { + for (i = 0; i < n; i++) { + char *str = NULL; + int verb = eventName(events[i],&str); + + xf86MsgVerb(X_INFO,verb,"PM Event received: %s\n",str); + DoApmEvent(events[i],FALSE); + switch (xf86PMConfirmEventToOs(fd,events[i])) { + case PM_WAIT: + wait = TRUE; + break; + case PM_CONTINUE: + wait = FALSE; + break; + case PM_FAILED: + DoApmEvent(events[i],TRUE); + wait = FALSE; + break; + default: + break; + } + } + if (wait) + n = xf86PMGetEventFromOs(fd,events,MAX_NO_EVENTS); + else + break; + } while (1); + } +} diff --git a/hw/xfree86/common/xf86PciInfo.h b/hw/xfree86/common/xf86PciInfo.h new file mode 100644 index 0000000..356c7db --- /dev/null +++ b/hw/xfree86/common/xf86PciInfo.h @@ -0,0 +1,731 @@ + +/* + * Copyright (c) 1995-2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * This file contains macros for the PCI Vendor and Device IDs for video + * cards plus a few other things that are needed in drivers or elsewhere. + * This information is used in several ways: + * 1. It is used by drivers and/or other code. + * 2. It is used by the pciid2c.pl script to determine what vendor data to + * include in the pcidata module that the X server loads. + * 3. A side-effect of 2. affects how config-generation works for + * otherwise "unknown" cards. + * + * Don't add entries here for vendors that don't make video cards, + * or for non-video devices unless they're needed by a driver or elsewhere. + * A comprehensive set of PCI vendor, device and subsystem data is + * auto-generated from the ../etc/pci.ids file using the pciids2c.pl script, + * and is used in scanpci utility. Don't modify the pci.ids file. If + * new/corrected entries are required, add them to ../etc/extrapci.ids. + */ + +#ifndef _XF86_PCIINFO_H +#define _XF86_PCIINFO_H + +/* PCI Pseudo Vendor */ +#define PCI_VENDOR_GENERIC 0x00FF + +#define PCI_VENDOR_REAL3D 0x003D +#define PCI_VENDOR_COMPAQ 0x0E11 +#define PCI_VENDOR_ATI 0x1002 +#define PCI_VENDOR_AVANCE 0x1005 +#define PCI_VENDOR_TSENG 0x100C +#define PCI_VENDOR_NS 0x100B +#define PCI_VENDOR_WEITEK 0x100E +#define PCI_VENDOR_VIDEOLOGIC 0x1010 +#define PCI_VENDOR_DIGITAL 0x1011 +#define PCI_VENDOR_CIRRUS 0x1013 +#define PCI_VENDOR_AMD 0x1022 +#define PCI_VENDOR_TRIDENT 0x1023 +#define PCI_VENDOR_ALI 0x1025 +#define PCI_VENDOR_DELL 0x1028 +#define PCI_VENDOR_MATROX 0x102B +#define PCI_VENDOR_CHIPSTECH 0x102C +#define PCI_VENDOR_MIRO 0x1031 +#define PCI_VENDOR_NEC 0x1033 +#define PCI_VENDOR_SIS 0x1039 +#define PCI_VENDOR_HP 0x103C +#define PCI_VENDOR_SGS 0x104A +#define PCI_VENDOR_TI 0x104C +#define PCI_VENDOR_SONY 0x104D +#define PCI_VENDOR_OAK 0x104E +#define PCI_VENDOR_MOTOROLA 0x1057 +#define PCI_VENDOR_NUMNINE 0x105D +#define PCI_VENDOR_CYRIX 0x1078 +#define PCI_VENDOR_SUN 0x108E +#define PCI_VENDOR_DIAMOND 0x1092 +#define PCI_VENDOR_BROOKTREE 0x109E +#define PCI_VENDOR_NEOMAGIC 0x10C8 +#define PCI_VENDOR_NVIDIA 0x10DE +#define PCI_VENDOR_IMS 0x10E0 +#define PCI_VENDOR_INTEGRAPHICS 0x10EA +#define PCI_VENDOR_ALLIANCE 0x1142 +#define PCI_VENDOR_RENDITION 0x1163 +#define PCI_VENDOR_3DFX 0x121A +#define PCI_VENDOR_SMI 0x126F +#define PCI_VENDOR_TRITECH 0x1292 +#define PCI_VENDOR_NVIDIA_SGS 0x12D2 +#define PCI_VENDOR_VMWARE 0x15AD +#define PCI_VENDOR_AST 0x1A03 +#define PCI_VENDOR_3DLABS 0x3D3D +#define PCI_VENDOR_AVANCE_2 0x4005 +#define PCI_VENDOR_HERCULES 0x4843 +#define PCI_VENDOR_S3 0x5333 +#define PCI_VENDOR_INTEL 0x8086 +#define PCI_VENDOR_ARK 0xEDD8 + + +/* Generic */ +#define PCI_CHIP_VGA 0x0000 +#define PCI_CHIP_8514 0x0001 + +/* Real 3D */ +#define PCI_CHIP_I740_PCI 0x00D1 + +/* Compaq */ +#define PCI_CHIP_QV1280 0x3033 + +/* ATI */ +#define PCI_CHIP_RV380_3150 0x3150 +#define PCI_CHIP_RV380_3151 0x3151 +#define PCI_CHIP_RV380_3152 0x3152 +#define PCI_CHIP_RV380_3153 0x3153 +#define PCI_CHIP_RV380_3154 0x3154 +#define PCI_CHIP_RV380_3156 0x3156 +#define PCI_CHIP_RV380_3E50 0x3E50 +#define PCI_CHIP_RV380_3E51 0x3E51 +#define PCI_CHIP_RV380_3E52 0x3E52 +#define PCI_CHIP_RV380_3E53 0x3E53 +#define PCI_CHIP_RV380_3E54 0x3E54 +#define PCI_CHIP_RV380_3E56 0x3E56 +#define PCI_CHIP_RS100_4136 0x4136 +#define PCI_CHIP_RS200_4137 0x4137 +#define PCI_CHIP_R300_AD 0x4144 +#define PCI_CHIP_R300_AE 0x4145 +#define PCI_CHIP_R300_AF 0x4146 +#define PCI_CHIP_R300_AG 0x4147 +#define PCI_CHIP_R350_AH 0x4148 +#define PCI_CHIP_R350_AI 0x4149 +#define PCI_CHIP_R350_AJ 0x414A +#define PCI_CHIP_R350_AK 0x414B +#define PCI_CHIP_RV350_AP 0x4150 +#define PCI_CHIP_RV350_AQ 0x4151 +#define PCI_CHIP_RV360_AR 0x4152 +#define PCI_CHIP_RV350_AS 0x4153 +#define PCI_CHIP_RV350_AT 0x4154 +#define PCI_CHIP_RV350_4155 0x4155 +#define PCI_CHIP_RV350_AV 0x4156 +#define PCI_CHIP_MACH32 0x4158 +#define PCI_CHIP_RS250_4237 0x4237 +#define PCI_CHIP_R200_BB 0x4242 +#define PCI_CHIP_R200_BC 0x4243 +#define PCI_CHIP_RS100_4336 0x4336 +#define PCI_CHIP_RS200_4337 0x4337 +#define PCI_CHIP_MACH64CT 0x4354 +#define PCI_CHIP_MACH64CX 0x4358 +#define PCI_CHIP_RS250_4437 0x4437 +#define PCI_CHIP_MACH64ET 0x4554 +#define PCI_CHIP_MACH64GB 0x4742 +#define PCI_CHIP_MACH64GD 0x4744 +#define PCI_CHIP_MACH64GI 0x4749 +#define PCI_CHIP_MACH64GL 0x474C +#define PCI_CHIP_MACH64GM 0x474D +#define PCI_CHIP_MACH64GN 0x474E +#define PCI_CHIP_MACH64GO 0x474F +#define PCI_CHIP_MACH64GP 0x4750 +#define PCI_CHIP_MACH64GQ 0x4751 +#define PCI_CHIP_MACH64GR 0x4752 +#define PCI_CHIP_MACH64GS 0x4753 +#define PCI_CHIP_MACH64GT 0x4754 +#define PCI_CHIP_MACH64GU 0x4755 +#define PCI_CHIP_MACH64GV 0x4756 +#define PCI_CHIP_MACH64GW 0x4757 +#define PCI_CHIP_MACH64GX 0x4758 +#define PCI_CHIP_MACH64GY 0x4759 +#define PCI_CHIP_MACH64GZ 0x475A +#define PCI_CHIP_RV250_Id 0x4964 +#define PCI_CHIP_RV250_Ie 0x4965 +#define PCI_CHIP_RV250_If 0x4966 +#define PCI_CHIP_RV250_Ig 0x4967 +#define PCI_CHIP_R420_JH 0x4A48 +#define PCI_CHIP_R420_JI 0x4A49 +#define PCI_CHIP_R420_JJ 0x4A4A +#define PCI_CHIP_R420_JK 0x4A4B +#define PCI_CHIP_R420_JL 0x4A4C +#define PCI_CHIP_R420_JM 0x4A4D +#define PCI_CHIP_R420_JN 0x4A4E +#define PCI_CHIP_R420_4A4F 0x4A4F +#define PCI_CHIP_R420_JP 0x4A50 +#define PCI_CHIP_R420_4A54 0x4A54 +#define PCI_CHIP_R481_4B49 0x4B49 +#define PCI_CHIP_R481_4B4A 0x4B4A +#define PCI_CHIP_R481_4B4B 0x4B4B +#define PCI_CHIP_R481_4B4C 0x4B4C +#define PCI_CHIP_MACH64LB 0x4C42 +#define PCI_CHIP_MACH64LD 0x4C44 +#define PCI_CHIP_RAGE128LE 0x4C45 +#define PCI_CHIP_RAGE128LF 0x4C46 +#define PCI_CHIP_MACH64LG 0x4C47 +#define PCI_CHIP_MACH64LI 0x4C49 +#define PCI_CHIP_MACH64LM 0x4C4D +#define PCI_CHIP_MACH64LN 0x4C4E +#define PCI_CHIP_MACH64LP 0x4C50 +#define PCI_CHIP_MACH64LQ 0x4C51 +#define PCI_CHIP_MACH64LR 0x4C52 +#define PCI_CHIP_MACH64LS 0x4C53 +#define PCI_CHIP_RADEON_LW 0x4C57 +#define PCI_CHIP_RADEON_LX 0x4C58 +#define PCI_CHIP_RADEON_LY 0x4C59 +#define PCI_CHIP_RADEON_LZ 0x4C5A +#define PCI_CHIP_RV250_Ld 0x4C64 +#define PCI_CHIP_RV250_Le 0x4C65 +#define PCI_CHIP_RV250_Lf 0x4C66 +#define PCI_CHIP_RV250_Lg 0x4C67 +#define PCI_CHIP_RV250_Ln 0x4C6E +#define PCI_CHIP_RAGE128MF 0x4D46 +#define PCI_CHIP_RAGE128ML 0x4D4C +#define PCI_CHIP_R300_ND 0x4E44 +#define PCI_CHIP_R300_NE 0x4E45 +#define PCI_CHIP_R300_NF 0x4E46 +#define PCI_CHIP_R300_NG 0x4E47 +#define PCI_CHIP_R350_NH 0x4E48 +#define PCI_CHIP_R350_NI 0x4E49 +#define PCI_CHIP_R360_NJ 0x4E4A +#define PCI_CHIP_R350_NK 0x4E4B +#define PCI_CHIP_RV350_NP 0x4E50 +#define PCI_CHIP_RV350_NQ 0x4E51 +#define PCI_CHIP_RV350_NR 0x4E52 +#define PCI_CHIP_RV350_NS 0x4E53 +#define PCI_CHIP_RV350_NT 0x4E54 +#define PCI_CHIP_RV350_NV 0x4E56 +#define PCI_CHIP_RAGE128PA 0x5041 +#define PCI_CHIP_RAGE128PB 0x5042 +#define PCI_CHIP_RAGE128PC 0x5043 +#define PCI_CHIP_RAGE128PD 0x5044 +#define PCI_CHIP_RAGE128PE 0x5045 +#define PCI_CHIP_RAGE128PF 0x5046 +#define PCI_CHIP_RAGE128PG 0x5047 +#define PCI_CHIP_RAGE128PH 0x5048 +#define PCI_CHIP_RAGE128PI 0x5049 +#define PCI_CHIP_RAGE128PJ 0x504A +#define PCI_CHIP_RAGE128PK 0x504B +#define PCI_CHIP_RAGE128PL 0x504C +#define PCI_CHIP_RAGE128PM 0x504D +#define PCI_CHIP_RAGE128PN 0x504E +#define PCI_CHIP_RAGE128PO 0x504F +#define PCI_CHIP_RAGE128PP 0x5050 +#define PCI_CHIP_RAGE128PQ 0x5051 +#define PCI_CHIP_RAGE128PR 0x5052 +#define PCI_CHIP_RAGE128PS 0x5053 +#define PCI_CHIP_RAGE128PT 0x5054 +#define PCI_CHIP_RAGE128PU 0x5055 +#define PCI_CHIP_RAGE128PV 0x5056 +#define PCI_CHIP_RAGE128PW 0x5057 +#define PCI_CHIP_RAGE128PX 0x5058 +#define PCI_CHIP_RADEON_QD 0x5144 +#define PCI_CHIP_RADEON_QE 0x5145 +#define PCI_CHIP_RADEON_QF 0x5146 +#define PCI_CHIP_RADEON_QG 0x5147 +#define PCI_CHIP_R200_QH 0x5148 +#define PCI_CHIP_R200_QI 0x5149 +#define PCI_CHIP_R200_QJ 0x514A +#define PCI_CHIP_R200_QK 0x514B +#define PCI_CHIP_R200_QL 0x514C +#define PCI_CHIP_R200_QM 0x514D +#define PCI_CHIP_R200_QN 0x514E +#define PCI_CHIP_R200_QO 0x514F +#define PCI_CHIP_RV200_QW 0x5157 +#define PCI_CHIP_RV200_QX 0x5158 +#define PCI_CHIP_RV100_QY 0x5159 +#define PCI_CHIP_RV100_QZ 0x515A +#define PCI_CHIP_RN50_515E 0x515E +#define PCI_CHIP_RAGE128RE 0x5245 +#define PCI_CHIP_RAGE128RF 0x5246 +#define PCI_CHIP_RAGE128RG 0x5247 +#define PCI_CHIP_RAGE128RK 0x524B +#define PCI_CHIP_RAGE128RL 0x524C +#define PCI_CHIP_RAGE128SE 0x5345 +#define PCI_CHIP_RAGE128SF 0x5346 +#define PCI_CHIP_RAGE128SG 0x5347 +#define PCI_CHIP_RAGE128SH 0x5348 +#define PCI_CHIP_RAGE128SK 0x534B +#define PCI_CHIP_RAGE128SL 0x534C +#define PCI_CHIP_RAGE128SM 0x534D +#define PCI_CHIP_RAGE128SN 0x534E +#define PCI_CHIP_RAGE128TF 0x5446 +#define PCI_CHIP_RAGE128TL 0x544C +#define PCI_CHIP_RAGE128TR 0x5452 +#define PCI_CHIP_RAGE128TS 0x5453 +#define PCI_CHIP_RAGE128TT 0x5454 +#define PCI_CHIP_RAGE128TU 0x5455 +#define PCI_CHIP_RV370_5460 0x5460 +#define PCI_CHIP_RV370_5461 0x5461 +#define PCI_CHIP_RV370_5462 0x5462 +#define PCI_CHIP_RV370_5463 0x5463 +#define PCI_CHIP_RV370_5464 0x5464 +#define PCI_CHIP_RV370_5465 0x5465 +#define PCI_CHIP_RV370_5466 0x5466 +#define PCI_CHIP_RV370_5467 0x5467 +#define PCI_CHIP_R423_UH 0x5548 +#define PCI_CHIP_R423_UI 0x5549 +#define PCI_CHIP_R423_UJ 0x554A +#define PCI_CHIP_R423_UK 0x554B +#define PCI_CHIP_R430_554C 0x554C +#define PCI_CHIP_R430_554D 0x554D +#define PCI_CHIP_R430_554E 0x554E +#define PCI_CHIP_R430_554F 0x554F +#define PCI_CHIP_R423_5550 0x5550 +#define PCI_CHIP_R423_UQ 0x5551 +#define PCI_CHIP_R423_UR 0x5552 +#define PCI_CHIP_R423_UT 0x5554 +#define PCI_CHIP_RV410_564A 0x564A +#define PCI_CHIP_RV410_564B 0x564B +#define PCI_CHIP_RV410_564F 0x564F +#define PCI_CHIP_RV410_5652 0x5652 +#define PCI_CHIP_RV410_5653 0x5653 +#define PCI_CHIP_MACH64VT 0x5654 +#define PCI_CHIP_MACH64VU 0x5655 +#define PCI_CHIP_MACH64VV 0x5656 +#define PCI_CHIP_RS300_5834 0x5834 +#define PCI_CHIP_RS300_5835 0x5835 +#define PCI_CHIP_RS300_5836 0x5836 +#define PCI_CHIP_RS300_5837 0x5837 +#define PCI_CHIP_RS480_5954 0x5954 +#define PCI_CHIP_RS480_5955 0x5955 +#define PCI_CHIP_RV280_5960 0x5960 +#define PCI_CHIP_RV280_5961 0x5961 +#define PCI_CHIP_RV280_5962 0x5962 +#define PCI_CHIP_RV280_5964 0x5964 +#define PCI_CHIP_RV280_5965 0x5965 +#define PCI_CHIP_RN50_5969 0x5969 +#define PCI_CHIP_RS482_5974 0x5974 +#define PCI_CHIP_RS482_5975 0x5975 +#define PCI_CHIP_RS400_5A41 0x5A41 +#define PCI_CHIP_RS400_5A42 0x5A42 +#define PCI_CHIP_RC410_5A61 0x5A61 +#define PCI_CHIP_RC410_5A62 0x5A62 +#define PCI_CHIP_RV370_5B60 0x5B60 +#define PCI_CHIP_RV370_5B61 0x5B61 +#define PCI_CHIP_RV370_5B62 0x5B62 +#define PCI_CHIP_RV370_5B63 0x5B63 +#define PCI_CHIP_RV370_5B64 0x5B64 +#define PCI_CHIP_RV370_5B65 0x5B65 +#define PCI_CHIP_RV370_5B66 0x5B66 +#define PCI_CHIP_RV370_5B67 0x5B67 +#define PCI_CHIP_RV280_5C61 0x5C61 +#define PCI_CHIP_RV280_5C63 0x5C63 +#define PCI_CHIP_R430_5D48 0x5D48 +#define PCI_CHIP_R430_5D49 0x5D49 +#define PCI_CHIP_R430_5D4A 0x5D4A +#define PCI_CHIP_R480_5D4C 0x5D4C +#define PCI_CHIP_R480_5D4D 0x5D4D +#define PCI_CHIP_R480_5D4E 0x5D4E +#define PCI_CHIP_R480_5D4F 0x5D4F +#define PCI_CHIP_R480_5D50 0x5D50 +#define PCI_CHIP_R480_5D52 0x5D52 +#define PCI_CHIP_R423_5D57 0x5D57 +#define PCI_CHIP_RV410_5E48 0x5E48 +#define PCI_CHIP_RV410_5E4A 0x5E4A +#define PCI_CHIP_RV410_5E4B 0x5E4B +#define PCI_CHIP_RV410_5E4C 0x5E4C +#define PCI_CHIP_RV410_5E4D 0x5E4D +#define PCI_CHIP_RV410_5E4F 0x5E4F +#define PCI_CHIP_RS350_7834 0x7834 +#define PCI_CHIP_RS350_7835 0x7835 + +/* ASPEED Technology (AST) */ +#define PCI_CHIP_AST2000 0x2000 + +/* Avance Logic */ +#define PCI_CHIP_ALG2064 0x2064 +#define PCI_CHIP_ALG2301 0x2301 +#define PCI_CHIP_ALG2501 0x2501 + +/* Tseng */ +#define PCI_CHIP_ET4000_W32P_A 0x3202 +#define PCI_CHIP_ET4000_W32P_B 0x3205 +#define PCI_CHIP_ET4000_W32P_D 0x3206 +#define PCI_CHIP_ET4000_W32P_C 0x3207 +#define PCI_CHIP_ET6000 0x3208 +#define PCI_CHIP_ET6300 0x4702 + +/* Weitek */ +#define PCI_CHIP_P9000 0x9001 +#define PCI_CHIP_P9100 0x9100 + +/* Digital */ +#define PCI_CHIP_DC21050 0x0001 +#define PCI_CHIP_DEC21030 0x0004 +#define PCI_CHIP_TGA2 0x000D + +/* Cirrus Logic */ +#define PCI_CHIP_GD7548 0x0038 +#define PCI_CHIP_GD7555 0x0040 +#define PCI_CHIP_GD5430 0x00A0 +#define PCI_CHIP_GD5434_4 0x00A4 +#define PCI_CHIP_GD5434_8 0x00A8 +#define PCI_CHIP_GD5436 0x00AC +#define PCI_CHIP_GD5446 0x00B8 +#define PCI_CHIP_GD5480 0x00BC +#define PCI_CHIP_GD5462 0x00D0 +#define PCI_CHIP_GD5464 0x00D4 +#define PCI_CHIP_GD5464BD 0x00D5 +#define PCI_CHIP_GD5465 0x00D6 +#define PCI_CHIP_6729 0x1100 +#define PCI_CHIP_6832 0x1110 +#define PCI_CHIP_GD7542 0x1200 +#define PCI_CHIP_GD7543 0x1202 +#define PCI_CHIP_GD7541 0x1204 + +/* AMD */ +#define PCI_CHIP_AMD761 0x700E + +/* Trident */ +#define PCI_CHIP_2100 0x2100 +#define PCI_CHIP_8400 0x8400 +#define PCI_CHIP_8420 0x8420 +#define PCI_CHIP_8500 0x8500 +#define PCI_CHIP_8520 0x8520 +#define PCI_CHIP_8600 0x8600 +#define PCI_CHIP_8620 0x8620 +#define PCI_CHIP_8820 0x8820 +#define PCI_CHIP_9320 0x9320 +#define PCI_CHIP_9388 0x9388 +#define PCI_CHIP_9397 0x9397 +#define PCI_CHIP_939A 0x939A +#define PCI_CHIP_9420 0x9420 +#define PCI_CHIP_9440 0x9440 +#define PCI_CHIP_9520 0x9520 +#define PCI_CHIP_9525 0x9525 +#define PCI_CHIP_9540 0x9540 +#define PCI_CHIP_9660 0x9660 +#define PCI_CHIP_9750 0x9750 +#define PCI_CHIP_9850 0x9850 +#define PCI_CHIP_9880 0x9880 +#define PCI_CHIP_9910 0x9910 + +/* ALI */ +#define PCI_CHIP_M1435 0x1435 + +/* Matrox */ +#define PCI_CHIP_MGA2085 0x0518 +#define PCI_CHIP_MGA2064 0x0519 +#define PCI_CHIP_MGA1064 0x051A +#define PCI_CHIP_MGA2164 0x051B +#define PCI_CHIP_MGA2164_AGP 0x051F +#define PCI_CHIP_MGAG200_PCI 0x0520 +#define PCI_CHIP_MGAG200 0x0521 +#define PCI_CHIP_MGAG400 0x0525 +#define PCI_CHIP_MGAG550 0x2527 +#define PCI_CHIP_IMPRESSION 0x0D10 +#define PCI_CHIP_MGAG100_PCI 0x1000 +#define PCI_CHIP_MGAG100 0x1001 + +#define PCI_CARD_G400_TH 0x2179 +#define PCI_CARD_MILL_G200_SD 0xFF00 +#define PCI_CARD_PROD_G100_SD 0xFF01 +#define PCI_CARD_MYST_G200_SD 0xFF02 +#define PCI_CARD_MILL_G200_SG 0xFF03 +#define PCI_CARD_MARV_G200_SD 0xFF04 + +/* Chips & Tech */ +#define PCI_CHIP_65545 0x00D8 +#define PCI_CHIP_65548 0x00DC +#define PCI_CHIP_65550 0x00E0 +#define PCI_CHIP_65554 0x00E4 +#define PCI_CHIP_65555 0x00E5 +#define PCI_CHIP_68554 0x00F4 +#define PCI_CHIP_69000 0x00C0 +#define PCI_CHIP_69030 0x0C30 + +/* Miro */ +#define PCI_CHIP_ZR36050 0x5601 + +/* NEC */ +#define PCI_CHIP_POWER_VR 0x0046 + +/* SiS */ +#define PCI_CHIP_SG86C201 0x0001 +#define PCI_CHIP_SG86C202 0x0002 +#define PCI_CHIP_SG85C503 0x0008 +#define PCI_CHIP_SIS5597 0x0200 +/* Agregado por Carlos Duclos & Manuel Jander */ +#define PCI_CHIP_SIS82C204 0x0204 +#define PCI_CHIP_SG86C205 0x0205 +#define PCI_CHIP_SG86C215 0x0215 +#define PCI_CHIP_SG86C225 0x0225 +#define PCI_CHIP_85C501 0x0406 +#define PCI_CHIP_85C496 0x0496 +#define PCI_CHIP_85C601 0x0601 +#define PCI_CHIP_85C5107 0x5107 +#define PCI_CHIP_85C5511 0x5511 +#define PCI_CHIP_85C5513 0x5513 +#define PCI_CHIP_SIS5571 0x5571 +#define PCI_CHIP_SIS5597_2 0x5597 +#define PCI_CHIP_SIS530 0x6306 +#define PCI_CHIP_SIS6326 0x6326 +#define PCI_CHIP_SIS7001 0x7001 +#define PCI_CHIP_SIS300 0x0300 +#define PCI_CHIP_SIS315H 0x0310 +#define PCI_CHIP_SIS315PRO 0x0325 +#define PCI_CHIP_SIS330 0x0330 +#define PCI_CHIP_SIS630 0x6300 +#define PCI_CHIP_SIS540 0x5300 +#define PCI_CHIP_SIS550 0x5315 +#define PCI_CHIP_SIS650 0x6325 +#define PCI_CHIP_SIS730 0x7300 + +/* Hewlett-Packard */ +#define PCI_CHIP_ELROY 0x1054 +#define PCI_CHIP_ZX1_SBA 0x1229 +#define PCI_CHIP_ZX1_IOC 0x122A +#define PCI_CHIP_ZX1_LBA 0x122E /* a.k.a. Mercury */ +#define PCI_CHIP_ZX1_AGP8 0x12B4 /* a.k.a. QuickSilver */ +#define PCI_CHIP_ZX2_LBA 0x12EE +#define PCI_CHIP_ZX2_SBA 0x4030 +#define PCI_CHIP_ZX2_IOC 0x4031 +#define PCI_CHIP_ZX2_PCIE 0x4037 + +/* SGS */ +#define PCI_CHIP_STG2000 0x0008 +#define PCI_CHIP_STG1764 0x0009 +#define PCI_CHIP_KYROII 0x0010 + +/* Texas Instruments */ +#define PCI_CHIP_TI_PERMEDIA 0x3D04 +#define PCI_CHIP_TI_PERMEDIA2 0x3D07 + +/* Oak */ +#define PCI_CHIP_OTI107 0x0107 + +/* Number Nine */ +#define PCI_CHIP_I128 0x2309 +#define PCI_CHIP_I128_2 0x2339 +#define PCI_CHIP_I128_T2R 0x493D +#define PCI_CHIP_I128_T2R4 0x5348 + +/* Sun */ +#define PCI_CHIP_EBUS 0x1000 +#define PCI_CHIP_HAPPY_MEAL 0x1001 +#define PCI_CHIP_SIMBA 0x5000 +#define PCI_CHIP_PSYCHO 0x8000 +#define PCI_CHIP_SCHIZO 0x8001 +#define PCI_CHIP_SABRE 0xA000 +#define PCI_CHIP_HUMMINGBIRD 0xA001 + +/* BrookTree */ +#define PCI_CHIP_BT848 0x0350 +#define PCI_CHIP_BT849 0x0351 + +/* NVIDIA */ +#define PCI_CHIP_NV1 0x0008 +#define PCI_CHIP_DAC64 0x0009 +#define PCI_CHIP_TNT 0x0020 +#define PCI_CHIP_TNT2 0x0028 +#define PCI_CHIP_UTNT2 0x0029 +#define PCI_CHIP_VTNT2 0x002C +#define PCI_CHIP_UVTNT2 0x002D +#define PCI_CHIP_ITNT2 0x00A0 +#define PCI_CHIP_GEFORCE_256 0x0100 +#define PCI_CHIP_GEFORCE_DDR 0x0101 +#define PCI_CHIP_QUADRO 0x0103 +#define PCI_CHIP_GEFORCE2_MX 0x0110 +#define PCI_CHIP_GEFORCE2_MX_100 0x0111 +#define PCI_CHIP_GEFORCE2_GO 0x0112 +#define PCI_CHIP_QUADRO2_MXR 0x0113 +#define PCI_CHIP_GEFORCE2_GTS 0x0150 +#define PCI_CHIP_GEFORCE2_TI 0x0151 +#define PCI_CHIP_GEFORCE2_ULTRA 0x0152 +#define PCI_CHIP_QUADRO2_PRO 0x0153 +#define PCI_CHIP_GEFORCE4_MX_460 0x0170 +#define PCI_CHIP_GEFORCE4_MX_440 0x0171 +#define PCI_CHIP_GEFORCE4_MX_420 0x0172 +#define PCI_CHIP_GEFORCE4_440_GO 0x0174 +#define PCI_CHIP_GEFORCE4_420_GO 0x0175 +#define PCI_CHIP_GEFORCE4_420_GO_M32 0x0176 +#define PCI_CHIP_QUADRO4_500XGL 0x0178 +#define PCI_CHIP_GEFORCE4_440_GO_M64 0x0179 +#define PCI_CHIP_QUADRO4_200 0x017A +#define PCI_CHIP_QUADRO4_550XGL 0x017B +#define PCI_CHIP_QUADRO4_500_GOGL 0x017C +#define PCI_CHIP_IGEFORCE2 0x01A0 +#define PCI_CHIP_GEFORCE3 0x0200 +#define PCI_CHIP_GEFORCE3_TI_200 0x0201 +#define PCI_CHIP_GEFORCE3_TI_500 0x0202 +#define PCI_CHIP_QUADRO_DCC 0x0203 +#define PCI_CHIP_GEFORCE4_TI_4600 0x0250 +#define PCI_CHIP_GEFORCE4_TI_4400 0x0251 +#define PCI_CHIP_GEFORCE4_TI_4200 0x0253 +#define PCI_CHIP_QUADRO4_900XGL 0x0258 +#define PCI_CHIP_QUADRO4_750XGL 0x0259 +#define PCI_CHIP_QUADRO4_700XGL 0x025B + +/* NVIDIA & SGS */ +#define PCI_CHIP_RIVA128 0x0018 + +/* IMS */ +#define PCI_CHIP_IMSTT128 0x9128 +#define PCI_CHIP_IMSTT3D 0x9135 + +/* Alliance Semiconductor */ +#define PCI_CHIP_AP6410 0x3210 +#define PCI_CHIP_AP6422 0x6422 +#define PCI_CHIP_AT24 0x6424 +#define PCI_CHIP_AT3D 0x643D + +/* 3dfx Interactive */ +#define PCI_CHIP_VOODOO_GRAPHICS 0x0001 +#define PCI_CHIP_VOODOO2 0x0002 +#define PCI_CHIP_BANSHEE 0x0003 +#define PCI_CHIP_VOODOO3 0x0005 +#define PCI_CHIP_VOODOO5 0x0009 + +#define PCI_CARD_VOODOO3_2000 0x0036 +#define PCI_CARD_VOODOO3_3000 0x003A + +/* Rendition */ +#define PCI_CHIP_V1000 0x0001 +#define PCI_CHIP_V2x00 0x2000 + +/* 3Dlabs */ +#define PCI_CHIP_300SX 0x0001 +#define PCI_CHIP_500TX 0x0002 +#define PCI_CHIP_DELTA 0x0003 +#define PCI_CHIP_PERMEDIA 0x0004 +#define PCI_CHIP_MX 0x0006 +#define PCI_CHIP_PERMEDIA2 0x0007 +#define PCI_CHIP_GAMMA 0x0008 +#define PCI_CHIP_PERMEDIA2V 0x0009 +#define PCI_CHIP_PERMEDIA3 0x000A +#define PCI_CHIP_PERMEDIA4 0x000C +#define PCI_CHIP_R4 0x000D +#define PCI_CHIP_GAMMA2 0x000E +#define PCI_CHIP_R4ALT 0x0011 + +/* S3 */ +#define PCI_CHIP_PLATO 0x0551 +#define PCI_CHIP_VIRGE 0x5631 +#define PCI_CHIP_TRIO 0x8811 +#define PCI_CHIP_AURORA64VP 0x8812 +#define PCI_CHIP_TRIO64UVP 0x8814 +#define PCI_CHIP_VIRGE_VX 0x883D +#define PCI_CHIP_868 0x8880 +#define PCI_CHIP_928 0x88B0 +#define PCI_CHIP_864_0 0x88C0 +#define PCI_CHIP_864_1 0x88C1 +#define PCI_CHIP_964_0 0x88D0 +#define PCI_CHIP_964_1 0x88D1 +#define PCI_CHIP_968 0x88F0 +#define PCI_CHIP_TRIO64V2_DXGX 0x8901 +#define PCI_CHIP_PLATO_PX 0x8902 +#define PCI_CHIP_Trio3D 0x8904 +#define PCI_CHIP_VIRGE_DXGX 0x8A01 +#define PCI_CHIP_VIRGE_GX2 0x8A10 +#define PCI_CHIP_Trio3D_2X 0x8A13 +#define PCI_CHIP_SAVAGE3D 0x8A20 +#define PCI_CHIP_SAVAGE3D_MV 0x8A21 +#define PCI_CHIP_SAVAGE4 0x8A22 +#define PCI_CHIP_PROSAVAGE_PM 0x8A25 +#define PCI_CHIP_PROSAVAGE_KM 0x8A26 +#define PCI_CHIP_VIRGE_MX 0x8C01 +#define PCI_CHIP_VIRGE_MXPLUS 0x8C02 +#define PCI_CHIP_VIRGE_MXP 0x8C03 +#define PCI_CHIP_SAVAGE_MX_MV 0x8C10 +#define PCI_CHIP_SAVAGE_MX 0x8C11 +#define PCI_CHIP_SAVAGE_IX_MV 0x8C12 +#define PCI_CHIP_SAVAGE_IX 0x8C13 +#define PCI_CHIP_SUPSAV_MX128 0x8C22 +#define PCI_CHIP_SUPSAV_MX64 0x8C24 +#define PCI_CHIP_SUPSAV_MX64C 0x8C26 +#define PCI_CHIP_SUPSAV_IX128SDR 0x8C2A +#define PCI_CHIP_SUPSAV_IX128DDR 0x8C2B +#define PCI_CHIP_SUPSAV_IX64SDR 0x8C2C +#define PCI_CHIP_SUPSAV_IX64DDR 0x8C2D +#define PCI_CHIP_SUPSAV_IXCSDR 0x8C2E +#define PCI_CHIP_SUPSAV_IXCDDR 0x8C2F +#define PCI_CHIP_S3TWISTER_P 0x8D01 +#define PCI_CHIP_S3TWISTER_K 0x8D02 +#define PCI_CHIP_PROSAVAGE_DDR 0x8D03 +#define PCI_CHIP_PROSAVAGE_DDRK 0x8D04 +#define PCI_CHIP_SAVAGE2000 0x9102 + +/* ARK Logic */ +#define PCI_CHIP_1000PV 0xA091 +#define PCI_CHIP_2000PV 0xA099 +#define PCI_CHIP_2000MT 0xA0A1 +#define PCI_CHIP_2000MI 0xA0A9 + +/* Tritech Microelectronics */ +#define PCI_CHIP_TR25202 0xFC02 + +/* Neomagic */ +#define PCI_CHIP_NM2070 0x0001 +#define PCI_CHIP_NM2090 0x0002 +#define PCI_CHIP_NM2093 0x0003 +#define PCI_CHIP_NM2097 0x0083 +#define PCI_CHIP_NM2160 0x0004 +#define PCI_CHIP_NM2200 0x0005 +#define PCI_CHIP_NM2230 0x0025 +#define PCI_CHIP_NM2360 0x0006 +#define PCI_CHIP_NM2380 0x0016 + +/* Intel */ +#define PCI_CHIP_I815_BRIDGE 0x1130 +#define PCI_CHIP_I815 0x1132 +#define PCI_CHIP_82801_P2P 0x244E +#define PCI_CHIP_845_G_BRIDGE 0x2560 +#define PCI_CHIP_845_G 0x2562 +#define PCI_CHIP_I830_M_BRIDGE 0x3575 +#define PCI_CHIP_I830_M 0x3577 +#define PCI_CHIP_I810_BRIDGE 0x7120 +#define PCI_CHIP_I810 0x7121 +#define PCI_CHIP_I810_DC100_BRIDGE 0x7122 +#define PCI_CHIP_I810_DC100 0x7123 +#define PCI_CHIP_I810_E_BRIDGE 0x7124 +#define PCI_CHIP_I810_E 0x7125 +#define PCI_CHIP_I740_AGP 0x7800 +#define PCI_CHIP_460GX_PXB 0x84CB +#define PCI_CHIP_460GX_SAC 0x84E0 +#define PCI_CHIP_460GX_GXB_2 0x84E2 /* PCI function 2 */ +#define PCI_CHIP_460GX_WXB 0x84E6 +#define PCI_CHIP_460GX_GXB_1 0x84EA /* PCI function 1 */ + +/* Silicon Motion Inc. */ +#define PCI_CHIP_SMI910 0x0910 +#define PCI_CHIP_SMI810 0x0810 +#define PCI_CHIP_SMI820 0x0820 +#define PCI_CHIP_SMI710 0x0710 +#define PCI_CHIP_SMI712 0x0712 +#define PCI_CHIP_SMI720 0x0720 +#define PCI_CHIP_SMI731 0x0730 + +/* VMware */ +#define PCI_CHIP_VMWARE0405 0x0405 +#define PCI_CHIP_VMWARE0710 0x0710 + +#endif /* _XF86_PCIINFO_H */ diff --git a/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h new file mode 100644 index 0000000..7137a53 --- /dev/null +++ b/hw/xfree86/common/xf86Priv.h @@ -0,0 +1,157 @@ +/* + * Copyright (c) 1997-2002 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * This file contains declarations for private XFree86 functions and variables, + * and definitions of private macros. + * + * "private" means not available to video drivers. + */ + +#ifndef _XF86PRIV_H +#define _XF86PRIV_H + +#include "xf86Privstr.h" +#include "propertyst.h" +#include "input.h" + +/* + * Parameters set ONLY from the command line options + * The global state of these things is held in xf86InfoRec (when appropriate). + */ +extern _X_EXPORT const char *xf86ConfigFile; +extern _X_EXPORT const char *xf86ConfigDir; +extern _X_EXPORT Bool xf86AllowMouseOpenFail; +#ifdef XF86VIDMODE +extern _X_EXPORT Bool xf86VidModeDisabled; +extern _X_EXPORT Bool xf86VidModeAllowNonLocal; +#endif +extern _X_EXPORT Bool xf86fpFlag; +extern _X_EXPORT Bool xf86sFlag; +extern _X_EXPORT Bool xf86bsEnableFlag; +extern _X_EXPORT Bool xf86bsDisableFlag; +extern _X_EXPORT Bool xf86silkenMouseDisableFlag; +extern _X_EXPORT Bool xf86xkbdirFlag; +#ifdef HAVE_ACPI +extern _X_EXPORT Bool xf86acpiDisableFlag; +#endif +extern _X_EXPORT char *xf86LayoutName; +extern _X_EXPORT char *xf86ScreenName; +extern _X_EXPORT char *xf86PointerName; +extern _X_EXPORT char *xf86KeyboardName; +extern _X_EXPORT int xf86FbBpp; +extern _X_EXPORT int xf86Depth; +extern _X_EXPORT Pix24Flags xf86Pix24; +extern _X_EXPORT rgb xf86Weight; +extern _X_EXPORT Bool xf86FlipPixels; +extern _X_EXPORT Gamma xf86Gamma; +extern _X_EXPORT char *xf86ServerName; + +/* Other parameters */ + +extern _X_EXPORT xf86InfoRec xf86Info; +extern _X_EXPORT const char *xf86ModulePath; +extern _X_EXPORT MessageType xf86ModPathFrom; +extern _X_EXPORT const char *xf86LogFile; +extern _X_EXPORT MessageType xf86LogFileFrom; +extern _X_EXPORT Bool xf86LogFileWasOpened; +extern _X_EXPORT serverLayoutRec xf86ConfigLayout; + +extern _X_EXPORT DriverPtr *xf86DriverList; +extern _X_EXPORT int xf86NumDrivers; +extern _X_EXPORT Bool xf86Resetting; +extern _X_EXPORT Bool xf86Initialising; +extern _X_EXPORT int xf86NumScreens; +extern _X_EXPORT const char *xf86VisualNames[]; +extern _X_EXPORT int xf86Verbose; /* verbosity level */ +extern _X_EXPORT int xf86LogVerbose; /* log file verbosity level */ +extern _X_EXPORT Bool xorgHWAccess; + +extern _X_EXPORT RootWinPropPtr *xf86RegisteredPropertiesTable; + +#ifndef DEFAULT_VERBOSE +#define DEFAULT_VERBOSE 0 +#endif +#ifndef DEFAULT_LOG_VERBOSE +#define DEFAULT_LOG_VERBOSE 3 +#endif +#ifndef DEFAULT_DPI +#define DEFAULT_DPI 96 +#endif + +/* Function Prototypes */ +#ifndef _NO_XF86_PROTOTYPES + +/* xf86Bus.c */ +extern _X_EXPORT Bool xf86BusConfig(void); +extern _X_EXPORT void xf86BusProbe(void); +extern _X_EXPORT void xf86AccessEnter(void); +extern _X_EXPORT void xf86AccessLeave(void); +extern _X_EXPORT void xf86PostProbe(void); +extern _X_EXPORT void xf86ClearEntityListForScreen(int scrnIndex); +extern _X_EXPORT void xf86AddDevToEntity(int entityIndex, GDevPtr dev); + +/* xf86Config.c */ + +extern _X_EXPORT Bool xf86PathIsSafe(const char *path); + +/* xf86DefaultModes */ + +extern _X_EXPORT const DisplayModeRec xf86DefaultModes[]; +extern _X_EXPORT const int xf86NumDefaultModes; + +/* xf86Configure.c */ +extern _X_EXPORT void DoConfigure(void); + +/* xf86ShowOpts.c */ +extern _X_EXPORT void DoShowOptions(void); + +/* xf86Events.c */ + +extern _X_EXPORT void xf86Wakeup(pointer blockData, int err, pointer pReadmask); +extern _X_HIDDEN int xf86SigWrapper(int signo); +extern _X_EXPORT void xf86HandlePMEvents(int fd, pointer data); +extern _X_EXPORT int (*xf86PMGetEventFromOs)(int fd,pmEvent *events,int num); +extern _X_EXPORT pmWait (*xf86PMConfirmEventToOs)(int fd,pmEvent event); + +/* xf86Helper.c */ +extern _X_EXPORT void xf86LogInit(void); +extern _X_EXPORT void xf86CloseLog(void); + +/* xf86Init.c */ +extern _X_EXPORT Bool xf86LoadModules(char **list, pointer *optlist); +extern _X_EXPORT int xf86SetVerbosity(int verb); +extern _X_EXPORT int xf86SetLogVerbosity(int verb); +extern _X_EXPORT Bool xf86CallDriverProbe( struct _DriverRec * drv, Bool detect_only ); + +/* xf86Xinput.c */ +extern _X_EXPORT EventList *xf86Events; + +#endif /* _NO_XF86_PROTOTYPES */ + + +#endif /* _XF86PRIV_H */ diff --git a/hw/xfree86/common/xf86Privstr.h b/hw/xfree86/common/xf86Privstr.h new file mode 100644 index 0000000..608f9bd --- /dev/null +++ b/hw/xfree86/common/xf86Privstr.h @@ -0,0 +1,168 @@ + +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * This file contains definitions of the private XFree86 data structures/types. + * None of the data structures here should be used by video drivers. + */ + +#ifndef _XF86PRIVSTR_H +#define _XF86PRIVSTR_H + +#include "xf86str.h" + +typedef enum { + LogNone, + LogFlush, + LogSync +} Log; + +typedef enum { + XF86_GlxVisualsMinimal, + XF86_GlxVisualsTypical, + XF86_GlxVisualsAll, +} XF86_GlxVisuals; + +/* + * xf86InfoRec contains global parameters which the video drivers never + * need to access. Global parameters which the video drivers do need + * should be individual globals. + */ + +typedef struct { + int consoleFd; + int vtno; + Bool vtSysreq; + + /* event handler part */ + int lastEventTime; + Bool vtRequestsPending; +#ifdef sun + int vtPendingNum; +#endif + Bool dontVTSwitch; + Bool dontZap; + Bool dontZoom; + Bool notrapSignals; /* don't exit cleanly - die at fault */ + Bool caughtSignal; + + /* graphics part */ + ScreenPtr currentScreen; +#if defined(CSRG_BASED) || defined(__FreeBSD_kernel__) + int screenFd; /* fd for memory mapped access to + * vga card */ + int consType; /* Which console driver? */ +#endif + + /* Other things */ + Bool allowMouseOpenFail; + Bool vidModeEnabled; /* VidMode extension enabled */ + Bool vidModeAllowNonLocal; /* allow non-local VidMode + * connections */ + Bool miscModInDevEnabled; /* Allow input devices to be + * changed */ + Bool miscModInDevAllowNonLocal; + Bool useSIGIO; /* Use SIGIO for handling + input device events */ + Pix24Flags pixmap24; + MessageType pix24From; +#ifdef SUPPORT_PC98 + Bool pc98; +#endif + Bool pmFlag; + Log log; + Bool disableRandR; + MessageType randRFrom; + Bool aiglx; + MessageType aiglxFrom; + XF86_GlxVisuals glxVisuals; + MessageType glxVisualsFrom; + + Bool useDefaultFontPath; + MessageType useDefaultFontPathFrom; + Bool ignoreABI; + + Bool forceInputDevices; /* force xorg.conf or built-in input devices */ + Bool autoAddDevices; /* Whether to succeed NIDR, or ignore. */ + Bool autoEnableDevices; /* Whether to enable, or let the client + * control. */ + + Bool dri2; + MessageType dri2From; +} xf86InfoRec, *xf86InfoPtr; + +#ifdef DPMSExtension +/* Private info for DPMS */ +typedef struct { + CloseScreenProcPtr CloseScreen; + Bool Enabled; + int Flags; +} DPMSRec, *DPMSPtr; +#endif + +#ifdef XF86VIDMODE +/* Private info for Video Mode Extentsion */ +typedef struct { + DisplayModePtr First; + DisplayModePtr Next; + int Flags; + CloseScreenProcPtr CloseScreen; +} VidModeRec, *VidModePtr; +#endif + +/* Information for root window properties. */ +typedef struct _RootWinProp { + struct _RootWinProp * next; + char * name; + Atom type; + short format; + long size; + pointer data; +} RootWinProp, *RootWinPropPtr; + +/* ISC's cc can't handle ~ of UL constants, so explicitly type cast them. */ +#define XLED1 ((unsigned long) 0x00000001) +#define XLED2 ((unsigned long) 0x00000002) +#define XLED3 ((unsigned long) 0x00000004) +#define XLED4 ((unsigned long) 0x00000008) +#define XCAPS ((unsigned long) 0x20000000) +#define XNUM ((unsigned long) 0x40000000) +#define XSCR ((unsigned long) 0x80000000) +#define XCOMP ((unsigned long) 0x00008000) + +/* BSD console driver types (consType) */ +#if defined(CSRG_BASED) || defined(__FreeBSD_kernel__) +#define PCCONS 0 +#define CODRV011 1 +#define CODRV01X 2 +#define SYSCONS 8 +#define PCVT 16 +#define WSCONS 32 +#endif + +#endif /* _XF86PRIVSTR_H */ diff --git a/hw/xfree86/common/xf86RandR.c b/hw/xfree86/common/xf86RandR.c new file mode 100644 index 0000000..d7ffff4 --- /dev/null +++ b/hw/xfree86/common/xf86RandR.c @@ -0,0 +1,462 @@ +/* + * + * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <X11/X.h> +#include "os.h" +#include "globals.h" +#include "xf86.h" +#include "xf86str.h" +#include "xf86Priv.h" +#include "xf86DDC.h" +#include "mipointer.h" +#include <randrstr.h> +#include "inputstr.h" + +typedef struct _xf86RandRInfo { + CreateScreenResourcesProcPtr CreateScreenResources; + CloseScreenProcPtr CloseScreen; + int virtualX; + int virtualY; + int mmWidth; + int mmHeight; + Rotation rotation; +} XF86RandRInfoRec, *XF86RandRInfoPtr; + +static DevPrivateKeyRec xf86RandRKeyRec; +static DevPrivateKey xf86RandRKey; + +#define XF86RANDRINFO(p) ((XF86RandRInfoPtr)dixLookupPrivate(&(p)->devPrivates, xf86RandRKey)) + +static int +xf86RandRModeRefresh (DisplayModePtr mode) +{ + if (mode->VRefresh) + return (int) (mode->VRefresh + 0.5); + else if (mode->Clock == 0) + return 0; + else + return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5); +} + +static Bool +xf86RandRGetInfo (ScreenPtr pScreen, Rotation *rotations) +{ + RRScreenSizePtr pSize; + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + DisplayModePtr mode; + int refresh0 = 60; + xorgRRModeMM RRModeMM; + + *rotations = RR_Rotate_0; + + for (mode = scrp->modes; mode != NULL ; mode = mode->next) + { + int refresh = xf86RandRModeRefresh (mode); + + if (mode == scrp->modes) + refresh0 = refresh; + + RRModeMM.mode = mode; + RRModeMM.virtX = randrp->virtualX; + RRModeMM.virtY = randrp->virtualY; + RRModeMM.mmWidth = randrp->mmWidth; + RRModeMM.mmHeight = randrp->mmHeight; + + if(scrp->DriverFunc) { + (*scrp->DriverFunc)(scrp, RR_GET_MODE_MM, &RRModeMM); + } + + pSize = RRRegisterSize (pScreen, + mode->HDisplay, mode->VDisplay, + RRModeMM.mmWidth, RRModeMM.mmHeight); + if (!pSize) + return FALSE; + RRRegisterRate (pScreen, pSize, refresh); + if (mode == scrp->currentMode && + mode->HDisplay == scrp->virtualX && mode->VDisplay == scrp->virtualY) + RRSetCurrentConfig (pScreen, randrp->rotation, refresh, pSize); + if (mode->next == scrp->modes) + break; + } + if (scrp->currentMode->HDisplay != randrp->virtualX || + scrp->currentMode->VDisplay != randrp->virtualY) + { + mode = scrp->modes; + + RRModeMM.mode = NULL; + RRModeMM.virtX = randrp->virtualX; + RRModeMM.virtY = randrp->virtualY; + RRModeMM.mmWidth = randrp->mmWidth; + RRModeMM.mmHeight = randrp->mmHeight; + + if(scrp->DriverFunc) { + (*scrp->DriverFunc)(scrp, RR_GET_MODE_MM, &RRModeMM); + } + + pSize = RRRegisterSize (pScreen, + randrp->virtualX, randrp->virtualY, + RRModeMM.mmWidth, RRModeMM.mmHeight); + if (!pSize) + return FALSE; + RRRegisterRate (pScreen, pSize, refresh0); + if (scrp->virtualX == randrp->virtualX && + scrp->virtualY == randrp->virtualY) + { + RRSetCurrentConfig (pScreen, randrp->rotation, refresh0, pSize); + } + } + + /* If there is driver support for randr, let it set our supported rotations */ + if(scrp->DriverFunc) { + xorgRRRotation RRRotation; + + RRRotation.RRRotations = *rotations; + if (!(*scrp->DriverFunc)(scrp, RR_GET_INFO, &RRRotation)) + return TRUE; + *rotations = RRRotation.RRRotations; + } + + return TRUE; +} + +static Bool +xf86RandRSetMode (ScreenPtr pScreen, + DisplayModePtr mode, + Bool useVirtual, + int mmWidth, + int mmHeight) +{ + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + int oldWidth = pScreen->width; + int oldHeight = pScreen->height; + int oldmmWidth = pScreen->mmWidth; + int oldmmHeight = pScreen->mmHeight; + int oldVirtualX = scrp->virtualX; + int oldVirtualY = scrp->virtualY; + WindowPtr pRoot = pScreen->root; + Bool ret = TRUE; + + if (pRoot && scrp->vtSema) + (*scrp->EnableDisableFBAccess) (pScreen->myNum, FALSE); + if (useVirtual) + { + scrp->virtualX = randrp->virtualX; + scrp->virtualY = randrp->virtualY; + } + else + { + scrp->virtualX = mode->HDisplay; + scrp->virtualY = mode->VDisplay; + } + + /* + * The DIX forgets the physical dimensions we passed into RRRegisterSize, so + * reconstruct them if possible. + */ + if(scrp->DriverFunc) { + xorgRRModeMM RRModeMM; + + RRModeMM.mode = mode; + RRModeMM.virtX = scrp->virtualX; + RRModeMM.virtY = scrp->virtualY; + RRModeMM.mmWidth = mmWidth; + RRModeMM.mmHeight = mmHeight; + + (*scrp->DriverFunc)(scrp, RR_GET_MODE_MM, &RRModeMM); + + mmWidth = RRModeMM.mmWidth; + mmHeight = RRModeMM.mmHeight; + } + if(randrp->rotation & (RR_Rotate_90 | RR_Rotate_270)) + { + /* If the screen is rotated 90 or 270 degrees, swap the sizes. */ + pScreen->width = scrp->virtualY; + pScreen->height = scrp->virtualX; + pScreen->mmWidth = mmHeight; + pScreen->mmHeight = mmWidth; + } + else + { + pScreen->width = scrp->virtualX; + pScreen->height = scrp->virtualY; + pScreen->mmWidth = mmWidth; + pScreen->mmHeight = mmHeight; + } + if (!xf86SwitchMode (pScreen, mode)) + { + pScreen->width = oldWidth; + pScreen->height = oldHeight; + pScreen->mmWidth = oldmmWidth; + pScreen->mmHeight = oldmmHeight; + scrp->virtualX = oldVirtualX; + scrp->virtualY = oldVirtualY; + ret = FALSE; + } + /* + * Make sure the layout is correct + */ + xf86ReconfigureLayout(); + + /* + * Make sure the whole screen is visible + */ + xf86SetViewport (pScreen, pScreen->width, pScreen->height); + xf86SetViewport (pScreen, 0, 0); + if (pRoot && scrp->vtSema) + (*scrp->EnableDisableFBAccess) (pScreen->myNum, TRUE); + return ret; +} + +static Bool +xf86RandRSetConfig (ScreenPtr pScreen, + Rotation rotation, + int rate, + RRScreenSizePtr pSize) +{ + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + DisplayModePtr mode; + int px, py; + Bool useVirtual = FALSE; + Rotation oldRotation = randrp->rotation; + + miPointerGetPosition(inputInfo.pointer, &px, &py); + for (mode = scrp->modes; ; mode = mode->next) + { + if (mode->HDisplay == pSize->width && + mode->VDisplay == pSize->height && + (rate == 0 || xf86RandRModeRefresh (mode) == rate)) + break; + if (mode->next == scrp->modes) + { + if (pSize->width == randrp->virtualX && + pSize->height == randrp->virtualY) + { + mode = scrp->modes; + useVirtual = TRUE; + break; + } + return FALSE; + } + } + + if (randrp->rotation != rotation) { + + /* Have the driver do its thing. */ + if (scrp->DriverFunc) { + xorgRRRotation RRRotation; + RRRotation.RRConfig.rotation = rotation; + RRRotation.RRConfig.rate = rate; + RRRotation.RRConfig.width = pSize->width; + RRRotation.RRConfig.height = pSize->height; + + /* + * Currently we need to rely on HW support for rotation. + */ + if (!(*scrp->DriverFunc)(scrp, RR_SET_CONFIG, &RRRotation)) + return FALSE; + } else + return FALSE; + + randrp->rotation = rotation; + } + + if (!xf86RandRSetMode (pScreen, mode, useVirtual, pSize->mmWidth, pSize->mmHeight)) { + if(randrp->rotation != oldRotation) { + /* Have the driver undo its thing. */ + if (scrp->DriverFunc) { + xorgRRRotation RRRotation; + RRRotation.RRConfig.rotation = oldRotation; + RRRotation.RRConfig.rate = xf86RandRModeRefresh (scrp->currentMode); + RRRotation.RRConfig.width = scrp->virtualX; + RRRotation.RRConfig.height = scrp->virtualY; + (*scrp->DriverFunc)(scrp, RR_SET_CONFIG, &RRRotation); + } + + randrp->rotation = oldRotation; + } + return FALSE; + } + /* + * Move the cursor back where it belongs; SwitchMode repositions it + */ + if (pScreen == miPointerCurrentScreen ()) + { + px = (px >= pScreen->width ? (pScreen->width - 1) : px); + py = (py >= pScreen->height ? (pScreen->height - 1) : py); + + xf86SetViewport(pScreen, px, py); + + (*pScreen->SetCursorPosition) (inputInfo.pointer, pScreen, px, py, FALSE); + } + + return TRUE; +} + +/* + * Wait until the screen is initialized before whacking the + * sizes around; otherwise the screen pixmap will be allocated + * at the current mode size rather than the maximum size + */ +static Bool +xf86RandRCreateScreenResources (ScreenPtr pScreen) +{ + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); +#if 0 + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + DisplayModePtr mode; +#endif + + pScreen->CreateScreenResources = randrp->CreateScreenResources; + if (!(*pScreen->CreateScreenResources) (pScreen)) + return FALSE; + +#if 0 + mode = scrp->currentMode; + if (mode) + xf86RandRSetMode (pScreen, mode, TRUE); +#endif + + return TRUE; +} + +/* + * Reset size back to original + */ +static Bool +xf86RandRCloseScreen (int index, ScreenPtr pScreen) +{ + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + + scrp->virtualX = pScreen->width = randrp->virtualX; + scrp->virtualY = pScreen->height = randrp->virtualY; + scrp->currentMode = scrp->modes; + pScreen->CloseScreen = randrp->CloseScreen; + free(randrp); + dixSetPrivate(&pScreen->devPrivates, xf86RandRKey, NULL); + return (*pScreen->CloseScreen) (index, pScreen); +} + +Rotation +xf86GetRotation(ScreenPtr pScreen) +{ + if (xf86RandRKey == NULL) + return RR_Rotate_0; + + return XF86RANDRINFO(pScreen)->rotation; +} + +/* Function to change RandR's idea of the virtual screen size */ +Bool +xf86RandRSetNewVirtualAndDimensions(ScreenPtr pScreen, + int newvirtX, int newvirtY, int newmmWidth, int newmmHeight, + Bool resetMode) +{ + XF86RandRInfoPtr randrp; + + if (xf86RandRKey == NULL) + return FALSE; + + randrp = XF86RANDRINFO(pScreen); + if (randrp == NULL) + return FALSE; + + if (newvirtX > 0) + randrp->virtualX = newvirtX; + + if (newvirtY > 0) + randrp->virtualY = newvirtY; + + if (newmmWidth > 0) + randrp->mmWidth = newmmWidth; + + if (newmmHeight > 0) + randrp->mmHeight = newmmHeight; + + /* This is only for during server start */ + if (resetMode) { + return (xf86RandRSetMode(pScreen, + XF86SCRNINFO(pScreen)->currentMode, + TRUE, + pScreen->mmWidth, pScreen->mmHeight)); + } + + return TRUE; +} + +Bool +xf86RandRInit (ScreenPtr pScreen) +{ + rrScrPrivPtr rp; + XF86RandRInfoPtr randrp; + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + +#ifdef PANORAMIX + /* XXX disable RandR when using Xinerama */ + if (!noPanoramiXExtension) + return TRUE; +#endif + + xf86RandRKey = &xf86RandRKeyRec; + + if (!dixRegisterPrivateKey(&xf86RandRKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + randrp = malloc(sizeof (XF86RandRInfoRec)); + if (!randrp) + return FALSE; + + if (!RRScreenInit (pScreen)) + { + free(randrp); + return FALSE; + } + rp = rrGetScrPriv(pScreen); + rp->rrGetInfo = xf86RandRGetInfo; + rp->rrSetConfig = xf86RandRSetConfig; + + randrp->virtualX = scrp->virtualX; + randrp->virtualY = scrp->virtualY; + randrp->mmWidth = pScreen->mmWidth; + randrp->mmHeight = pScreen->mmHeight; + + randrp->CreateScreenResources = pScreen->CreateScreenResources; + pScreen->CreateScreenResources = xf86RandRCreateScreenResources; + + randrp->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = xf86RandRCloseScreen; + + randrp->rotation = RR_Rotate_0; + + dixSetPrivate(&pScreen->devPrivates, xf86RandRKey, randrp); + return TRUE; +} + + diff --git a/hw/xfree86/common/xf86ShowOpts.c b/hw/xfree86/common/xf86ShowOpts.c new file mode 100644 index 0000000..c0fa80a --- /dev/null +++ b/hw/xfree86/common/xf86ShowOpts.c @@ -0,0 +1,130 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86ShopwOpts.c,v 3.80 2003/10/08 14:58:27 dawes Exp $ */ +/* + * Copyright 2000-2002 by Alan Hourihane, Flint Mountain, North Wales. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Alan Hourihane not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Alan Hourihane makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Author: Marcus Schaefer, ms@suse.de + * + */ + +#include <ctype.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <X11/X.h> +#include <X11/Xmd.h> +#include "os.h" +#ifdef XFree86LOADER +#include "loaderProcs.h" +#endif +#include "xf86.h" +#include "xf86Config.h" +#include "xf86_OSlib.h" +#include "xf86Priv.h" +/* #include "xf86PciData.h" */ +#define IN_XSERVER +#include "xf86Parser.h" +#include "xf86tokens.h" +#include "Configint.h" +#include "xf86DDC.h" +#if defined(__sparc__) && !defined(__OpenBSD__) +#include "xf86Bus.h" +#include "xf86Sbus.h" +#endif +#include "globals.h" + +static const char* +optionTypeToSting(OptionValueType type) +{ + switch (type) { + case OPTV_NONE: + return ""; + case OPTV_INTEGER: + return "<int>"; + case OPTV_STRING: + return "<str>"; + case OPTV_ANYSTR: + return "<str>"; + case OPTV_REAL: + return "<real>"; + case OPTV_BOOLEAN: + return "<bool>"; + case OPTV_FREQ: + return "<freq>"; + case OPTV_PERCENT: + return "<percent>"; + default: + return "<undef>"; + } +} + +void DoShowOptions (void) { + int i = 0; + char **vlist = 0; + char *pSymbol = 0; + XF86ModuleData *initData = 0; + if (! (vlist = xf86DriverlistFromCompile())) { + ErrorF("Missing output drivers\n"); + goto bail; + } + xf86LoadModules (vlist,0); + free(vlist); + for (i = 0; i < xf86NumDrivers; i++) { + if (xf86DriverList[i]->AvailableOptions) { + OptionInfoPtr pOption = (OptionInfoPtr)(*xf86DriverList[i]->AvailableOptions)(0,0); + if (! pOption) { + ErrorF ("(EE) Couldn't read option table for %s driver\n", + xf86DriverList[i]->driverName + ); + continue; + } + XNFasprintf(&pSymbol, "%sModuleData", + xf86DriverList[i]->driverName); + initData = LoaderSymbol (pSymbol); + if (initData) { + XF86ModuleVersionInfo *vers = initData->vers; + OptionInfoPtr p; + ErrorF ("Driver[%d]:%s[%s] {\n", + i,xf86DriverList[i]->driverName,vers->vendor + ); + for (p = pOption; p->name != NULL; p++) { + const char *opttype = optionTypeToSting(p->type); + /* XXX: Why overallocate by 2 bytes? + * Otherwise, this would be strdup() + */ + char *optname = malloc(strlen(p->name) + 2 + 1); + if (!optname) { + continue; + } + sprintf(optname, "%s", p->name); + ErrorF ("\t%s:%s\n", optname,opttype); + } + ErrorF ("}\n"); + } + } + } + bail: + OsCleanup (TRUE); + AbortDDX (); + fflush (stderr); + exit (0); +} diff --git a/hw/xfree86/common/xf86VGAarbiter.c b/hw/xfree86/common/xf86VGAarbiter.c new file mode 100644 index 0000000..215e845 --- /dev/null +++ b/hw/xfree86/common/xf86VGAarbiter.c @@ -0,0 +1,1127 @@ +/* + * This code was stolen from RAC and adapted to control the legacy vga + * interface. + * + * + * Copyright (c) 2007 Paulo R. Zanoni, Tiago Vignatti + * + * 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, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS 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. + * + */ + +#include "xorg-config.h" + +#include "xf86VGAarbiter.h" + +#ifdef HAVE_PCI_DEVICE_VGAARB_INIT +#include "xf86VGAarbiterPriv.h" +#include "xf86Bus.h" +#include "xf86Priv.h" +#include "pciaccess.h" + + +static GCFuncs VGAarbiterGCFuncs = { + VGAarbiterValidateGC, VGAarbiterChangeGC, VGAarbiterCopyGC, + VGAarbiterDestroyGC, VGAarbiterChangeClip, VGAarbiterDestroyClip, + VGAarbiterCopyClip +}; + +static GCOps VGAarbiterGCOps = { + VGAarbiterFillSpans, VGAarbiterSetSpans, VGAarbiterPutImage, + VGAarbiterCopyArea, VGAarbiterCopyPlane, VGAarbiterPolyPoint, + VGAarbiterPolylines, VGAarbiterPolySegment, VGAarbiterPolyRectangle, + VGAarbiterPolyArc, VGAarbiterFillPolygon, VGAarbiterPolyFillRect, + VGAarbiterPolyFillArc, VGAarbiterPolyText8, VGAarbiterPolyText16, + VGAarbiterImageText8, VGAarbiterImageText16, VGAarbiterImageGlyphBlt, + VGAarbiterPolyGlyphBlt, VGAarbiterPushPixels, +}; + +static miPointerSpriteFuncRec VGAarbiterSpriteFuncs = { + VGAarbiterSpriteRealizeCursor, VGAarbiterSpriteUnrealizeCursor, + VGAarbiterSpriteSetCursor, VGAarbiterSpriteMoveCursor, + VGAarbiterDeviceCursorInitialize, VGAarbiterDeviceCursorCleanup +}; + +static DevPrivateKeyRec VGAarbiterScreenKeyRec; +#define VGAarbiterScreenKey (&VGAarbiterScreenKeyRec) +static DevPrivateKeyRec VGAarbiterGCKeyRec; +#define VGAarbiterGCKey (&VGAarbiterGCKeyRec) + +static int vga_no_arb = 0; +void +xf86VGAarbiterInit(void) +{ + if (pci_device_vgaarb_init() != 0) { + vga_no_arb = 1; + xf86Msg(X_WARNING, "VGA arbiter: cannot open kernel arbiter, no multi-card support\n"); + } +} + +void +xf86VGAarbiterFini(void) +{ + if (vga_no_arb) + return; + pci_device_vgaarb_fini(); +} + +void +xf86VGAarbiterLock(ScrnInfoPtr pScrn) +{ + if (vga_no_arb) + return; + pci_device_vgaarb_set_target(pScrn->vgaDev); + pci_device_vgaarb_lock(); +} + +void +xf86VGAarbiterUnlock(ScrnInfoPtr pScrn) +{ + if (vga_no_arb) + return; + pci_device_vgaarb_unlock(); +} + +Bool xf86VGAarbiterAllowDRI(ScreenPtr pScreen) +{ + int vga_count; + int rsrc_decodes; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + if (vga_no_arb) + return TRUE; + + pci_device_vgaarb_get_info(pScrn->vgaDev, &vga_count, &rsrc_decodes); + if (vga_count > 1) { + if (rsrc_decodes) { + return FALSE; + } + } + return TRUE; +} + +void +xf86VGAarbiterScrnInit(ScrnInfoPtr pScrn) +{ + struct pci_device *dev; + EntityPtr pEnt; + + if (vga_no_arb) + return; + + pEnt = xf86Entities[pScrn->entityList[0]]; + if (pEnt->bus.type != BUS_PCI) + return; + + dev = pEnt->bus.id.pci; + pScrn->vgaDev = dev; +} + +void +xf86VGAarbiterDeviceDecodes(ScrnInfoPtr pScrn, int rsrc) +{ + if (vga_no_arb) + return; + pci_device_vgaarb_set_target(pScrn->vgaDev); + pci_device_vgaarb_decodes(rsrc); +} + +Bool +xf86VGAarbiterWrapFunctions(void) +{ + ScrnInfoPtr pScrn; + VGAarbiterScreenPtr pScreenPriv; + miPointerScreenPtr PointPriv; + PictureScreenPtr ps; + ScreenPtr pScreen; + int vga_count, i; + + if (vga_no_arb) + return FALSE; + + /* + * we need to wrap the arbiter if we have more than + * one VGA card - hotplug cries. + */ + pci_device_vgaarb_get_info(NULL, &vga_count, NULL); + if (vga_count < 2 || !xf86Screens) + return FALSE; + + xf86Msg(X_INFO,"Found %d VGA devices: arbiter wrapping enabled\n", + vga_count); + + for (i = 0; i < xf86NumScreens; i++) { + pScreen = xf86Screens[i]->pScreen; + ps = GetPictureScreenIfSet(pScreen); + pScrn = xf86Screens[pScreen->myNum]; + PointPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); + + if (!dixRegisterPrivateKey(&VGAarbiterGCKeyRec, PRIVATE_GC, sizeof(VGAarbiterGCRec))) + return FALSE; + + if (!dixRegisterPrivateKey(&VGAarbiterScreenKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + if (!(pScreenPriv = malloc(sizeof(VGAarbiterScreenRec)))) + return FALSE; + + dixSetPrivate(&pScreen->devPrivates, VGAarbiterScreenKey, pScreenPriv); + + WRAP_SCREEN(CloseScreen, VGAarbiterCloseScreen); + WRAP_SCREEN(SaveScreen, VGAarbiterSaveScreen); + WRAP_SCREEN(WakeupHandler, VGAarbiterWakeupHandler); + WRAP_SCREEN(BlockHandler, VGAarbiterBlockHandler); + WRAP_SCREEN(CreateGC, VGAarbiterCreateGC); + WRAP_SCREEN(GetImage, VGAarbiterGetImage); + WRAP_SCREEN(GetSpans, VGAarbiterGetSpans); + WRAP_SCREEN(SourceValidate, VGAarbiterSourceValidate); + WRAP_SCREEN(CopyWindow, VGAarbiterCopyWindow); + WRAP_SCREEN(ClearToBackground, VGAarbiterClearToBackground); + WRAP_SCREEN(CreatePixmap, VGAarbiterCreatePixmap); + WRAP_SCREEN(StoreColors, VGAarbiterStoreColors); + WRAP_SCREEN(DisplayCursor, VGAarbiterDisplayCursor); + WRAP_SCREEN(RealizeCursor, VGAarbiterRealizeCursor); + WRAP_SCREEN(UnrealizeCursor, VGAarbiterUnrealizeCursor); + WRAP_SCREEN(RecolorCursor, VGAarbiterRecolorCursor); + WRAP_SCREEN(SetCursorPosition, VGAarbiterSetCursorPosition); + WRAP_PICT(Composite,VGAarbiterComposite); + WRAP_PICT(Glyphs,VGAarbiterGlyphs); + WRAP_PICT(CompositeRects,VGAarbiterCompositeRects); + WRAP_SCREEN_INFO(AdjustFrame, VGAarbiterAdjustFrame); + WRAP_SCREEN_INFO(SwitchMode, VGAarbiterSwitchMode); + WRAP_SCREEN_INFO(EnterVT, VGAarbiterEnterVT); + WRAP_SCREEN_INFO(LeaveVT, VGAarbiterLeaveVT); + WRAP_SCREEN_INFO(FreeScreen, VGAarbiterFreeScreen); + WRAP_SPRITE; + } + + return TRUE; +} + +/* Screen funcs */ +static Bool +VGAarbiterCloseScreen (int i, ScreenPtr pScreen) +{ + Bool val; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, VGAarbiterScreenKey); + miPointerScreenPtr PointPriv = (miPointerScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, miPointerScreenKey); + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + + UNWRAP_SCREEN(CreateGC); + UNWRAP_SCREEN(CloseScreen); + UNWRAP_SCREEN(GetImage); + UNWRAP_SCREEN(GetSpans); + UNWRAP_SCREEN(SourceValidate); + UNWRAP_SCREEN(CopyWindow); + UNWRAP_SCREEN(ClearToBackground); + UNWRAP_SCREEN(SaveScreen); + UNWRAP_SCREEN(StoreColors); + UNWRAP_SCREEN(DisplayCursor); + UNWRAP_SCREEN(RealizeCursor); + UNWRAP_SCREEN(UnrealizeCursor); + UNWRAP_SCREEN(RecolorCursor); + UNWRAP_SCREEN(SetCursorPosition); + UNWRAP_PICT(Composite); + UNWRAP_PICT(Glyphs); + UNWRAP_PICT(CompositeRects); + UNWRAP_SCREEN_INFO(AdjustFrame); + UNWRAP_SCREEN_INFO(SwitchMode); + UNWRAP_SCREEN_INFO(EnterVT); + UNWRAP_SCREEN_INFO(LeaveVT); + UNWRAP_SCREEN_INFO(FreeScreen); + UNWRAP_SPRITE; + + free((pointer) pScreenPriv); + xf86VGAarbiterLock(xf86Screens[i]); + val = (*pScreen->CloseScreen) (i, pScreen); + xf86VGAarbiterUnlock(xf86Screens[i]); + return val; +} + +static void +VGAarbiterBlockHandler(int i, + pointer blockData, pointer pTimeout, pointer pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[i]; + SCREEN_PROLOG(BlockHandler); + VGAGet(pScreen); + pScreen->BlockHandler(i, blockData, pTimeout, pReadmask); + VGAPut(); + SCREEN_EPILOG(BlockHandler, VGAarbiterBlockHandler); +} + +static void +VGAarbiterWakeupHandler(int i, pointer blockData, unsigned long result, pointer pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[i]; + SCREEN_PROLOG(WakeupHandler); + VGAGet(pScreen); + pScreen->WakeupHandler(i, blockData, result, pReadmask); + VGAPut(); + SCREEN_EPILOG(WakeupHandler, VGAarbiterWakeupHandler); +} + +static void +VGAarbiterGetImage ( + DrawablePtr pDrawable, + int sx, int sy, int w, int h, + unsigned int format, + unsigned long planemask, + char *pdstLine + ) +{ + ScreenPtr pScreen = pDrawable->pScreen; + SCREEN_PROLOG(GetImage); +// if (xf86Screens[pScreen->myNum]->vtSema) { + VGAGet(pScreen); +// } + (*pScreen->GetImage) (pDrawable, sx, sy, w, h, + format, planemask, pdstLine); + VGAPut(); + SCREEN_EPILOG (GetImage, VGAarbiterGetImage); +} + +static void +VGAarbiterGetSpans ( + DrawablePtr pDrawable, + int wMax, + DDXPointPtr ppt, + int *pwidth, + int nspans, + char *pdstStart + ) +{ + ScreenPtr pScreen = pDrawable->pScreen; + + SCREEN_PROLOG (GetSpans); + VGAGet(pScreen); + (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); + VGAPut(); + SCREEN_EPILOG (GetSpans, VGAarbiterGetSpans); +} + +static void +VGAarbiterSourceValidate ( + DrawablePtr pDrawable, + int x, int y, int width, int height, + unsigned int subWindowMode ) +{ + ScreenPtr pScreen = pDrawable->pScreen; + SCREEN_PROLOG (SourceValidate); + VGAGet(pScreen); + if (pScreen->SourceValidate) + (*pScreen->SourceValidate) (pDrawable, x, y, width, height, subWindowMode); + VGAPut(); + SCREEN_EPILOG (SourceValidate, VGAarbiterSourceValidate); +} + +static void +VGAarbiterCopyWindow( + WindowPtr pWin, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc ) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + SCREEN_PROLOG (CopyWindow); + VGAGet(pScreen); + (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc); + VGAPut(); + SCREEN_EPILOG (CopyWindow, VGAarbiterCopyWindow); +} + +static void +VGAarbiterClearToBackground ( + WindowPtr pWin, + int x, int y, + int w, int h, + Bool generateExposures ) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + SCREEN_PROLOG ( ClearToBackground); + VGAGet(pScreen); + (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures); + VGAPut(); + SCREEN_EPILOG (ClearToBackground, VGAarbiterClearToBackground); +} + +static PixmapPtr +VGAarbiterCreatePixmap(ScreenPtr pScreen, int w, int h, int depth, unsigned usage_hint) +{ + PixmapPtr pPix; + + SCREEN_PROLOG ( CreatePixmap); + VGAGet(pScreen); + pPix = (*pScreen->CreatePixmap) (pScreen, w, h, depth, usage_hint); + VGAPut(); + SCREEN_EPILOG (CreatePixmap, VGAarbiterCreatePixmap); + + return pPix; +} + +static Bool +VGAarbiterSaveScreen(ScreenPtr pScreen, Bool unblank) +{ + Bool val; + + SCREEN_PROLOG (SaveScreen); + VGAGet(pScreen); + val = (*pScreen->SaveScreen) (pScreen, unblank); + VGAPut(); + SCREEN_EPILOG (SaveScreen, VGAarbiterSaveScreen); + + return val; +} + +static void +VGAarbiterStoreColors ( + ColormapPtr pmap, + int ndef, + xColorItem *pdefs) +{ + ScreenPtr pScreen = pmap->pScreen; + + SCREEN_PROLOG (StoreColors); + VGAGet(pScreen); + (*pScreen->StoreColors) (pmap,ndef,pdefs); + VGAPut(); + SCREEN_EPILOG ( StoreColors, VGAarbiterStoreColors); +} + +static void +VGAarbiterRecolorCursor ( + DeviceIntPtr pDev, + ScreenPtr pScreen, + CursorPtr pCurs, + Bool displayed + ) +{ + SCREEN_PROLOG (RecolorCursor); + VGAGet(pScreen); + (*pScreen->RecolorCursor) (pDev, pScreen, pCurs, displayed); + VGAPut(); + SCREEN_EPILOG ( RecolorCursor, VGAarbiterRecolorCursor); +} + +static Bool +VGAarbiterRealizeCursor ( + DeviceIntPtr pDev, + ScreenPtr pScreen, + CursorPtr pCursor + ) +{ + Bool val; + + SCREEN_PROLOG (RealizeCursor); + VGAGet(pScreen); + val = (*pScreen->RealizeCursor) (pDev, pScreen,pCursor); + VGAPut(); + SCREEN_EPILOG ( RealizeCursor, VGAarbiterRealizeCursor); + return val; +} + +static Bool +VGAarbiterUnrealizeCursor ( + DeviceIntPtr pDev, + ScreenPtr pScreen, + CursorPtr pCursor + ) +{ + Bool val; + + SCREEN_PROLOG (UnrealizeCursor); + VGAGet(pScreen); + val = (*pScreen->UnrealizeCursor) (pDev, pScreen, pCursor); + VGAPut(); + SCREEN_EPILOG ( UnrealizeCursor, VGAarbiterUnrealizeCursor); + return val; +} + +static Bool +VGAarbiterDisplayCursor ( + DeviceIntPtr pDev, + ScreenPtr pScreen, + CursorPtr pCursor + ) +{ + Bool val; + + SCREEN_PROLOG (DisplayCursor); + VGAGet(pScreen); + val = (*pScreen->DisplayCursor) (pDev, pScreen, pCursor); + VGAPut(); + SCREEN_EPILOG ( DisplayCursor, VGAarbiterDisplayCursor); + return val; +} + +static Bool +VGAarbiterSetCursorPosition ( + DeviceIntPtr pDev, + ScreenPtr pScreen, + int x, int y, + Bool generateEvent) +{ + Bool val; + + SCREEN_PROLOG (SetCursorPosition); + VGAGet(pScreen); + val = (*pScreen->SetCursorPosition) (pDev, pScreen, x, y, generateEvent); + VGAPut(); + SCREEN_EPILOG ( SetCursorPosition, VGAarbiterSetCursorPosition); + return val; +} + +static void +VGAarbiterAdjustFrame(int index, int x, int y, int flags) +{ + ScreenPtr pScreen = screenInfo.screens[index]; + VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, VGAarbiterScreenKey); + + VGAGet(pScreen); + (*pScreenPriv->AdjustFrame)(index, x, y, flags); + VGAPut(); +} + +static Bool +VGAarbiterSwitchMode(int index, DisplayModePtr mode, int flags) +{ + Bool val; + ScreenPtr pScreen = screenInfo.screens[index]; + VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, VGAarbiterScreenKey); + + VGAGet(pScreen); + val = (*pScreenPriv->SwitchMode)(index, mode, flags); + VGAPut(); + return val; +} + +static Bool +VGAarbiterEnterVT(int index, int flags) +{ + Bool val; + ScrnInfoPtr pScrn = xf86Screens[index]; + ScreenPtr pScreen = screenInfo.screens[index]; + VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, VGAarbiterScreenKey); + + VGAGet(pScreen); + pScrn->EnterVT = pScreenPriv->EnterVT; + val = (*pScrn->EnterVT)(index, flags); + pScreenPriv->EnterVT = pScrn->EnterVT; + pScrn->EnterVT = VGAarbiterEnterVT; + VGAPut(); + return val; +} + +static void +VGAarbiterLeaveVT(int index, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[index]; + ScreenPtr pScreen = screenInfo.screens[index]; + VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, VGAarbiterScreenKey); + + VGAGet(pScreen); + pScrn->LeaveVT = pScreenPriv->LeaveVT; + (*pScreenPriv->LeaveVT)(index, flags); + pScreenPriv->LeaveVT = pScrn->LeaveVT; + pScrn->LeaveVT = VGAarbiterLeaveVT; + VGAPut(); +} + +static void +VGAarbiterFreeScreen(int index, int flags) +{ + ScreenPtr pScreen = screenInfo.screens[index]; + VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, VGAarbiterScreenKey); + + VGAGet(pScreen); + (*pScreenPriv->FreeScreen)(index, flags); + VGAPut(); +} + +static Bool +VGAarbiterCreateGC(GCPtr pGC) +{ + ScreenPtr pScreen = pGC->pScreen; + VGAarbiterGCPtr pGCPriv = (VGAarbiterGCPtr)dixLookupPrivate(&pGC->devPrivates, VGAarbiterGCKey); + Bool ret; + + SCREEN_PROLOG(CreateGC); + ret = (*pScreen->CreateGC)(pGC); + GC_WRAP(pGC); + SCREEN_EPILOG(CreateGC,VGAarbiterCreateGC); + + return ret; +} + +/* GC funcs */ +static void +VGAarbiterValidateGC( + GCPtr pGC, + unsigned long changes, + DrawablePtr pDraw ) +{ + GC_UNWRAP(pGC); + (*pGC->funcs->ValidateGC)(pGC, changes, pDraw); + GC_WRAP(pGC); +} + + +static void +VGAarbiterDestroyGC(GCPtr pGC) +{ + GC_UNWRAP (pGC); + (*pGC->funcs->DestroyGC)(pGC); + GC_WRAP (pGC); +} + +static void +VGAarbiterChangeGC ( + GCPtr pGC, + unsigned long mask) +{ + GC_UNWRAP (pGC); + (*pGC->funcs->ChangeGC) (pGC, mask); + GC_WRAP (pGC); +} + +static void +VGAarbiterCopyGC ( + GCPtr pGCSrc, + unsigned long mask, + GCPtr pGCDst) +{ + GC_UNWRAP (pGCDst); + (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); + GC_WRAP (pGCDst); +} + +static void +VGAarbiterChangeClip ( + GCPtr pGC, + int type, + pointer pvalue, + int nrects ) +{ + GC_UNWRAP (pGC); + (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); + GC_WRAP (pGC); +} + +static void +VGAarbiterCopyClip(GCPtr pgcDst, GCPtr pgcSrc) +{ + GC_UNWRAP (pgcDst); + (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); + GC_WRAP (pgcDst); +} + +static void +VGAarbiterDestroyClip(GCPtr pGC) +{ + GC_UNWRAP (pGC); + (* pGC->funcs->DestroyClip)(pGC); + GC_WRAP (pGC); +} + +/* GC Ops */ +static void +VGAarbiterFillSpans( + DrawablePtr pDraw, + GC *pGC, + int nInit, + DDXPointPtr pptInit, + int *pwidthInit, + int fSorted ) +{ + ScreenPtr pScreen = pGC->pScreen; + GC_UNWRAP(pGC); + VGAGet(pScreen); + (*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted); + VGAPut(); + GC_WRAP(pGC); +} + +static void +VGAarbiterSetSpans( + DrawablePtr pDraw, + GCPtr pGC, + char *pcharsrc, + register DDXPointPtr ppt, + int *pwidth, + int nspans, + int fSorted ) +{ + ScreenPtr pScreen = pGC->pScreen; + GC_UNWRAP(pGC); + VGAGet(pScreen); + (*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, ppt, pwidth, nspans, fSorted); + VGAPut(); + GC_WRAP(pGC); +} + +static void +VGAarbiterPutImage( + DrawablePtr pDraw, + GCPtr pGC, + int depth, + int x, int y, int w, int h, + int leftPad, + int format, + char *pImage ) +{ + ScreenPtr pScreen = pGC->pScreen; + GC_UNWRAP(pGC); + VGAGet(pScreen); + (*pGC->ops->PutImage)(pDraw, pGC, depth, x, y, w, h, + leftPad, format, pImage); + VGAPut(); + GC_WRAP(pGC); +} + +static RegionPtr +VGAarbiterCopyArea( + DrawablePtr pSrc, + DrawablePtr pDst, + GC *pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty ) +{ + RegionPtr ret; + ScreenPtr pScreen = pGC->pScreen; + GC_UNWRAP(pGC); + VGAGet(pScreen); + ret = (*pGC->ops->CopyArea)(pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty); + VGAPut(); + GC_WRAP(pGC); + return ret; +} + +static RegionPtr +VGAarbiterCopyPlane( + DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty, + unsigned long bitPlane ) +{ + RegionPtr ret; + ScreenPtr pScreen = pGC->pScreen; + GC_UNWRAP(pGC); + VGAGet(pScreen); + ret = (*pGC->ops->CopyPlane)(pSrc, pDst, pGC, srcx, srcy, + width, height, dstx, dsty, bitPlane); + VGAPut(); + GC_WRAP(pGC); + return ret; +} + +static void +VGAarbiterPolyPoint( + DrawablePtr pDraw, + GCPtr pGC, + int mode, + int npt, + xPoint *pptInit ) +{ + ScreenPtr pScreen = pGC->pScreen; + GC_UNWRAP(pGC); + VGAGet(pScreen); + (*pGC->ops->PolyPoint)(pDraw, pGC, mode, npt, pptInit); + VGAPut(); + GC_WRAP(pGC); +} + + +static void +VGAarbiterPolylines( + DrawablePtr pDraw, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr pptInit ) +{ + ScreenPtr pScreen = pGC->pScreen; + GC_UNWRAP(pGC); + VGAGet(pScreen); + (*pGC->ops->Polylines)(pDraw, pGC, mode, npt, pptInit); + VGAPut(); + GC_WRAP(pGC); +} + +static void +VGAarbiterPolySegment( + DrawablePtr pDraw, + GCPtr pGC, + int nseg, + xSegment *pSeg ) +{ + ScreenPtr pScreen = pGC->pScreen; + GC_UNWRAP(pGC); + VGAGet(pScreen); + (*pGC->ops->PolySegment)(pDraw, pGC, nseg, pSeg); + VGAPut(); + GC_WRAP(pGC); +} + +static void +VGAarbiterPolyRectangle( + DrawablePtr pDraw, + GCPtr pGC, + int nRectsInit, + xRectangle *pRectsInit ) +{ + ScreenPtr pScreen = pGC->pScreen; + GC_UNWRAP(pGC); + VGAGet(pScreen); + (*pGC->ops->PolyRectangle)(pDraw, pGC, nRectsInit, pRectsInit); + VGAPut(); + GC_WRAP(pGC); +} + +static void +VGAarbiterPolyArc( + DrawablePtr pDraw, + GCPtr pGC, + int narcs, + xArc *parcs ) +{ + ScreenPtr pScreen = pGC->pScreen; + GC_UNWRAP(pGC); + VGAGet(pScreen); + (*pGC->ops->PolyArc)(pDraw, pGC, narcs, parcs); + VGAPut(); + GC_WRAP(pGC); +} + +static void +VGAarbiterFillPolygon( + DrawablePtr pDraw, + GCPtr pGC, + int shape, + int mode, + int count, + DDXPointPtr ptsIn ) +{ + ScreenPtr pScreen = pGC->pScreen; + GC_UNWRAP(pGC); + VGAGet(pScreen); + (*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, ptsIn); + VGAPut(); + GC_WRAP(pGC); +} + +static void +VGAarbiterPolyFillRect( + DrawablePtr pDraw, + GCPtr pGC, + int nrectFill, + xRectangle *prectInit) +{ + ScreenPtr pScreen = pGC->pScreen; + GC_UNWRAP(pGC); + VGAGet(pScreen); + (*pGC->ops->PolyFillRect)(pDraw, pGC, nrectFill, prectInit); + VGAPut(); + GC_WRAP(pGC); +} + +static void +VGAarbiterPolyFillArc( + DrawablePtr pDraw, + GCPtr pGC, + int narcs, + xArc *parcs ) +{ + ScreenPtr pScreen = pGC->pScreen; + GC_UNWRAP(pGC); + VGAGet(pScreen); + (*pGC->ops->PolyFillArc)(pDraw, pGC, narcs, parcs); + VGAPut(); + GC_WRAP(pGC); +} + +static int +VGAarbiterPolyText8( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + char *chars ) +{ + int ret; + ScreenPtr pScreen = pGC->pScreen; + GC_UNWRAP(pGC); + VGAGet(pScreen); + ret = (*pGC->ops->PolyText8)(pDraw, pGC, x, y, count, chars); + VGAPut(); + GC_WRAP(pGC); + return ret; +} + +static int +VGAarbiterPolyText16( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars ) +{ + int ret; + ScreenPtr pScreen = pGC->pScreen; + GC_UNWRAP(pGC); + VGAGet(pScreen); + ret = (*pGC->ops->PolyText16)(pDraw, pGC, x, y, count, chars); + VGAPut(); + GC_WRAP(pGC); + return ret; +} + +static void +VGAarbiterImageText8( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + char *chars ) +{ + ScreenPtr pScreen = pGC->pScreen; + GC_UNWRAP(pGC); + VGAGet(pScreen); + (*pGC->ops->ImageText8)(pDraw, pGC, x, y, count, chars); + VGAPut(); + GC_WRAP(pGC); +} + +static void +VGAarbiterImageText16( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars ) +{ + ScreenPtr pScreen = pGC->pScreen; + GC_UNWRAP(pGC); + VGAGet(pScreen); + (*pGC->ops->ImageText16)(pDraw, pGC, x, y, count, chars); + VGAPut(); + GC_WRAP(pGC); +} + + +static void +VGAarbiterImageGlyphBlt( + DrawablePtr pDraw, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase ) +{ + ScreenPtr pScreen = pGC->pScreen; + GC_UNWRAP(pGC); + VGAGet(pScreen); + (*pGC->ops->ImageGlyphBlt)(pDraw, pGC, xInit, yInit, + nglyph, ppci, pglyphBase); + VGAPut(); + GC_WRAP(pGC); +} + +static void +VGAarbiterPolyGlyphBlt( + DrawablePtr pDraw, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase ) +{ + ScreenPtr pScreen = pGC->pScreen; + GC_UNWRAP(pGC); + VGAGet(pScreen); + (*pGC->ops->PolyGlyphBlt)(pDraw, pGC, xInit, yInit, + nglyph, ppci, pglyphBase); + VGAPut(); + GC_WRAP(pGC); +} + +static void +VGAarbiterPushPixels( + GCPtr pGC, + PixmapPtr pBitMap, + DrawablePtr pDraw, + int dx, int dy, int xOrg, int yOrg ) +{ + ScreenPtr pScreen = pGC->pScreen; + GC_UNWRAP(pGC); + VGAGet(pScreen); + (*pGC->ops->PushPixels)(pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg); + VGAPut(); + GC_WRAP(pGC); +} + + +/* miSpriteFuncs */ +static Bool +VGAarbiterSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCur) +{ + Bool val; + SPRITE_PROLOG; + VGAGet(pScreen); + val = PointPriv->spriteFuncs->RealizeCursor(pDev, pScreen, pCur); + VGAPut(); + SPRITE_EPILOG; + return val; +} + +static Bool +VGAarbiterSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCur) +{ + Bool val; + SPRITE_PROLOG; + VGAGet(pScreen); + val = PointPriv->spriteFuncs->UnrealizeCursor(pDev, pScreen, pCur); + VGAPut(); + SPRITE_EPILOG; + return val; +} + +static void +VGAarbiterSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCur, int x, int y) +{ + SPRITE_PROLOG; + VGAGet(pScreen); + PointPriv->spriteFuncs->SetCursor(pDev, pScreen, pCur, x, y); + VGAPut(); + SPRITE_EPILOG; +} + +static void +VGAarbiterSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ + SPRITE_PROLOG; + VGAGet(pScreen); + PointPriv->spriteFuncs->MoveCursor(pDev, pScreen, x, y); + VGAPut(); + SPRITE_EPILOG; +} + +static Bool +VGAarbiterDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + Bool val; + SPRITE_PROLOG; + VGAGet(pScreen); + val = PointPriv->spriteFuncs->DeviceCursorInitialize(pDev, pScreen); + VGAPut(); + SPRITE_EPILOG; + return val; +} + +static void +VGAarbiterDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + SPRITE_PROLOG; + VGAGet(pScreen); + PointPriv->spriteFuncs->DeviceCursorCleanup(pDev, pScreen); + VGAPut(); + SPRITE_EPILOG; +} + +static void +VGAarbiterComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, + PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, + INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, + CARD16 height) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + + PICTURE_PROLOGUE(Composite); + + VGAGet(pScreen); + (*ps->Composite) (op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, + yDst, width, height); + VGAPut(); + PICTURE_EPILOGUE(Composite, VGAarbiterComposite); +} + +static void +VGAarbiterGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlist, + GlyphListPtr list, GlyphPtr *glyphs) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + + PICTURE_PROLOGUE(Glyphs); + + VGAGet(pScreen); + (*ps->Glyphs)(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); + VGAPut(); + PICTURE_EPILOGUE (Glyphs, VGAarbiterGlyphs); +} + +static void +VGAarbiterCompositeRects(CARD8 op, PicturePtr pDst, xRenderColor *color, int nRect, + xRectangle *rects) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + + PICTURE_PROLOGUE(CompositeRects); + + VGAGet(pScreen); + (*ps->CompositeRects)(op, pDst, color, nRect, rects); + VGAPut(); + PICTURE_EPILOGUE (CompositeRects, VGAarbiterCompositeRects); +} +#else +/* dummy functions */ +void xf86VGAarbiterInit(void) {} +void xf86VGAarbiterFini(void) {} + +void xf86VGAarbiterLock(ScrnInfoPtr pScrn) {} +void xf86VGAarbiterUnlock(ScrnInfoPtr pScrn) {} +Bool xf86VGAarbiterAllowDRI(ScreenPtr pScreen) { return TRUE; } +void xf86VGAarbiterScrnInit(ScrnInfoPtr pScrn) {} +void xf86VGAarbiterDeviceDecodes(ScrnInfoPtr pScrn, int rsrc) {} +Bool xf86VGAarbiterWrapFunctions(void) { return FALSE; } + +#endif diff --git a/hw/xfree86/common/xf86VGAarbiter.h b/hw/xfree86/common/xf86VGAarbiter.h new file mode 100644 index 0000000..de104a9 --- /dev/null +++ b/hw/xfree86/common/xf86VGAarbiter.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2009 Tiago Vignatti + * + * 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, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS 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. + */ + +#ifndef __XF86VGAARBITER_H +#define __XF86VGAARBITER_H + +#include "screenint.h" +#include "misc.h" +#include "xf86.h" + +/* Functions */ +extern void xf86VGAarbiterInit(void); +extern void xf86VGAarbiterFini(void); +void xf86VGAarbiterScrnInit(ScrnInfoPtr pScrn); +extern Bool xf86VGAarbiterWrapFunctions(void); +extern void xf86VGAarbiterLock(ScrnInfoPtr pScrn); +extern void xf86VGAarbiterUnlock(ScrnInfoPtr pScrn); + +/* allow a driver to remove itself from arbiter - really should be + * done in the kernel though */ +extern _X_EXPORT void xf86VGAarbiterDeviceDecodes(ScrnInfoPtr pScrn, int rsrc); +/* DRI and arbiter are really not possible together, + * you really want to remove the card from arbitration if you can */ +extern _X_EXPORT Bool xf86VGAarbiterAllowDRI(ScreenPtr pScreen); + +#endif /* __XF86VGAARBITER_H */ diff --git a/hw/xfree86/common/xf86VGAarbiterPriv.h b/hw/xfree86/common/xf86VGAarbiterPriv.h new file mode 100644 index 0000000..848e45d --- /dev/null +++ b/hw/xfree86/common/xf86VGAarbiterPriv.h @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2009 Tiago Vignatti + * + * 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, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS 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. + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" +#include <X11/X.h> +#include "colormapst.h" +#include "scrnintstr.h" +#include "screenint.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "pixmap.h" +#include "windowstr.h" +#include "window.h" +#include "xf86str.h" +#include "mipointer.h" +#include "mipointrst.h" +# include "picturestr.h" + + +#define WRAP_SCREEN(x,y) {pScreenPriv->x = pScreen->x; pScreen->x = y;} + +#define UNWRAP_SCREEN(x) pScreen->x = pScreenPriv->x + +#define SCREEN_PROLOG(x) pScreen->x = ((VGAarbiterScreenPtr) \ + dixLookupPrivate(&(pScreen)->devPrivates, VGAarbiterScreenKey))->x + +#define SCREEN_EPILOG(x,y) pScreen->x = y; + +#define WRAP_PICT(x,y) if (ps) {pScreenPriv->x = ps->x;\ + ps->x = y;} + +#define UNWRAP_PICT(x) if (ps) {ps->x = pScreenPriv->x;} + +#define PICTURE_PROLOGUE(field) ps->field = \ + ((VGAarbiterScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, \ + VGAarbiterScreenKey))->field + +#define PICTURE_EPILOGUE(field, wrap) ps->field = wrap + +#define WRAP_SCREEN_INFO(x,y) do {pScreenPriv->x = pScrn->x; pScrn->x = y;} while(0) + +#define UNWRAP_SCREEN_INFO(x) pScrn->x = pScreenPriv->x + +#define SPRITE_PROLOG miPointerScreenPtr PointPriv = \ + (miPointerScreenPtr)dixLookupPrivate(&pScreen->devPrivates, \ + miPointerScreenKey); VGAarbiterScreenPtr pScreenPriv = \ + ((VGAarbiterScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, \ + VGAarbiterScreenKey)); PointPriv->spriteFuncs = pScreenPriv->miSprite; + +#define SPRITE_EPILOG pScreenPriv->miSprite = PointPriv->spriteFuncs;\ + PointPriv->spriteFuncs = &VGAarbiterSpriteFuncs; + +#define WRAP_SPRITE do { pScreenPriv->miSprite = PointPriv->spriteFuncs;\ + PointPriv->spriteFuncs = &VGAarbiterSpriteFuncs; \ + } while (0) + +#define UNWRAP_SPRITE PointPriv->spriteFuncs = pScreenPriv->miSprite + +#define GC_WRAP(x) pGCPriv->wrapOps = (x)->ops;\ + pGCPriv->wrapFuncs = (x)->funcs; (x)->ops = &VGAarbiterGCOps;\ + (x)->funcs = &VGAarbiterGCFuncs; + +#define GC_UNWRAP(x) VGAarbiterGCPtr pGCPriv = \ + (VGAarbiterGCPtr)dixLookupPrivate(&(x)->devPrivates, VGAarbiterGCKey);\ + (x)->ops = pGCPriv->wrapOps; (x)->funcs = pGCPriv->wrapFuncs; + +static inline void +VGAGet(ScreenPtr pScreen) { + pci_device_vgaarb_set_target(xf86Screens[pScreen->myNum]->vgaDev); + pci_device_vgaarb_lock(); +} + +static inline void +VGAPut(void) { + pci_device_vgaarb_unlock(); +} + +typedef struct _VGAarbiterScreen { + CreateGCProcPtr CreateGC; + CloseScreenProcPtr CloseScreen; + ScreenBlockHandlerProcPtr BlockHandler; + ScreenWakeupHandlerProcPtr WakeupHandler; + GetImageProcPtr GetImage; + GetSpansProcPtr GetSpans; + SourceValidateProcPtr SourceValidate; + CopyWindowProcPtr CopyWindow; + ClearToBackgroundProcPtr ClearToBackground; + CreatePixmapProcPtr CreatePixmap; + SaveScreenProcPtr SaveScreen; + /* Colormap */ + StoreColorsProcPtr StoreColors; + /* Cursor */ + DisplayCursorProcPtr DisplayCursor; + RealizeCursorProcPtr RealizeCursor; + UnrealizeCursorProcPtr UnrealizeCursor; + RecolorCursorProcPtr RecolorCursor; + SetCursorPositionProcPtr SetCursorPosition; + void (*AdjustFrame)(int,int,int,int); + Bool (*SwitchMode)(int, DisplayModePtr,int); + Bool (*EnterVT)(int, int); + void (*LeaveVT)(int, int); + void (*FreeScreen)(int, int); + miPointerSpriteFuncPtr miSprite; + CompositeProcPtr Composite; + GlyphsProcPtr Glyphs; + CompositeRectsProcPtr CompositeRects; +} VGAarbiterScreenRec, *VGAarbiterScreenPtr; + +typedef struct _VGAarbiterGC { + GCOps *wrapOps; + GCFuncs *wrapFuncs; +} VGAarbiterGCRec, *VGAarbiterGCPtr; + +/* Screen funcs */ +static void VGAarbiterBlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask); +static void VGAarbiterWakeupHandler(int i, pointer blockData, unsigned long result, pointer pReadmask); +static Bool VGAarbiterCloseScreen (int i, ScreenPtr pScreen); +static void VGAarbiterGetImage (DrawablePtr pDrawable, int sx, int sy, int w, + int h, unsigned int format, unsigned long planemask, char *pdstLine); +static void VGAarbiterGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr + ppt, int *pwidth, int nspans, char *pdstStart); +static void VGAarbiterSourceValidate (DrawablePtr pDrawable, int x, int y, + int width, int height, unsigned int subWindowMode); +static void VGAarbiterCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, + RegionPtr prgnSrc); +static void VGAarbiterClearToBackground (WindowPtr pWin, int x, int y, int w, + int h, Bool generateExposures); +static PixmapPtr VGAarbiterCreatePixmap(ScreenPtr pScreen, int w, int h, + int depth, unsigned int usage_hint); +static Bool VGAarbiterCreateGC(GCPtr pGC); +static Bool VGAarbiterSaveScreen(ScreenPtr pScreen, Bool unblank); +static void VGAarbiterStoreColors (ColormapPtr pmap, int ndef, xColorItem + *pdefs); +static void VGAarbiterRecolorCursor (DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCurs, Bool displayed); +static Bool VGAarbiterRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static Bool VGAarbiterUnrealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static Bool VGAarbiterDisplayCursor (DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static Bool VGAarbiterSetCursorPosition (DeviceIntPtr pDev, ScreenPtr + pScreen, int x, int y, Bool generateEvent); +static void VGAarbiterAdjustFrame(int index, int x, int y, int flags); +static Bool VGAarbiterSwitchMode(int index, DisplayModePtr mode, int flags); +static Bool VGAarbiterEnterVT(int index, int flags); +static void VGAarbiterLeaveVT(int index, int flags); +static void VGAarbiterFreeScreen(int index, int flags); + +/* GC funcs */ +static void VGAarbiterValidateGC(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw); +static void VGAarbiterChangeGC(GCPtr pGC, unsigned long mask); +static void VGAarbiterCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst); +static void VGAarbiterDestroyGC(GCPtr pGC); +static void VGAarbiterChangeClip(GCPtr pGC, int type, pointer pvalue, + int nrects); +static void VGAarbiterDestroyClip(GCPtr pGC); +static void VGAarbiterCopyClip(GCPtr pgcDst, GCPtr pgcSrc); + +/* GC ops */ +static void VGAarbiterFillSpans( DrawablePtr pDraw, GC *pGC, int nInit, + DDXPointPtr pptInit, int *pwidthInit, int fSorted); +static void VGAarbiterSetSpans(DrawablePtr pDraw, GCPtr pGC, char *pcharsrc, + register DDXPointPtr ppt, int *pwidth, int nspans, int fSorted); +static void VGAarbiterPutImage(DrawablePtr pDraw, GCPtr pGC, int depth, + int x, int y, int w, int h, int leftPad, int format, char *pImage); +static RegionPtr VGAarbiterCopyArea(DrawablePtr pSrc, DrawablePtr pDst, + GC *pGC, int srcx, int srcy, int width, int height, int dstx, int dsty); +static RegionPtr VGAarbiterCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, + GCPtr pGC, int srcx, int srcy, int width, int height, int dstx, int dsty, + unsigned long bitPlane); +static void VGAarbiterPolyPoint(DrawablePtr pDraw, GCPtr pGC, int mode, + int npt, xPoint *pptInit); +static void VGAarbiterPolylines(DrawablePtr pDraw, GCPtr pGC, int mode, + int npt, DDXPointPtr pptInit); +static void VGAarbiterPolySegment(DrawablePtr pDraw, GCPtr pGC, int nseg, + xSegment *pSeg); +static void VGAarbiterPolyRectangle(DrawablePtr pDraw, GCPtr pGC, + int nRectsInit, xRectangle *pRectsInit); +static void VGAarbiterPolyArc(DrawablePtr pDraw, GCPtr pGC, int narcs, + xArc *parcs); +static void VGAarbiterFillPolygon(DrawablePtr pDraw, GCPtr pGC, int shape, + int mode, int count, DDXPointPtr ptsIn); +static void VGAarbiterPolyFillRect( DrawablePtr pDraw, GCPtr pGC, + int nrectFill, xRectangle *prectInit); +static void VGAarbiterPolyFillArc(DrawablePtr pDraw, GCPtr pGC, int narcs, + xArc *parcs); +static int VGAarbiterPolyText8(DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, char *chars); +static int VGAarbiterPolyText16(DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, unsigned short *chars); +static void VGAarbiterImageText8(DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, char *chars); +static void VGAarbiterImageText16(DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, unsigned short *chars); +static void VGAarbiterImageGlyphBlt(DrawablePtr pDraw, GCPtr pGC, int xInit, + int yInit, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase); +static void VGAarbiterPolyGlyphBlt(DrawablePtr pDraw, GCPtr pGC, int xInit, + int yInit, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase); +static void VGAarbiterPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr + pDraw, int dx, int dy, int xOrg, int yOrg); + +/* miSpriteFuncs */ +static Bool VGAarbiterSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr + pScreen, CursorPtr pCur); +static Bool VGAarbiterSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr + pScreen, CursorPtr pCur); +static void VGAarbiterSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCur, int x, int y); +static void VGAarbiterSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y); +static Bool VGAarbiterDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen); +static void VGAarbiterDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen); + + +static void VGAarbiterComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, + PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height); +static void VGAarbiterGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlist, GlyphListPtr + list, GlyphPtr *glyphs); +static void VGAarbiterCompositeRects(CARD8 op, PicturePtr pDst, xRenderColor + *color, int nRect, xRectangle *rects); diff --git a/hw/xfree86/common/xf86VidMode.c b/hw/xfree86/common/xf86VidMode.c new file mode 100644 index 0000000..4dd454d --- /dev/null +++ b/hw/xfree86/common/xf86VidMode.c @@ -0,0 +1,669 @@ +/* + * Copyright (c) 1999-2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * This file contains the VidMode functions required by the extension. + * These have been added to avoid the need for the higher level extension + * code to access the private XFree86 data structures directly. Wherever + * possible this code uses the functions in xf86Mode.c to do the work, + * so that two version of code that do similar things don't have to be + * maintained. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <X11/X.h> +#include "os.h" +#include "xf86.h" +#include "xf86Priv.h" + +#ifdef XF86VIDMODE +#include "vidmodeproc.h" +#include "xf86cmap.h" + +static DevPrivateKeyRec VidModeKeyRec; +static DevPrivateKey VidModeKey; +static int VidModeCount = 0; +static Bool VidModeClose(int i, ScreenPtr pScreen); + +#define VMPTR(p) ((VidModePtr)dixLookupPrivate(&(p)->devPrivates, VidModeKey)) + +#endif + +Bool +VidModeExtensionInit(ScreenPtr pScreen) +{ +#ifdef XF86VIDMODE + VidModePtr pVidMode; + + if (!xf86GetVidModeEnabled()) { + DebugF("!xf86GetVidModeEnabled()\n"); + return FALSE; + } + + VidModeKey = &VidModeKeyRec; + + if (!dixRegisterPrivateKey(&VidModeKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + pVidMode = calloc(sizeof(VidModeRec), 1); + if (!pVidMode) + return FALSE; + + dixSetPrivate(&pScreen->devPrivates, VidModeKey, pVidMode); + + pVidMode->Flags = 0; + pVidMode->Next = NULL; + pVidMode->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = VidModeClose; + VidModeCount++; + return TRUE; +#else + DebugF("no vidmode extension\n"); + return FALSE; +#endif +} + + +#ifdef XF86VIDMODE + +static Bool +VidModeClose(int i, ScreenPtr pScreen) +{ + VidModePtr pVidMode = VMPTR(pScreen); + + /* This shouldn't happen */ + if (!pVidMode) + return FALSE; + + pScreen->CloseScreen = pVidMode->CloseScreen; + + if (--VidModeCount == 0) { + free(dixLookupPrivate(&pScreen->devPrivates, VidModeKey)); + dixSetPrivate(&pScreen->devPrivates, VidModeKey, NULL); + VidModeKey = NULL; + } + return pScreen->CloseScreen(i, pScreen); +} + +Bool +VidModeAvailable(int scrnIndex) +{ + ScrnInfoPtr pScrn; + VidModePtr pVidMode; + + if (VidModeKey == NULL) { + DebugF("VidModeKey == NULL\n"); + return FALSE; + } + + pScrn = xf86Screens[scrnIndex]; + if (pScrn == NULL) { + DebugF("pScrn == NULL\n"); + return FALSE; + } + + pVidMode = VMPTR(pScrn->pScreen); + if (pVidMode) + return TRUE; + else { + DebugF("pVidMode == NULL\n"); + return FALSE; + } +} + +Bool +VidModeGetCurrentModeline(int scrnIndex, pointer *mode, int *dotClock) +{ + ScrnInfoPtr pScrn; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + + if (pScrn->currentMode) { + *mode = (pointer)(pScrn->currentMode); + *dotClock = pScrn->currentMode->Clock; + + return TRUE; + } + return FALSE; +} + +int +VidModeGetDotClock(int scrnIndex, int Clock) +{ + ScrnInfoPtr pScrn; + + if (!VidModeAvailable(scrnIndex)) + return 0; + + pScrn = xf86Screens[scrnIndex]; + if ((pScrn->progClock) || (Clock >= MAXCLOCKS)) + return Clock; + else + return pScrn->clock[Clock]; +} + +int +VidModeGetNumOfClocks(int scrnIndex, Bool *progClock) +{ + ScrnInfoPtr pScrn; + + if (!VidModeAvailable(scrnIndex)) + return 0; + + pScrn = xf86Screens[scrnIndex]; + if (pScrn->progClock){ + *progClock = TRUE; + return 0; + } else { + *progClock = FALSE; + return pScrn->numClocks; + } +} + +Bool +VidModeGetClocks(int scrnIndex, int *Clocks) +{ + ScrnInfoPtr pScrn; + int i; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + + if (pScrn->progClock) + return FALSE; + + for (i = 0; i < pScrn->numClocks; i++) + *Clocks++ = pScrn->clock[i]; + + return TRUE; +} + + +Bool +VidModeGetFirstModeline(int scrnIndex, pointer *mode, int *dotClock) +{ + ScrnInfoPtr pScrn; + VidModePtr pVidMode; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + pVidMode = VMPTR(pScrn->pScreen); + pVidMode->First = pScrn->modes; + pVidMode->Next = pVidMode->First->next; + + if (pVidMode->First->status == MODE_OK) { + *mode = (pointer)(pVidMode->First); + *dotClock = VidModeGetDotClock(scrnIndex, pVidMode->First->Clock); + return TRUE; + } + + return VidModeGetNextModeline(scrnIndex, mode, dotClock); +} + +Bool +VidModeGetNextModeline(int scrnIndex, pointer *mode, int *dotClock) +{ + ScrnInfoPtr pScrn; + VidModePtr pVidMode; + DisplayModePtr p; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + pVidMode = VMPTR(pScrn->pScreen); + + for (p = pVidMode->Next; p != NULL && p != pVidMode->First; p = p->next) { + if (p->status == MODE_OK) { + pVidMode->Next = p->next; + *mode = (pointer)p; + *dotClock = VidModeGetDotClock(scrnIndex, p->Clock); + return TRUE; + } + } + + return FALSE; +} + +Bool +VidModeDeleteModeline(int scrnIndex, pointer mode) +{ + ScrnInfoPtr pScrn; + + if ((mode == NULL) || (!VidModeAvailable(scrnIndex))) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + xf86DeleteMode(&(pScrn->modes), (DisplayModePtr)mode); + return TRUE; +} + +Bool +VidModeZoomViewport(int scrnIndex, int zoom) +{ + ScrnInfoPtr pScrn; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + xf86ZoomViewport(pScrn->pScreen, zoom); + return TRUE; +} + +Bool +VidModeSetViewPort(int scrnIndex, int x, int y) +{ + ScrnInfoPtr pScrn; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + pScrn->frameX0 = min( max(x, 0), + pScrn->virtualX - pScrn->currentMode->HDisplay ); + pScrn->frameX1 = pScrn->frameX0 + pScrn->currentMode->HDisplay - 1; + pScrn->frameY0 = min( max(y, 0), + pScrn->virtualY - pScrn->currentMode->VDisplay ); + pScrn->frameY1 = pScrn->frameY0 + pScrn->currentMode->VDisplay - 1; + if (pScrn->AdjustFrame != NULL) + (pScrn->AdjustFrame)(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + + return TRUE; +} + +Bool +VidModeGetViewPort(int scrnIndex, int *x, int *y) +{ + ScrnInfoPtr pScrn; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + *x = pScrn->frameX0; + *y = pScrn->frameY0; + return TRUE; +} + +Bool +VidModeSwitchMode(int scrnIndex, pointer mode) +{ + ScrnInfoPtr pScrn; + DisplayModePtr pTmpMode; + Bool retval; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + /* save in case we fail */ + pTmpMode = pScrn->currentMode; + /* Force a mode switch */ + pScrn->currentMode = NULL; + retval = xf86SwitchMode(pScrn->pScreen, mode); + /* we failed: restore it */ + if (retval == FALSE) + pScrn->currentMode = pTmpMode; + return retval; +} + +Bool +VidModeLockZoom(int scrnIndex, Bool lock) +{ + ScrnInfoPtr pScrn; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + + if (xf86Info.dontZoom) + return FALSE; + + xf86LockZoom(pScrn->pScreen, lock); + return TRUE; +} + +Bool +VidModeGetMonitor(int scrnIndex, pointer *monitor) +{ + ScrnInfoPtr pScrn; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + *monitor = (pointer)(pScrn->monitor); + + return TRUE; +} + +ModeStatus +VidModeCheckModeForMonitor(int scrnIndex, pointer mode) +{ + ScrnInfoPtr pScrn; + + if ((mode == NULL) || (!VidModeAvailable(scrnIndex))) + return MODE_ERROR; + + pScrn = xf86Screens[scrnIndex]; + + return xf86CheckModeForMonitor((DisplayModePtr)mode, pScrn->monitor); +} + +ModeStatus +VidModeCheckModeForDriver(int scrnIndex, pointer mode) +{ + ScrnInfoPtr pScrn; + + if ((mode == NULL) || (!VidModeAvailable(scrnIndex))) + return MODE_ERROR; + + pScrn = xf86Screens[scrnIndex]; + + return xf86CheckModeForDriver(pScrn, (DisplayModePtr)mode, 0); +} + +void +VidModeSetCrtcForMode(int scrnIndex, pointer mode) +{ + ScrnInfoPtr pScrn; + DisplayModePtr ScreenModes; + + if ((mode == NULL) || (!VidModeAvailable(scrnIndex))) + return; + + /* Ugly hack so that the xf86Mode.c function can be used without change */ + pScrn = xf86Screens[scrnIndex]; + ScreenModes = pScrn->modes; + pScrn->modes = (DisplayModePtr)mode; + + xf86SetCrtcForModes(pScrn, pScrn->adjustFlags); + pScrn->modes = ScreenModes; + return; +} + +Bool +VidModeAddModeline(int scrnIndex, pointer mode) +{ + ScrnInfoPtr pScrn; + + if ((mode == NULL) || (!VidModeAvailable(scrnIndex))) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + + ((DisplayModePtr)mode)->name = strdup(""); /* freed by deletemode */ + ((DisplayModePtr)mode)->status = MODE_OK; + ((DisplayModePtr)mode)->next = pScrn->modes->next; + ((DisplayModePtr)mode)->prev = pScrn->modes; + pScrn->modes->next = (DisplayModePtr)mode; + if( ((DisplayModePtr)mode)->next != NULL ) + ((DisplayModePtr)mode)->next->prev = (DisplayModePtr)mode; + + return TRUE; +} + +int +VidModeGetNumOfModes(int scrnIndex) +{ + pointer mode = NULL; + int dotClock= 0, nummodes = 0; + + if (!VidModeGetFirstModeline(scrnIndex, &mode, &dotClock)) + return nummodes; + + do { + nummodes++; + if (!VidModeGetNextModeline(scrnIndex, &mode, &dotClock)) + return nummodes; + } while (TRUE); +} + +Bool +VidModeSetGamma(int scrnIndex, float red, float green, float blue) +{ + ScrnInfoPtr pScrn; + Gamma gamma; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + gamma.red = red; + gamma.green = green; + gamma.blue = blue; + if (xf86ChangeGamma(pScrn->pScreen, gamma) != Success) + return FALSE; + else + return TRUE; +} + +Bool +VidModeGetGamma(int scrnIndex, float *red, float *green, float *blue) +{ + ScrnInfoPtr pScrn; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + *red = pScrn->gamma.red; + *green = pScrn->gamma.green; + *blue = pScrn->gamma.blue; + return TRUE; +} + +Bool +VidModeSetGammaRamp(int scrnIndex, int size, CARD16 *r, CARD16 *g, CARD16 *b) +{ + ScrnInfoPtr pScrn; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + xf86ChangeGammaRamp(pScrn->pScreen, size, r, g, b); + return TRUE; +} + +Bool +VidModeGetGammaRamp(int scrnIndex, int size, CARD16 *r, CARD16 *g, CARD16 *b) +{ + ScrnInfoPtr pScrn; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + xf86GetGammaRamp(pScrn->pScreen, size, r, g, b); + return TRUE; +} + +int +VidModeGetGammaRampSize(int scrnIndex) +{ + if (!VidModeAvailable(scrnIndex)) + return 0; + + return xf86GetGammaRampSize(xf86Screens[scrnIndex]->pScreen); +} + +pointer +VidModeCreateMode(void) +{ + DisplayModePtr mode; + + mode = malloc(sizeof(DisplayModeRec)); + if (mode != NULL) { + mode->name = ""; + mode->VScan = 1; /* divides refresh rate. default = 1 */ + mode->Private = NULL; + mode->next = mode; + mode->prev = mode; + } + return mode; +} + +void +VidModeCopyMode(pointer modefrom, pointer modeto) +{ + memcpy(modeto, modefrom, sizeof(DisplayModeRec)); +} + + +int +VidModeGetModeValue(pointer mode, int valtyp) +{ + int ret = 0; + + switch (valtyp) { + case VIDMODE_H_DISPLAY: + ret = ((DisplayModePtr) mode)->HDisplay; + break; + case VIDMODE_H_SYNCSTART: + ret = ((DisplayModePtr)mode)->HSyncStart; + break; + case VIDMODE_H_SYNCEND: + ret = ((DisplayModePtr)mode)->HSyncEnd; + break; + case VIDMODE_H_TOTAL: + ret = ((DisplayModePtr)mode)->HTotal; + break; + case VIDMODE_H_SKEW: + ret = ((DisplayModePtr)mode)->HSkew; + break; + case VIDMODE_V_DISPLAY: + ret = ((DisplayModePtr)mode)->VDisplay; + break; + case VIDMODE_V_SYNCSTART: + ret = ((DisplayModePtr)mode)->VSyncStart; + break; + case VIDMODE_V_SYNCEND: + ret = ((DisplayModePtr)mode)->VSyncEnd; + break; + case VIDMODE_V_TOTAL: + ret = ((DisplayModePtr)mode)->VTotal; + break; + case VIDMODE_FLAGS: + ret = ((DisplayModePtr)mode)->Flags; + break; + case VIDMODE_CLOCK: + ret = ((DisplayModePtr)mode)->Clock; + break; + } + return ret; +} + +void +VidModeSetModeValue(pointer mode, int valtyp, int val) +{ + switch (valtyp) { + case VIDMODE_H_DISPLAY: + ((DisplayModePtr)mode)->HDisplay = val; + break; + case VIDMODE_H_SYNCSTART: + ((DisplayModePtr)mode)->HSyncStart = val; + break; + case VIDMODE_H_SYNCEND: + ((DisplayModePtr)mode)->HSyncEnd = val; + break; + case VIDMODE_H_TOTAL: + ((DisplayModePtr)mode)->HTotal = val; + break; + case VIDMODE_H_SKEW: + ((DisplayModePtr)mode)->HSkew = val; + break; + case VIDMODE_V_DISPLAY: + ((DisplayModePtr)mode)->VDisplay = val; + break; + case VIDMODE_V_SYNCSTART: + ((DisplayModePtr)mode)->VSyncStart = val; + break; + case VIDMODE_V_SYNCEND: + ((DisplayModePtr)mode)->VSyncEnd = val; + break; + case VIDMODE_V_TOTAL: + ((DisplayModePtr)mode)->VTotal = val; + break; + case VIDMODE_FLAGS: + ((DisplayModePtr)mode)->Flags = val; + break; + case VIDMODE_CLOCK: + ((DisplayModePtr)mode)->Clock = val; + break; + } + return; +} + +vidMonitorValue +VidModeGetMonitorValue(pointer monitor, int valtyp, int indx) +{ + vidMonitorValue ret = { NULL, }; + + switch (valtyp) { + case VIDMODE_MON_VENDOR: + ret.ptr = (((MonPtr)monitor)->vendor); + break; + case VIDMODE_MON_MODEL: + ret.ptr = (((MonPtr)monitor)->model); + break; + case VIDMODE_MON_NHSYNC: + ret.i = ((MonPtr)monitor)->nHsync; + break; + case VIDMODE_MON_NVREFRESH: + ret.i = ((MonPtr)monitor)->nVrefresh; + break; + case VIDMODE_MON_HSYNC_LO: + ret.f = (100.0 * ((MonPtr)monitor)->hsync[indx].lo); + break; + case VIDMODE_MON_HSYNC_HI: + ret.f = (100.0 * ((MonPtr)monitor)->hsync[indx].hi); + break; + case VIDMODE_MON_VREFRESH_LO: + ret.f = (100.0 * ((MonPtr)monitor)->vrefresh[indx].lo); + break; + case VIDMODE_MON_VREFRESH_HI: + ret.f = (100.0 * ((MonPtr)monitor)->vrefresh[indx].hi); + break; + } + return ret; +} + + +#endif /* XF86VIDMODE */ diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c new file mode 100644 index 0000000..2bac33a --- /dev/null +++ b/hw/xfree86/common/xf86Xinput.c @@ -0,0 +1,1411 @@ +/* + * Copyright 1995-1999 by Frederic Lepied, France. <Lepied@XFree86.org> + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Frederic Lepied not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Frederic Lepied makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL FREDERIC LEPIED 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. + * + */ +/* + * Copyright (c) 2000-2002 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <X11/Xfuncproto.h> +#include <X11/Xmd.h> +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include <X11/Xatom.h> +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86Config.h" +#include "xf86Xinput.h" +#include "xf86Optrec.h" +#include "mipointer.h" +#include "extinit.h" +#include "loaderProcs.h" + +#include "exevents.h" /* AddInputDevice */ +#include "exglobals.h" +#include "eventstr.h" +#include "inpututils.h" + +#include <string.h> /* InputClassMatches */ +#ifdef HAVE_FNMATCH_H +#include <fnmatch.h> +#endif +#ifdef HAVE_SYS_UTSNAME_H +#include <sys/utsname.h> +#endif + +#include <stdarg.h> +#include <stdint.h> /* for int64_t */ + +#include "mi.h" + +#include <ptrveloc.h> /* dix pointer acceleration */ +#include <xserver-properties.h> + +#ifdef XFreeXDGA +#include "dgaproc.h" +#endif + +#include "xkbsrv.h" + +/* Valuator verification macro */ +#define XI_VERIFY_VALUATORS(num_valuators) \ + if (num_valuators > MAX_VALUATORS) { \ + xf86Msg(X_ERROR, "%s: num_valuator %d is greater than" \ + " MAX_VALUATORS\n", __FUNCTION__, num_valuators); \ + return; \ + } + +EventListPtr xf86Events = NULL; + +static int +xf86InputDevicePostInit(DeviceIntPtr dev); + +/** + * Eval config and modify DeviceVelocityRec accordingly + */ +static void +ProcessVelocityConfiguration(DeviceIntPtr pDev, char* devname, pointer list, + DeviceVelocityPtr s) +{ + int tempi; + float tempf; + Atom float_prop = XIGetKnownProperty(XATOM_FLOAT); + Atom prop; + + if(!s) + return; + + /* common settings (available via device properties) */ + tempf = xf86SetRealOption(list, "ConstantDeceleration", 1.0); + if (tempf > 1.0) { + xf86Msg(X_CONFIG, "%s: (accel) constant deceleration by %.1f\n", + devname, tempf); + prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION); + XIChangeDeviceProperty(pDev, prop, float_prop, 32, + PropModeReplace, 1, &tempf, FALSE); + } + + tempf = xf86SetRealOption(list, "AdaptiveDeceleration", 1.0); + if (tempf > 1.0) { + xf86Msg(X_CONFIG, "%s: (accel) adaptive deceleration by %.1f\n", + devname, tempf); + prop = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION); + XIChangeDeviceProperty(pDev, prop, float_prop, 32, + PropModeReplace, 1, &tempf, FALSE); + } + + /* select profile by number */ + tempi = xf86SetIntOption(list, "AccelerationProfile", + s->statistics.profile_number); + + prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER); + if (XIChangeDeviceProperty(pDev, prop, XA_INTEGER, 32, + PropModeReplace, 1, &tempi, FALSE) == Success) { + xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i\n", devname, + tempi); + } else { + xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i is unknown\n", + devname, tempi); + } + + /* set scaling */ + tempf = xf86SetRealOption(list, "ExpectedRate", 0); + prop = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING); + if (tempf > 0) { + tempf = 1000.0 / tempf; + XIChangeDeviceProperty(pDev, prop, float_prop, 32, + PropModeReplace, 1, &tempf, FALSE); + } else { + tempf = xf86SetRealOption(list, "VelocityScale", s->corr_mul); + XIChangeDeviceProperty(pDev, prop, float_prop, 32, + PropModeReplace, 1, &tempf, FALSE); + } + + tempi = xf86SetIntOption(list, "VelocityTrackerCount", -1); + if (tempi > 1) + InitTrackers(s, tempi); + + s->initial_range = xf86SetIntOption(list, "VelocityInitialRange", + s->initial_range); + + s->max_diff = xf86SetRealOption(list, "VelocityAbsDiff", s->max_diff); + + tempf = xf86SetRealOption(list, "VelocityRelDiff", -1); + if (tempf >= 0) { + xf86Msg(X_CONFIG, "%s: (accel) max rel. velocity difference: %.1f%%\n", + devname, tempf*100.0); + s->max_rel_diff = tempf; + } + + /* Configure softening. If const deceleration is used, this is expected + * to provide better subpixel information so we enable + * softening by default only if ConstantDeceleration is not used + */ + s->use_softening = xf86SetBoolOption(list, "Softening", + s->const_acceleration == 1.0); + + s->average_accel = xf86SetBoolOption(list, "AccelerationProfileAveraging", + s->average_accel); + + s->reset_time = xf86SetIntOption(list, "VelocityReset", s->reset_time); +} + +static void +ApplyAccelerationSettings(DeviceIntPtr dev){ + int scheme, i; + DeviceVelocityPtr pVel; + InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; + char* schemeStr; + + if (dev->valuator && dev->ptrfeed) { + schemeStr = xf86SetStrOption(pInfo->options, "AccelerationScheme", ""); + + scheme = dev->valuator->accelScheme.number; + + if (!xf86NameCmp(schemeStr, "predictable")) + scheme = PtrAccelPredictable; + + if (!xf86NameCmp(schemeStr, "lightweight")) + scheme = PtrAccelLightweight; + + if (!xf86NameCmp(schemeStr, "none")) + scheme = PtrAccelNoOp; + + /* reinit scheme if needed */ + if (dev->valuator->accelScheme.number != scheme) { + if (dev->valuator->accelScheme.AccelCleanupProc) { + dev->valuator->accelScheme.AccelCleanupProc(dev); + } + + if (InitPointerAccelerationScheme(dev, scheme)) { + xf86Msg(X_CONFIG, "%s: (accel) selected scheme %s/%i\n", + pInfo->name, schemeStr, scheme); + } else { + xf86Msg(X_CONFIG, "%s: (accel) could not init scheme %s\n", + pInfo->name, schemeStr); + scheme = dev->valuator->accelScheme.number; + } + } else { + xf86Msg(X_CONFIG, "%s: (accel) keeping acceleration scheme %i\n", + pInfo->name, scheme); + } + + free(schemeStr); + + /* process special configuration */ + switch (scheme) { + case PtrAccelPredictable: + pVel = GetDevicePredictableAccelData(dev); + ProcessVelocityConfiguration (dev, pInfo->name, pInfo->options, + pVel); + break; + } + + i = xf86SetIntOption(pInfo->options, "AccelerationNumerator", + dev->ptrfeed->ctrl.num); + if (i >= 0) + dev->ptrfeed->ctrl.num = i; + + i = xf86SetIntOption(pInfo->options, "AccelerationDenominator", + dev->ptrfeed->ctrl.den); + if (i > 0) + dev->ptrfeed->ctrl.den = i; + + i = xf86SetIntOption(pInfo->options, "AccelerationThreshold", + dev->ptrfeed->ctrl.threshold); + if (i >= 0) + dev->ptrfeed->ctrl.threshold = i; + + xf86Msg(X_CONFIG, "%s: (accel) acceleration factor: %.3f\n", + pInfo->name, ((float)dev->ptrfeed->ctrl.num)/ + ((float)dev->ptrfeed->ctrl.den)); + xf86Msg(X_CONFIG, "%s: (accel) acceleration threshold: %i\n", + pInfo->name, dev->ptrfeed->ctrl.threshold); + } +} + +/*********************************************************************** + * + * xf86ProcessCommonOptions -- + * + * Process global options. + * + *********************************************************************** + */ +void +xf86ProcessCommonOptions(InputInfoPtr pInfo, + pointer list) +{ + if (xf86SetBoolOption(list, "Floating", 0) || + !xf86SetBoolOption(list, "AlwaysCore", 1) || + !xf86SetBoolOption(list, "SendCoreEvents", 1) || + !xf86SetBoolOption(list, "CorePointer", 1) || + !xf86SetBoolOption(list, "CoreKeyboard", 1)) { + xf86Msg(X_CONFIG, "%s: doesn't report core events\n", pInfo->name); + } else { + pInfo->flags |= XI86_ALWAYS_CORE; + xf86Msg(X_CONFIG, "%s: always reports core events\n", pInfo->name); + } +} + +/*********************************************************************** + * + * xf86ActivateDevice -- + * + * Initialize an input device. + * + * Returns TRUE on success, or FALSE otherwise. + *********************************************************************** + */ +static DeviceIntPtr +xf86ActivateDevice(InputInfoPtr pInfo) +{ + DeviceIntPtr dev; + Atom atom; + + dev = AddInputDevice(serverClient, pInfo->device_control, TRUE); + + if (dev == NULL) + { + xf86Msg(X_ERROR, "Too many input devices. Ignoring %s\n", + pInfo->name); + pInfo->dev = NULL; + return NULL; + } + + atom = MakeAtom(pInfo->type_name, strlen(pInfo->type_name), TRUE); + AssignTypeAndName(dev, atom, pInfo->name); + dev->public.devicePrivate = pInfo; + pInfo->dev = dev; + + dev->coreEvents = pInfo->flags & XI86_ALWAYS_CORE; + dev->type = SLAVE; + dev->spriteInfo->spriteOwner = FALSE; + + dev->config_info = xf86SetStrOption(pInfo->options, "config_info", NULL); + + if (serverGeneration == 1) + xf86Msg(X_INFO, "XINPUT: Adding extended input device \"%s\" (type: %s)\n", + pInfo->name, pInfo->type_name); + + return dev; +} + +/**************************************************************************** + * + * Caller: ProcXSetDeviceMode + * + * Change the mode of an extension device. + * This function is used to change the mode of a device from reporting + * relative motion to reporting absolute positional information, and + * vice versa. + * The default implementation below is that no such devices are supported. + * + *********************************************************************** + */ + +int +SetDeviceMode (ClientPtr client, DeviceIntPtr dev, int mode) +{ + InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; + + if (pInfo->switch_mode) { + return (*pInfo->switch_mode)(client, dev, mode); + } + else + return BadMatch; +} + + +/*********************************************************************** + * + * Caller: ProcXSetDeviceValuators + * + * Set the value of valuators on an extension input device. + * This function is used to set the initial value of valuators on + * those input devices that are capable of reporting either relative + * motion or an absolute position, and allow an initial position to be set. + * The default implementation below is that no such devices are supported. + * + *********************************************************************** + */ + +int +SetDeviceValuators (ClientPtr client, DeviceIntPtr dev, int *valuators, + int first_valuator, int num_valuators) +{ + InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; + + if (pInfo->set_device_valuators) + return (*pInfo->set_device_valuators)(pInfo, valuators, first_valuator, + num_valuators); + + return BadMatch; +} + + +/*********************************************************************** + * + * Caller: ProcXChangeDeviceControl + * + * Change the specified device controls on an extension input device. + * + *********************************************************************** + */ + +int +ChangeDeviceControl (ClientPtr client, DeviceIntPtr dev, xDeviceCtl *control) +{ + InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; + + if (!pInfo->control_proc) { + switch (control->control) { + case DEVICE_CORE: + return BadMatch; + case DEVICE_RESOLUTION: + case DEVICE_ABS_CALIB: + case DEVICE_ABS_AREA: + case DEVICE_ENABLE: + return Success; + default: + return BadMatch; + } + } + else { + return (*pInfo->control_proc)(pInfo, control); + } +} + +/* + * Get the operating system name from uname and store it statically to avoid + * repeating the system call each time MatchOS is checked. + */ +static const char * +HostOS(void) +{ +#ifdef HAVE_SYS_UTSNAME_H + struct utsname name; + static char host_os[sizeof(name.sysname)] = ""; + + if (*host_os == '\0') { + if (uname(&name) >= 0) + strcpy(host_os, name.sysname); + else { + strncpy(host_os, "unknown", sizeof(host_os)); + host_os[sizeof(host_os)-1] = '\0'; + } + } + return host_os; +#else + return ""; +#endif +} + +static int +match_substring(const char *attr, const char *pattern) +{ + return (strstr(attr, pattern)) ? 0 : -1; +} + +#ifdef HAVE_FNMATCH_H +static int +match_pattern(const char *attr, const char *pattern) +{ + return fnmatch(pattern, attr, 0); +} +#else +#define match_pattern match_substring +#endif + +#ifdef HAVE_FNMATCH_H +static int +match_path_pattern(const char *attr, const char *pattern) +{ + return fnmatch(pattern, attr, FNM_PATHNAME); +} +#else +#define match_path_pattern match_substring +#endif + +/* + * Match an attribute against a list of NULL terminated arrays of patterns. + * If a pattern in each list entry is matched, return TRUE. + */ +static Bool +MatchAttrToken(const char *attr, struct list *patterns, + int (*compare)(const char *attr, const char *pattern)) +{ + const xf86MatchGroup *group; + + /* If there are no patterns, accept the match */ + if (list_is_empty(patterns)) + return TRUE; + + /* If there are patterns but no attribute, reject the match */ + if (!attr) + return FALSE; + + /* + * Otherwise, iterate the list of patterns ensuring each entry has a + * match. Each list entry is a separate Match line of the same type. + */ + list_for_each_entry(group, patterns, entry) { + char * const *cur; + Bool match = FALSE; + + for (cur = group->values; *cur; cur++) + if ((*compare)(attr, *cur) == 0) { + match = TRUE; + break; + } + if (!match) + return FALSE; + } + + /* All the entries in the list matched the attribute */ + return TRUE; +} + +/* + * Classes without any Match statements match all devices. Otherwise, all + * statements must match. + */ +static Bool +InputClassMatches(const XF86ConfInputClassPtr iclass, const InputInfoPtr idev, + const InputAttributes *attrs) +{ + /* MatchProduct substring */ + if (!MatchAttrToken(attrs->product, &iclass->match_product, match_substring)) + return FALSE; + + /* MatchVendor substring */ + if (!MatchAttrToken(attrs->vendor, &iclass->match_vendor, match_substring)) + return FALSE; + + /* MatchDevicePath pattern */ + if (!MatchAttrToken(attrs->device, &iclass->match_device, match_path_pattern)) + return FALSE; + + /* MatchOS case-insensitive string */ + if (!MatchAttrToken(HostOS(), &iclass->match_os, strcasecmp)) + return FALSE; + + /* MatchPnPID pattern */ + if (!MatchAttrToken(attrs->pnp_id, &iclass->match_pnpid, match_pattern)) + return FALSE; + + /* MatchUSBID pattern */ + if (!MatchAttrToken(attrs->usb_id, &iclass->match_usbid, match_pattern)) + return FALSE; + + /* MatchDriver string */ + if (!MatchAttrToken(idev->driver, &iclass->match_driver, strcmp)) + return FALSE; + + /* + * MatchTag string + * See if any of the device's tags match any of the MatchTag tokens. + */ + if (!list_is_empty(&iclass->match_tag)) { + char * const *tag; + Bool match; + + if (!attrs->tags) + return FALSE; + for (tag = attrs->tags, match = FALSE; *tag; tag++) { + if (MatchAttrToken(*tag, &iclass->match_tag, strcmp)) { + match = TRUE; + break; + } + } + if (!match) + return FALSE; + } + + /* MatchIs* booleans */ + if (iclass->is_keyboard.set && + iclass->is_keyboard.val != !!(attrs->flags & ATTR_KEYBOARD)) + return FALSE; + if (iclass->is_pointer.set && + iclass->is_pointer.val != !!(attrs->flags & ATTR_POINTER)) + return FALSE; + if (iclass->is_joystick.set && + iclass->is_joystick.val != !!(attrs->flags & ATTR_JOYSTICK)) + return FALSE; + if (iclass->is_tablet.set && + iclass->is_tablet.val != !!(attrs->flags & ATTR_TABLET)) + return FALSE; + if (iclass->is_touchpad.set && + iclass->is_touchpad.val != !!(attrs->flags & ATTR_TOUCHPAD)) + return FALSE; + if (iclass->is_touchscreen.set && + iclass->is_touchscreen.val != !!(attrs->flags & ATTR_TOUCHSCREEN)) + return FALSE; + + return TRUE; +} + +/* + * Merge in any InputClass configurations. Options in each InputClass + * section have more priority than the original device configuration as + * well as any previous InputClass sections. + */ +static int +MergeInputClasses(const InputInfoPtr idev, const InputAttributes *attrs) +{ + XF86ConfInputClassPtr cl; + XF86OptionPtr classopts; + + for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { + if (!InputClassMatches(cl, idev, attrs)) + continue; + + /* Collect class options and driver settings */ + classopts = xf86optionListDup(cl->option_lst); + if (cl->driver) { + free(idev->driver); + idev->driver = xstrdup(cl->driver); + if (!idev->driver) { + xf86Msg(X_ERROR, "Failed to allocate memory while merging " + "InputClass configuration"); + return BadAlloc; + } + classopts = xf86ReplaceStrOption(classopts, "driver", + idev->driver); + } + + /* Apply options to device with InputClass settings preferred. */ + xf86Msg(X_CONFIG, "%s: Applying InputClass \"%s\"\n", + idev->name, cl->identifier); + idev->options = xf86optionListMerge(idev->options, classopts); + } + + return Success; +} + +/* + * Iterate the list of classes and look for Option "Ignore". Return the + * value of the last matching class and holler when returning TRUE. + */ +static Bool +IgnoreInputClass(const InputInfoPtr idev, const InputAttributes *attrs) +{ + XF86ConfInputClassPtr cl; + Bool ignore = FALSE; + const char *ignore_class; + + for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { + if (!InputClassMatches(cl, idev, attrs)) + continue; + if (xf86findOption(cl->option_lst, "Ignore")) { + ignore = xf86CheckBoolOption(cl->option_lst, "Ignore", FALSE); + ignore_class = cl->identifier; + } + } + + if (ignore) + xf86Msg(X_CONFIG, "%s: Ignoring device from InputClass \"%s\"\n", + idev->name, ignore_class); + return ignore; +} + +InputInfoPtr +xf86AllocateInput(void) +{ + InputInfoPtr pInfo; + + pInfo = calloc(sizeof(*pInfo), 1); + if (!pInfo) + return NULL; + + pInfo->fd = -1; + pInfo->type_name = "UNKNOWN"; + + return pInfo; +} + +/* Append InputInfoRec to the tail of xf86InputDevs. */ +static void +xf86AddInput(InputDriverPtr drv, InputInfoPtr pInfo) +{ + InputInfoPtr *prev = NULL; + + pInfo->drv = drv; + pInfo->module = DuplicateModule(drv->module, NULL); + + for (prev = &xf86InputDevs; *prev; prev = &(*prev)->next) + ; + + *prev = pInfo; + pInfo->next = NULL; + + xf86CollectInputOptions(pInfo, (const char**)drv->default_options); + xf86OptionListReport(pInfo->options); + xf86ProcessCommonOptions(pInfo, pInfo->options); +} + +/* + * Remove an entry from xf86InputDevs and free all the device's information. + */ +void +xf86DeleteInput(InputInfoPtr pInp, int flags) +{ + /* First check if the inputdev is valid. */ + if (pInp == NULL) + return; + + if (pInp->module) + UnloadModule(pInp->module); + + /* This should *really* be handled in drv->UnInit(dev) call instead, but + * if the driver forgets about it make sure we free it or at least crash + * with flying colors */ + free(pInp->private); + + FreeInputAttributes(pInp->attrs); + + /* Remove the entry from the list. */ + if (pInp == xf86InputDevs) + xf86InputDevs = pInp->next; + else { + InputInfoPtr p = xf86InputDevs; + while (p && p->next != pInp) + p = p->next; + if (p) + p->next = pInp->next; + /* Else the entry wasn't in the xf86InputDevs list (ignore this). */ + } + + free(pInp->driver); + free(pInp->name); + xf86optionListFree(pInp->options); + free(pInp); +} + +/* + * Apply backend-specific initialization. Invoked after ActiveteDevice(), + * i.e. after the driver successfully completed DEVICE_INIT and the device + * is advertised. + * @param dev the device + * @return Success or an error code + */ +static int +xf86InputDevicePostInit(DeviceIntPtr dev) { + ApplyAccelerationSettings(dev); + return Success; +} + +/** + * Create a new input device, activate and enable it. + * + * Possible return codes: + * BadName .. a bad driver name was supplied. + * BadImplementation ... The driver does not have a PreInit function. This + * is a driver bug. + * BadMatch .. device initialization failed. + * BadAlloc .. too many input devices + * + * @param idev The device, already set up with identifier, driver, and the + * options. + * @param pdev Pointer to the new device, if Success was reported. + * @param enable Enable the device after activating it. + * + * @return Success or an error code + */ +_X_INTERNAL int +xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable) +{ + InputDriverPtr drv = NULL; + DeviceIntPtr dev = NULL; + int rval; + + /* Memory leak for every attached device if we don't + * test if the module is already loaded first */ + drv = xf86LookupInputDriver(pInfo->driver); + if (!drv) + if (xf86LoadOneModule(pInfo->driver, NULL)) + drv = xf86LookupInputDriver(pInfo->driver); + if (!drv) { + xf86Msg(X_ERROR, "No input driver matching `%s'\n", pInfo->driver); + rval = BadName; + goto unwind; + } + + xf86Msg(X_INFO, "Using input driver '%s' for '%s'\n", drv->driverName, pInfo->name); + + if (!drv->PreInit) { + xf86Msg(X_ERROR, + "Input driver `%s' has no PreInit function (ignoring)\n", + drv->driverName); + rval = BadImplementation; + goto unwind; + } + + xf86AddInput(drv, pInfo); + + rval = drv->PreInit(drv, pInfo, 0); + + if (rval != Success) { + xf86Msg(X_ERROR, "PreInit returned %d for \"%s\"\n", rval, pInfo->name); + goto unwind; + } + + if (!(dev = xf86ActivateDevice(pInfo))) + { + rval = BadAlloc; + goto unwind; + } + + rval = ActivateDevice(dev, TRUE); + if (rval != Success) + { + xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); + RemoveDevice(dev, TRUE); + goto unwind; + } + + rval = xf86InputDevicePostInit(dev); + if (rval != Success) + { + xf86Msg(X_ERROR, "Couldn't post-init device \"%s\"\n", pInfo->name); + RemoveDevice(dev, TRUE); + goto unwind; + } + + /* Enable it if it's properly initialised and we're currently in the VT */ + if (enable && dev->inited && dev->startup && xf86Screens[0]->vtSema) + { + OsBlockSignals(); + EnableDevice(dev, TRUE); + if (!dev->enabled) + { + OsReleaseSignals(); + xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); + rval = BadMatch; + goto unwind; + } + /* send enter/leave event, update sprite window */ + CheckMotion(NULL, dev); + OsReleaseSignals(); + } + + *pdev = dev; + return Success; + +unwind: + if(pInfo) { + if(drv && drv->UnInit) + drv->UnInit(drv, pInfo, 0); + else + xf86DeleteInput(pInfo, 0); + } + return rval; +} + +int +NewInputDeviceRequest (InputOption *options, InputAttributes *attrs, + DeviceIntPtr *pdev) +{ + InputInfoPtr pInfo = NULL; + InputOption *option = NULL; + int rval = Success; + int is_auto = 0; + + pInfo = xf86AllocateInput(); + if (!pInfo) + return BadAlloc; + + for (option = options; option; option = option->next) { + if (strcasecmp(option->key, "driver") == 0) { + if (pInfo->driver) { + rval = BadRequest; + goto unwind; + } + pInfo->driver = xstrdup(option->value); + if (!pInfo->driver) { + rval = BadAlloc; + goto unwind; + } + } + + if (strcasecmp(option->key, "name") == 0 || + strcasecmp(option->key, "identifier") == 0) { + if (pInfo->name) { + rval = BadRequest; + goto unwind; + } + pInfo->name = xstrdup(option->value); + if (!pInfo->name) { + rval = BadAlloc; + goto unwind; + } + } + + if (strcmp(option->key, "_source") == 0 && + (strcmp(option->value, "server/hal") == 0 || + strcmp(option->value, "server/udev") == 0)) { + is_auto = 1; + if (!xf86Info.autoAddDevices) { + rval = BadMatch; + goto unwind; + } + } + } + + for (option = options; option; option = option->next) { + /* Steal option key/value strings from the provided list. + * We need those strings, the InputOption list doesn't. */ + pInfo->options = xf86addNewOption(pInfo->options, + option->key, option->value); + option->key = NULL; + option->value = NULL; + } + + /* Apply InputClass settings */ + if (attrs) { + if (IgnoreInputClass(pInfo, attrs)) { + rval = BadIDChoice; + goto unwind; + } + + rval = MergeInputClasses(pInfo, attrs); + if (rval != Success) + goto unwind; + + pInfo->attrs = DuplicateInputAttributes(attrs); + } + + if (!pInfo->driver || !pInfo->name) { + xf86Msg(X_INFO, "No input driver/identifier specified (ignoring)\n"); + rval = BadRequest; + goto unwind; + } + + if (!pInfo->name) { + xf86Msg(X_ERROR, "No device identifier specified (ignoring)\n"); + rval = BadMatch; + goto unwind; + } + + rval = xf86NewInputDevice(pInfo, pdev, + (!is_auto || (is_auto && xf86Info.autoEnableDevices))); + + return rval; + +unwind: + if (is_auto && !xf86Info.autoAddDevices) + xf86Msg(X_INFO, "AutoAddDevices is off - not adding device.\n"); + xf86DeleteInput(pInfo, 0); + return rval; +} + +void +DeleteInputDeviceRequest(DeviceIntPtr pDev) +{ + InputInfoPtr pInfo = (InputInfoPtr) pDev->public.devicePrivate; + InputDriverPtr drv = NULL; + Bool isMaster = IsMaster(pDev); + + if (pInfo) /* need to get these before RemoveDevice */ + drv = pInfo->drv; + + OsBlockSignals(); + RemoveDevice(pDev, TRUE); + + if (!isMaster && pInfo != NULL) + { + if(drv->UnInit) + drv->UnInit(drv, pInfo, 0); + else + xf86DeleteInput(pInfo, 0); + } + OsReleaseSignals(); +} + +/* + * convenient functions to post events + */ + +void +xf86PostMotionEvent(DeviceIntPtr device, + int is_absolute, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + int i = 0; + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_zero(&mask); + va_start(var, num_valuators); + for (i = 0; i < num_valuators; i++) + valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); + va_end(var); + + xf86PostMotionEventM(device, is_absolute, &mask); +} + +void +xf86PostMotionEventP(DeviceIntPtr device, + int is_absolute, + int first_valuator, + int num_valuators, + const int *valuators) +{ + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); + xf86PostMotionEventM(device, is_absolute, &mask); +} + +void +xf86PostMotionEventM(DeviceIntPtr device, + int is_absolute, + const ValuatorMask *mask) +{ + int i = 0, nevents = 0; + DeviceEvent *event; + int flags = 0; + + if (valuator_mask_num_valuators(mask) > 0) + { + if (is_absolute) + flags = POINTER_ABSOLUTE; + else + flags = POINTER_RELATIVE | POINTER_ACCELERATE; + } + +#if XFreeXDGA + /* The evdev driver may not always send all axes across. */ + if (valuator_mask_isset(mask, 0) || + valuator_mask_isset(mask, 1)) + if (miPointerGetScreen(device)) { + int index = miPointerGetScreen(device)->myNum; + int dx = 0, dy = 0; + + if (valuator_mask_isset(mask, 0)) + { + dx = valuator_mask_get(mask, 0); + if (is_absolute) + dx -= device->last.valuators[0]; + } + + if (valuator_mask_isset(mask, 1)) + { + dy = valuator_mask_get(mask, 1); + if (is_absolute) + dy -= device->last.valuators[1]; + } + + if (DGAStealMotionEvent(device, index, dx, dy)) + return; + } +#endif + + nevents = GetPointerEvents(xf86Events, device, MotionNotify, 0, flags, mask); + + for (i = 0; i < nevents; i++) { + event = (DeviceEvent*)((xf86Events + i)->event); + mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); + } +} + +void +xf86PostProximityEvent(DeviceIntPtr device, + int is_in, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + int i; + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_zero(&mask); + va_start(var, num_valuators); + for (i = 0; i < num_valuators; i++) + valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); + va_end(var); + + xf86PostProximityEventM(device, is_in, &mask); +} + +void +xf86PostProximityEventP(DeviceIntPtr device, + int is_in, + int first_valuator, + int num_valuators, + const int *valuators) +{ + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); + xf86PostProximityEventM(device, is_in, &mask); +} + +void +xf86PostProximityEventM(DeviceIntPtr device, + int is_in, + const ValuatorMask *mask) +{ + int i, nevents; + + nevents = GetProximityEvents(xf86Events, device, + is_in ? ProximityIn : ProximityOut, mask); + for (i = 0; i < nevents; i++) + mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); + +} + +void +xf86PostButtonEvent(DeviceIntPtr device, + int is_absolute, + int button, + int is_down, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + ValuatorMask mask; + int i = 0; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_zero(&mask); + + va_start(var, num_valuators); + for (i = 0; i < num_valuators; i++) + valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); + va_end(var); + + xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); +} + +void +xf86PostButtonEventP(DeviceIntPtr device, + int is_absolute, + int button, + int is_down, + int first_valuator, + int num_valuators, + const int *valuators) +{ + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); + xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); +} + +void +xf86PostButtonEventM(DeviceIntPtr device, + int is_absolute, + int button, + int is_down, + const ValuatorMask *mask) +{ + int i = 0, nevents = 0; + int flags = 0; + + if (valuator_mask_num_valuators(mask) > 0) + { + if (is_absolute) + flags = POINTER_ABSOLUTE; + else + flags = POINTER_RELATIVE | POINTER_ACCELERATE; + } + +#if XFreeXDGA + if (miPointerGetScreen(device)) { + int index = miPointerGetScreen(device)->myNum; + + if (DGAStealButtonEvent(device, index, button, is_down)) + return; + } +#endif + + nevents = GetPointerEvents(xf86Events, device, + is_down ? ButtonPress : ButtonRelease, button, + flags, mask); + + for (i = 0; i < nevents; i++) + mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); + +} + +void +xf86PostKeyEvent(DeviceIntPtr device, + unsigned int key_code, + int is_down, + int is_absolute, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + int i = 0; + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_zero(&mask); + + va_start(var, num_valuators); + for (i = 0; i < num_valuators; i++) + valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); + va_end(var); + + xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask); +} + +void +xf86PostKeyEventP(DeviceIntPtr device, + unsigned int key_code, + int is_down, + int is_absolute, + int first_valuator, + int num_valuators, + const int *valuators) +{ + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); + xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask); +} + +void +xf86PostKeyEventM(DeviceIntPtr device, + unsigned int key_code, + int is_down, + int is_absolute, + const ValuatorMask *mask) +{ + int i = 0, nevents = 0; + +#if XFreeXDGA + DeviceIntPtr pointer; + + /* Some pointers send key events, paired device is wrong then. */ + pointer = IsPointerDevice(device) ? device : GetPairedDevice(device); + if (miPointerGetScreen(pointer)) { + int index = miPointerGetScreen(pointer)->myNum; + + if (DGAStealKeyEvent(device, index, key_code, is_down)) + return; + } +#endif + + if (is_absolute) { + nevents = GetKeyboardValuatorEvents(xf86Events, device, + is_down ? KeyPress : KeyRelease, + key_code, mask); + } + else { + nevents = GetKeyboardEvents(xf86Events, device, + is_down ? KeyPress : KeyRelease, + key_code); + } + + for (i = 0; i < nevents; i++) + mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); +} + +void +xf86PostKeyboardEvent(DeviceIntPtr device, + unsigned int key_code, + int is_down) +{ + ValuatorMask mask; + + valuator_mask_zero(&mask); + xf86PostKeyEventM(device, key_code, is_down, 0, &mask); +} + +InputInfoPtr +xf86FirstLocalDevice(void) +{ + return xf86InputDevs; +} + +/* + * Cx - raw data from touch screen + * to_max - scaled highest dimension + * (remember, this is of rows - 1 because of 0 origin) + * to_min - scaled lowest dimension + * from_max - highest raw value from touch screen calibration + * from_min - lowest raw value from touch screen calibration + * + * This function is the same for X or Y coordinates. + * You may have to reverse the high and low values to compensate for + * different orgins on the touch screen vs X. + * + * e.g. to scale from device coordinates into screen coordinates, call + * xf86ScaleAxis(x, 0, screen_width, dev_min, dev_max); + */ + +int +xf86ScaleAxis(int Cx, + int to_max, + int to_min, + int from_max, + int from_min ) +{ + int X; + int64_t to_width = to_max - to_min; + int64_t from_width = from_max - from_min; + + if (from_width) { + X = (int)(((to_width * (Cx - from_min)) / from_width) + to_min); + } + else { + X = 0; + ErrorF ("Divide by Zero in xf86ScaleAxis\n"); + } + + if (X > to_max) + X = to_max; + if (X < to_min) + X = to_min; + + return X; +} + +/* + * This function checks the given screen against the current screen and + * makes changes if appropriate. It should be called from an XInput driver's + * ReadInput function before any events are posted, if the device is screen + * specific like a touch screen. + */ +void +xf86XInputSetScreen(InputInfoPtr pInfo, + int screen_number, + int x, + int y) +{ + if (miPointerGetScreen(pInfo->dev) != + screenInfo.screens[screen_number]) { + miPointerSetScreen(pInfo->dev, screen_number, x, y); + } +} + + +void +xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval, + int resolution, int min_res, int max_res, int mode) +{ + if (!dev || !dev->valuator) + return; + + InitValuatorAxisStruct(dev, axnum, label, minval, maxval, resolution, min_res, + max_res, mode); +} + +/* + * Set the valuator values to be in synch with dix/event.c + * DefineInitialRootWindow(). + */ +void +xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum) +{ + if (axnum == 0) { + dev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; + dev->last.valuators[0] = dev->valuator->axisVal[0]; + } + else if (axnum == 1) { + dev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; + dev->last.valuators[1] = dev->valuator->axisVal[1]; + } +} + + +/** + * Deactivate a device. Call this function from the driver if you receive a + * read error or something else that spoils your day. + * Device will be moved to the off_devices list, but it will still be there + * until you really clean up after it. + * Notifies the client about an inactive device. + * + * @param panic True if device is unrecoverable and needs to be removed. + */ +void +xf86DisableDevice(DeviceIntPtr dev, Bool panic) +{ + if(!panic) + { + DisableDevice(dev, TRUE); + } else + { + SendDevicePresenceEvent(dev->id, DeviceUnrecoverable); + DeleteInputDeviceRequest(dev); + } +} + +/** + * Reactivate a device. Call this function from the driver if you just found + * out that the read error wasn't quite that bad after all. + * Device will be re-activated, and an event sent to the client. + */ +void +xf86EnableDevice(DeviceIntPtr dev) +{ + EnableDevice(dev, TRUE); +} + +/* end of xf86Xinput.c */ diff --git a/hw/xfree86/common/xf86Xinput.h b/hw/xfree86/common/xf86Xinput.h new file mode 100644 index 0000000..1b0b16f --- /dev/null +++ b/hw/xfree86/common/xf86Xinput.h @@ -0,0 +1,182 @@ +/* + * Copyright 1995-1999 by Frederic Lepied, France. <Lepied@XFree86.org> + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Frederic Lepied not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Frederic Lepied makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL FREDERIC LEPIED 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. + * + */ + +/* + * Copyright (c) 2000-2002 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + + +#ifndef _xf86Xinput_h +#define _xf86Xinput_h + +#include "xf86str.h" +#include "inputstr.h" +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include "XIstubs.h" + +/* Input device flags */ +#define XI86_ALWAYS_CORE 0x04 /* device always controls the pointer */ +/* the device sends Xinput and core pointer events */ +#define XI86_SEND_CORE_EVENTS XI86_ALWAYS_CORE + +/* This holds the input driver entry and module information. */ +typedef struct _InputDriverRec { + int driverVersion; + char * driverName; + void (*Identify)(int flags); + int (*PreInit)(struct _InputDriverRec *drv, + struct _InputInfoRec* pInfo, int flags); + void (*UnInit)(struct _InputDriverRec *drv, + struct _InputInfoRec *pInfo, + int flags); + pointer module; + char ** default_options; +} InputDriverRec, *InputDriverPtr; + +/* This is to input devices what the ScrnInfoRec is to screens. */ + +typedef struct _InputInfoRec { + struct _InputInfoRec *next; + char * name; + char * driver; + + int flags; + + Bool (*device_control)(DeviceIntPtr device, int what); + void (*read_input)(struct _InputInfoRec *local); + int (*control_proc)(struct _InputInfoRec *local, + xDeviceCtl *control); + int (*switch_mode)(ClientPtr client, DeviceIntPtr dev, + int mode); + int (*set_device_valuators) + (struct _InputInfoRec *local, + int *valuators, int first_valuator, + int num_valuators); + + int fd; + DeviceIntPtr dev; + pointer private; + char * type_name; + InputDriverPtr drv; + pointer module; + pointer options; + InputAttributes *attrs; +} *InputInfoPtr; + +/* xf86Globals.c */ +extern InputInfoPtr xf86InputDevs; + +/* xf86Xinput.c */ +extern _X_EXPORT void xf86PostMotionEvent(DeviceIntPtr device, int is_absolute, + int first_valuator, int num_valuators, ...); +extern _X_EXPORT void xf86PostMotionEventP(DeviceIntPtr device, int is_absolute, + int first_valuator, int num_valuators, const int *valuators); +extern _X_EXPORT void xf86PostMotionEventM(DeviceIntPtr device, int is_absolute, + const ValuatorMask *mask); +extern _X_EXPORT void xf86PostProximityEvent(DeviceIntPtr device, int is_in, + int first_valuator, int num_valuators, ...); +extern _X_EXPORT void xf86PostProximityEventP(DeviceIntPtr device, int is_in, int first_valuator, + int num_valuators, const int *valuators); +extern _X_EXPORT void xf86PostProximityEventM(DeviceIntPtr device, int is_in, + const ValuatorMask *mask); +extern _X_EXPORT void xf86PostButtonEvent(DeviceIntPtr device, int is_absolute, int button, + int is_down, int first_valuator, int num_valuators, + ...); +extern _X_EXPORT void xf86PostButtonEventP(DeviceIntPtr device, int is_absolute, int button, + int is_down, int first_valuator, int num_valuators, + const int *valuators); +extern _X_EXPORT void xf86PostButtonEventM(DeviceIntPtr device, int is_absolute, int button, + int is_down, const ValuatorMask *mask); +extern _X_EXPORT void xf86PostKeyEvent(DeviceIntPtr device, unsigned int key_code, int is_down, + int is_absolute, int first_valuator, int num_valuators, + ...); +extern _X_EXPORT void xf86PostKeyEventM(DeviceIntPtr device, unsigned int key_code, int is_down, + int is_absolute, const ValuatorMask *mask); +extern _X_EXPORT void xf86PostKeyEventP(DeviceIntPtr device, unsigned int key_code, int is_down, + int is_absolute, int first_valuator, int num_valuators, + const int *valuators); +extern _X_EXPORT void xf86PostKeyboardEvent(DeviceIntPtr device, unsigned int key_code, + int is_down); +extern _X_EXPORT InputInfoPtr xf86FirstLocalDevice(void); +extern _X_EXPORT int xf86ScaleAxis(int Cx, int to_max, int to_min, int from_max, int from_min); +extern _X_EXPORT void xf86XInputSetScreen(InputInfoPtr pInfo, int screen_number, int x, int y); +extern _X_EXPORT void xf86ProcessCommonOptions(InputInfoPtr pInfo, pointer options); +extern _X_EXPORT void xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, + int maxval, int resolution, int min_res, + int max_res, int mode); +extern _X_EXPORT void xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum); +extern _X_EXPORT void xf86AddEnabledDevice(InputInfoPtr pInfo); +extern _X_EXPORT void xf86RemoveEnabledDevice(InputInfoPtr pInfo); +extern _X_EXPORT void xf86DisableDevice(DeviceIntPtr dev, Bool panic); +extern _X_EXPORT void xf86EnableDevice(DeviceIntPtr dev); +/* not exported */ +int xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL is_auto); +InputInfoPtr xf86AllocateInput(void); + +/* xf86Helper.c */ +extern _X_EXPORT void xf86AddInputDriver(InputDriverPtr driver, pointer module, int flags); +extern _X_EXPORT void xf86DeleteInputDriver(int drvIndex); +extern _X_EXPORT InputDriverPtr xf86LookupInputDriver(const char *name); +extern _X_EXPORT InputInfoPtr xf86LookupInput(const char *name); +extern _X_EXPORT void xf86DeleteInput(InputInfoPtr pInp, int flags); +extern _X_EXPORT void xf86MotionHistoryAllocate(InputInfoPtr pInfo); +extern _X_EXPORT void xf86IDrvMsgVerb(InputInfoPtr dev, + MessageType type, int verb, + const char *format, ...) _X_ATTRIBUTE_PRINTF(4,5); +extern _X_EXPORT void xf86IDrvMsg(InputInfoPtr dev, + MessageType type, + const char *format, ...) _X_ATTRIBUTE_PRINTF(3,4); +extern _X_EXPORT void xf86VIDrvMsgVerb(InputInfoPtr dev, + MessageType type, + int verb, + const char *format, + va_list args); + +/* xf86Option.c */ +extern _X_EXPORT void xf86CollectInputOptions(InputInfoPtr pInfo, const char **defaultOpts); + +#endif /* _xf86Xinput_h */ diff --git a/hw/xfree86/common/xf86cmap.c b/hw/xfree86/common/xf86cmap.c new file mode 100644 index 0000000..8b27b84 --- /dev/null +++ b/hw/xfree86/common/xf86cmap.c @@ -0,0 +1,1183 @@ +/* + * Copyright (c) 1998-2001 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#if defined(_XOPEN_SOURCE) || defined(sun) && defined(__SVR4) +#include <math.h> +#else +#define _XOPEN_SOURCE /* to get prototype for pow on some systems */ +#include <math.h> +#undef _XOPEN_SOURCE +#endif + +#include <X11/X.h> +#include "misc.h" +#include <X11/Xproto.h> +#include "colormapst.h" +#include "scrnintstr.h" + +#include "resource.h" + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86str.h" +#include "micmap.h" +#include "xf86Crtc.h" + +#ifdef XFreeXDGA +#include <X11/extensions/xf86dgaproto.h> +#include "dgaproc.h" +#endif + +#include "xf86cmap.h" + +#define SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = \ + ((CMapScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, CMapScreenKey))->field) +#define SCREEN_EPILOGUE(pScreen, field, wrapper)\ + ((pScreen)->field = wrapper) + +#define LOAD_PALETTE(pmap) \ + ((pmap == GetInstalledmiColormap(pmap->pScreen)) && \ + ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || \ + xf86Screens[pmap->pScreen->myNum]->vtSema || pScreenPriv->isDGAmode)) + + +typedef struct _CMapLink { + ColormapPtr cmap; + struct _CMapLink *next; +} CMapLink, *CMapLinkPtr; + +typedef struct { + ScrnInfoPtr pScrn; + CloseScreenProcPtr CloseScreen; + CreateColormapProcPtr CreateColormap; + DestroyColormapProcPtr DestroyColormap; + InstallColormapProcPtr InstallColormap; + StoreColorsProcPtr StoreColors; + Bool (*EnterVT)(int, int); + Bool (*SwitchMode)(int, DisplayModePtr, int); + int (*SetDGAMode)(int, int, DGADevicePtr); + xf86ChangeGammaProc *ChangeGamma; + int maxColors; + int sigRGBbits; + int gammaElements; + LOCO *gamma; + int *PreAllocIndices; + CMapLinkPtr maps; + unsigned int flags; + Bool isDGAmode; +} CMapScreenRec, *CMapScreenPtr; + +typedef struct { + int numColors; + LOCO *colors; + Bool recalculate; + int overscan; +} CMapColormapRec, *CMapColormapPtr; + +static DevPrivateKeyRec CMapScreenKeyRec; +#define CMapScreenKeyRegistered dixPrivateKeyRegistered(&CMapScreenKeyRec) +#define CMapScreenKey (&CMapScreenKeyRec) +static DevPrivateKeyRec CMapColormapKeyRec; +#define CMapColormapKey (&CMapColormapKeyRec) + +static void CMapInstallColormap(ColormapPtr); +static void CMapStoreColors(ColormapPtr, int, xColorItem *); +static Bool CMapCloseScreen (int, ScreenPtr); +static Bool CMapCreateColormap (ColormapPtr); +static void CMapDestroyColormap (ColormapPtr); + +static Bool CMapEnterVT(int, int); +static Bool CMapSwitchMode(int, DisplayModePtr, int); +#ifdef XFreeXDGA +static int CMapSetDGAMode(int, int, DGADevicePtr); +#endif +static int CMapChangeGamma(int, Gamma); + +static void ComputeGamma(CMapScreenPtr); +static Bool CMapAllocateColormapPrivate(ColormapPtr); +static void CMapRefreshColors(ColormapPtr, int, int*); +static void CMapSetOverscan(ColormapPtr, int, int *); +static void CMapReinstallMap(ColormapPtr); +static void CMapUnwrapScreen(ScreenPtr pScreen); + + +Bool xf86ColormapAllocatePrivates(ScrnInfoPtr pScrn) +{ + /* If we support a better colormap system, then pretend we succeeded. */ + if (xf86_crtc_supports_gamma(pScrn)) + return TRUE; + if (!dixRegisterPrivateKey(&CMapScreenKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + if (!dixRegisterPrivateKey(&CMapColormapKeyRec, PRIVATE_COLORMAP, 0)) + return FALSE; + return TRUE; +} + +Bool xf86HandleColormaps( + ScreenPtr pScreen, + int maxColors, + int sigRGBbits, + xf86LoadPaletteProc *loadPalette, + xf86SetOverscanProc *setOverscan, + unsigned int flags +){ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + ColormapPtr pDefMap = NULL; + CMapScreenPtr pScreenPriv; + LOCO *gamma; + int *indices; + int elements; + + /* If we support a better colormap system, then pretend we succeeded. */ + if (xf86_crtc_supports_gamma(pScrn)) + return TRUE; + + if(!maxColors || !sigRGBbits || !loadPalette) + return FALSE; + + elements = 1 << sigRGBbits; + + if(!(gamma = malloc(elements * sizeof(LOCO)))) + return FALSE; + + if(!(indices = malloc(maxColors * sizeof(int)))) { + free(gamma); + return FALSE; + } + + if(!(pScreenPriv = malloc(sizeof(CMapScreenRec)))) { + free(gamma); + free(indices); + return FALSE; + } + + dixSetPrivate(&pScreen->devPrivates, &CMapScreenKeyRec, pScreenPriv); + + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreenPriv->CreateColormap = pScreen->CreateColormap; + pScreenPriv->DestroyColormap = pScreen->DestroyColormap; + pScreenPriv->InstallColormap = pScreen->InstallColormap; + pScreenPriv->StoreColors = pScreen->StoreColors; + pScreen->CloseScreen = CMapCloseScreen; + pScreen->CreateColormap = CMapCreateColormap; + pScreen->DestroyColormap = CMapDestroyColormap; + pScreen->InstallColormap = CMapInstallColormap; + pScreen->StoreColors = CMapStoreColors; + + pScreenPriv->pScrn = pScrn; + pScrn->LoadPalette = loadPalette; + pScrn->SetOverscan = setOverscan; + pScreenPriv->maxColors = maxColors; + pScreenPriv->sigRGBbits = sigRGBbits; + pScreenPriv->gammaElements = elements; + pScreenPriv->gamma = gamma; + pScreenPriv->PreAllocIndices = indices; + pScreenPriv->maps = NULL; + pScreenPriv->flags = flags; + pScreenPriv->isDGAmode = FALSE; + + pScreenPriv->EnterVT = pScrn->EnterVT; + pScreenPriv->SwitchMode = pScrn->SwitchMode; + pScreenPriv->SetDGAMode = pScrn->SetDGAMode; + pScreenPriv->ChangeGamma = pScrn->ChangeGamma; + + if (!(flags & CMAP_LOAD_EVEN_IF_OFFSCREEN)) { + pScrn->EnterVT = CMapEnterVT; + if ((flags & CMAP_RELOAD_ON_MODE_SWITCH) && pScrn->SwitchMode) + pScrn->SwitchMode = CMapSwitchMode; + } +#ifdef XFreeXDGA + pScrn->SetDGAMode = CMapSetDGAMode; +#endif + pScrn->ChangeGamma = CMapChangeGamma; + + ComputeGamma(pScreenPriv); + + /* get the default map */ + dixLookupResourceByType((pointer *)&pDefMap, pScreen->defColormap, + RT_COLORMAP, serverClient, DixInstallAccess); + + if(!CMapAllocateColormapPrivate(pDefMap)) { + CMapUnwrapScreen(pScreen); + return FALSE; + } + + /* Force the initial map to be loaded */ + SetInstalledmiColormap(pScreen, NULL); + CMapInstallColormap(pDefMap); + return TRUE; +} + + +/**** Screen functions ****/ + + +static Bool +CMapCloseScreen (int i, ScreenPtr pScreen) +{ + CMapUnwrapScreen(pScreen); + + return (*pScreen->CloseScreen) (i, pScreen); +} + +static Bool +CMapColormapUseMax(VisualPtr pVisual, CMapScreenPtr pScreenPriv) +{ + if (pVisual->nplanes > 16) + return TRUE; + return ((1 << pVisual->nplanes) > pScreenPriv->maxColors); +} + +static Bool +CMapAllocateColormapPrivate(ColormapPtr pmap) +{ + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pmap->pScreen->devPrivates, CMapScreenKey); + CMapColormapPtr pColPriv; + CMapLinkPtr pLink; + int numColors; + LOCO *colors; + + if (CMapColormapUseMax(pmap->pVisual, pScreenPriv)) + numColors = pmap->pVisual->ColormapEntries; + else + numColors = 1 << pmap->pVisual->nplanes; + + if(!(colors = malloc(numColors * sizeof(LOCO)))) + return FALSE; + + if(!(pColPriv = malloc(sizeof(CMapColormapRec)))) { + free(colors); + return FALSE; + } + + dixSetPrivate(&pmap->devPrivates, CMapColormapKey, pColPriv); + + pColPriv->numColors = numColors; + pColPriv->colors = colors; + pColPriv->recalculate = TRUE; + pColPriv->overscan = -1; + + /* add map to list */ + pLink = malloc(sizeof(CMapLink)); + if(pLink) { + pLink->cmap = pmap; + pLink->next = pScreenPriv->maps; + pScreenPriv->maps = pLink; + } + + return TRUE; +} + +static Bool +CMapCreateColormap (ColormapPtr pmap) +{ + ScreenPtr pScreen = pmap->pScreen; + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, CMapScreenKey); + Bool ret = FALSE; + + pScreen->CreateColormap = pScreenPriv->CreateColormap; + if((*pScreen->CreateColormap)(pmap)) { + if(CMapAllocateColormapPrivate(pmap)) + ret = TRUE; + } + pScreen->CreateColormap = CMapCreateColormap; + + return ret; +} + +static void +CMapDestroyColormap (ColormapPtr cmap) +{ + ScreenPtr pScreen = cmap->pScreen; + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, CMapScreenKey); + CMapColormapPtr pColPriv = (CMapColormapPtr)dixLookupPrivate( + &cmap->devPrivates, CMapColormapKey); + CMapLinkPtr prevLink = NULL, pLink = pScreenPriv->maps; + + if(pColPriv) { + free(pColPriv->colors); + free(pColPriv); + } + + /* remove map from list */ + while(pLink) { + if(pLink->cmap == cmap) { + if(prevLink) + prevLink->next = pLink->next; + else + pScreenPriv->maps = pLink->next; + free(pLink); + break; + } + prevLink = pLink; + pLink = pLink->next; + } + + if(pScreenPriv->DestroyColormap) { + pScreen->DestroyColormap = pScreenPriv->DestroyColormap; + (*pScreen->DestroyColormap)(cmap); + pScreen->DestroyColormap = CMapDestroyColormap; + } +} + + + +static void +CMapStoreColors( + ColormapPtr pmap, + int ndef, + xColorItem *pdefs +){ + ScreenPtr pScreen = pmap->pScreen; + VisualPtr pVisual = pmap->pVisual; + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, CMapScreenKey); + int *indices = pScreenPriv->PreAllocIndices; + int num = ndef; + + /* At the moment this isn't necessary since there's nobody below us */ + pScreen->StoreColors = pScreenPriv->StoreColors; + (*pScreen->StoreColors)(pmap, ndef, pdefs); + pScreen->StoreColors = CMapStoreColors; + + /* should never get here for these */ + if( (pVisual->class == TrueColor) || + (pVisual->class == StaticColor) || + (pVisual->class == StaticGray)) + return; + + if(pVisual->class == DirectColor) { + CMapColormapPtr pColPriv = (CMapColormapPtr)dixLookupPrivate( + &pmap->devPrivates, CMapColormapKey); + int i; + + if (CMapColormapUseMax(pVisual, pScreenPriv)) { + int index; + + num = 0; + while(ndef--) { + if(pdefs[ndef].flags & DoRed) { + index = (pdefs[ndef].pixel & pVisual->redMask) >> + pVisual->offsetRed; + i = num; + while(i--) + if(indices[i] == index) break; + if(i == -1) + indices[num++] = index; + } + if(pdefs[ndef].flags & DoGreen) { + index = (pdefs[ndef].pixel & pVisual->greenMask) >> + pVisual->offsetGreen; + i = num; + while(i--) + if(indices[i] == index) break; + if(i == -1) + indices[num++] = index; + } + if(pdefs[ndef].flags & DoBlue) { + index = (pdefs[ndef].pixel & pVisual->blueMask) >> + pVisual->offsetBlue; + i = num; + while(i--) + if(indices[i] == index) break; + if(i == -1) + indices[num++] = index; + } + } + + } else { + /* not really as overkill as it seems */ + num = pColPriv->numColors; + for(i = 0; i < pColPriv->numColors; i++) + indices[i] = i; + } + } else { + while(ndef--) + indices[ndef] = pdefs[ndef].pixel; + } + + CMapRefreshColors(pmap, num, indices); +} + + +static void +CMapInstallColormap(ColormapPtr pmap) +{ + ScreenPtr pScreen = pmap->pScreen; + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, CMapScreenKey); + + if (pmap == GetInstalledmiColormap(pmap->pScreen)) + return; + + pScreen->InstallColormap = pScreenPriv->InstallColormap; + (*pScreen->InstallColormap)(pmap); + pScreen->InstallColormap = CMapInstallColormap; + + /* Important. We let the lower layers, namely DGA, + overwrite the choice of Colormap to install */ + if (GetInstalledmiColormap(pmap->pScreen)) + pmap = GetInstalledmiColormap(pmap->pScreen); + + if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) && + (pmap->pVisual->class == TrueColor) && + CMapColormapUseMax(pmap->pVisual, pScreenPriv)) + return; + + if(LOAD_PALETTE(pmap)) + CMapReinstallMap(pmap); +} + + +/**** ScrnInfoRec functions ****/ + +static Bool +CMapEnterVT(int index, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[index]; + ScreenPtr pScreen = screenInfo.screens[index]; + Bool ret; + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, CMapScreenKey); + + pScrn->EnterVT = pScreenPriv->EnterVT; + ret = (*pScreenPriv->EnterVT)(index, flags); + pScreenPriv->EnterVT = pScrn->EnterVT; + pScrn->EnterVT = CMapEnterVT; + if(ret) { + if(GetInstalledmiColormap(pScreen)) + CMapReinstallMap(GetInstalledmiColormap(pScreen)); + return TRUE; + } + return FALSE; +} + + +static Bool +CMapSwitchMode(int index, DisplayModePtr mode, int flags) +{ + ScreenPtr pScreen = screenInfo.screens[index]; + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, CMapScreenKey); + + if((*pScreenPriv->SwitchMode)(index, mode, flags)) { + if(GetInstalledmiColormap(pScreen)) + CMapReinstallMap(GetInstalledmiColormap(pScreen)); + return TRUE; + } + return FALSE; +} + +#ifdef XFreeXDGA +static int +CMapSetDGAMode(int index, int num, DGADevicePtr dev) +{ + ScreenPtr pScreen = screenInfo.screens[index]; + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, CMapScreenKey); + int ret; + + ret = (*pScreenPriv->SetDGAMode)(index, num, dev); + + pScreenPriv->isDGAmode = DGAActive(index); + + if(!pScreenPriv->isDGAmode && GetInstalledmiColormap(pScreen) + && xf86Screens[pScreen->myNum]->vtSema) + CMapReinstallMap(GetInstalledmiColormap(pScreen)); + + return ret; +} +#endif + + +/**** Utilities ****/ + +static void +CMapReinstallMap(ColormapPtr pmap) +{ + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pmap->pScreen->devPrivates, CMapScreenKey); + CMapColormapPtr cmapPriv = (CMapColormapPtr)dixLookupPrivate( + &pmap->devPrivates, CMapColormapKey); + ScrnInfoPtr pScrn = xf86Screens[pmap->pScreen->myNum]; + int i = cmapPriv->numColors; + int *indices = pScreenPriv->PreAllocIndices; + + while(i--) + indices[i] = i; + + if(cmapPriv->recalculate) + CMapRefreshColors(pmap, cmapPriv->numColors, indices); + else { + (*pScrn->LoadPalette)(pScrn, cmapPriv->numColors, + indices, cmapPriv->colors, pmap->pVisual); + if (pScrn->SetOverscan) { +#ifdef DEBUGOVERSCAN + ErrorF("SetOverscan() called from CMapReinstallMap\n"); +#endif + pScrn->SetOverscan(pScrn, cmapPriv->overscan); + } + } + + cmapPriv->recalculate = FALSE; +} + + +static void +CMapRefreshColors(ColormapPtr pmap, int defs, int* indices) +{ + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pmap->pScreen->devPrivates, CMapScreenKey); + CMapColormapPtr pColPriv = (CMapColormapPtr)dixLookupPrivate( + &pmap->devPrivates, CMapColormapKey); + VisualPtr pVisual = pmap->pVisual; + ScrnInfoPtr pScrn = xf86Screens[pmap->pScreen->myNum]; + int numColors, i; + LOCO *gamma, *colors; + EntryPtr entry; + int reds, greens, blues, maxValue, index, shift; + + numColors = pColPriv->numColors; + shift = 16 - pScreenPriv->sigRGBbits; + maxValue = (1 << pScreenPriv->sigRGBbits) - 1; + gamma = pScreenPriv->gamma; + colors = pColPriv->colors; + + reds = pVisual->redMask >> pVisual->offsetRed; + greens = pVisual->greenMask >> pVisual->offsetGreen; + blues = pVisual->blueMask >> pVisual->offsetBlue; + + switch(pVisual->class) { + case StaticGray: + for(i = 0; i < numColors; i++) { + index = (i+1) * maxValue / numColors; + colors[i].red = gamma[index].red; + colors[i].green = gamma[index].green; + colors[i].blue = gamma[index].blue; + } + break; + case TrueColor: + if (CMapColormapUseMax(pVisual, pScreenPriv)) { + for(i = 0; i <= reds; i++) + colors[i].red = gamma[i * maxValue / reds].red; + for(i = 0; i <= greens; i++) + colors[i].green = gamma[i * maxValue / greens].green; + for(i = 0; i <= blues; i++) + colors[i].blue = gamma[i * maxValue / blues].blue; + break; + } + for(i = 0; i < numColors; i++) { + colors[i].red = gamma[((i >> pVisual->offsetRed) & reds) * + maxValue / reds].red; + colors[i].green = gamma[((i >> pVisual->offsetGreen) & greens) * + maxValue / greens].green; + colors[i].blue = gamma[((i >> pVisual->offsetBlue) & blues) * + maxValue / blues].blue; + } + break; + case StaticColor: + case PseudoColor: + case GrayScale: + for(i = 0; i < defs; i++) { + index = indices[i]; + entry = (EntryPtr)&pmap->red[index]; + + if(entry->fShared) { + colors[index].red = + gamma[entry->co.shco.red->color >> shift].red; + colors[index].green = + gamma[entry->co.shco.green->color >> shift].green; + colors[index].blue = + gamma[entry->co.shco.blue->color >> shift].blue; + } else { + colors[index].red = + gamma[entry->co.local.red >> shift].red; + colors[index].green = + gamma[entry->co.local.green >> shift].green; + colors[index].blue = + gamma[entry->co.local.blue >> shift].blue; + } + } + break; + case DirectColor: + if (CMapColormapUseMax(pVisual, pScreenPriv)) { + for(i = 0; i < defs; i++) { + index = indices[i]; + if(index <= reds) + colors[index].red = + gamma[pmap->red[index].co.local.red >> shift].red; + if(index <= greens) + colors[index].green = + gamma[pmap->green[index].co.local.green >> shift].green; + if(index <= blues) + colors[index].blue = + gamma[pmap->blue[index].co.local.blue >> shift].blue; + + } + break; + } + for(i = 0; i < defs; i++) { + index = indices[i]; + + colors[index].red = gamma[pmap->red[ + (index >> pVisual->offsetRed) & reds + ].co.local.red >> shift].red; + colors[index].green = gamma[pmap->green[ + (index >> pVisual->offsetGreen) & greens + ].co.local.green >> shift].green; + colors[index].blue = gamma[pmap->blue[ + (index >> pVisual->offsetBlue) & blues + ].co.local.blue >> shift].blue; + } + break; + } + + + if(LOAD_PALETTE(pmap)) + (*pScrn->LoadPalette)(pScreenPriv->pScrn, defs, indices, + colors, pmap->pVisual); + + if (pScrn->SetOverscan) + CMapSetOverscan(pmap, defs, indices); + +} + +static Bool +CMapCompareColors(LOCO *color1, LOCO *color2) +{ + /* return TRUE if the color1 is "closer" to black than color2 */ +#ifdef DEBUGOVERSCAN + ErrorF("#%02x%02x%02x vs #%02x%02x%02x (%d vs %d)\n", + color1->red, color1->green, color1->blue, + color2->red, color2->green, color2->blue, + color1->red + color1->green + color1->blue, + color2->red + color2->green + color2->blue); +#endif + return (color1->red + color1->green + color1->blue < + color2->red + color2->green + color2->blue); +} + +static void +CMapSetOverscan(ColormapPtr pmap, int defs, int *indices) +{ + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pmap->pScreen->devPrivates, CMapScreenKey); + CMapColormapPtr pColPriv = (CMapColormapPtr)dixLookupPrivate( + &pmap->devPrivates, CMapColormapKey); + ScrnInfoPtr pScrn = xf86Screens[pmap->pScreen->myNum]; + VisualPtr pVisual = pmap->pVisual; + int i; + LOCO *colors; + int index; + Bool newOverscan = FALSE; + int overscan, tmpOverscan; + + colors = pColPriv->colors; + overscan = pColPriv->overscan; + + /* + * Search for a new overscan index in the following cases: + * + * - The index hasn't yet been initialised. In this case search + * for an index that is black or a close match to black. + * + * - The colour of the old index is changed. In this case search + * all indices for a black or close match to black. + * + * - The colour of the old index wasn't black. In this case only + * search the indices that were changed for a better match to black. + */ + + switch (pVisual->class) { + case StaticGray: + case TrueColor: + /* Should only come here once. Initialise the overscan index to 0 */ + overscan = 0; + newOverscan = TRUE; + break; + case StaticColor: + /* + * Only come here once, but search for the overscan in the same way + * as for the other cases. + */ + case DirectColor: + case PseudoColor: + case GrayScale: + if (overscan < 0 || overscan > pScreenPriv->maxColors - 1) { + /* Uninitialised */ + newOverscan = TRUE; + } else { + /* Check if the overscan was changed */ + for (i = 0; i < defs; i++) { + index = indices[i]; + if (index == overscan) { + newOverscan = TRUE; + break; + } + } + } + if (newOverscan) { + /* The overscan is either uninitialised or it has been changed */ + + if (overscan < 0 || overscan > pScreenPriv->maxColors - 1) + tmpOverscan = pScreenPriv->maxColors - 1; + else + tmpOverscan = overscan; + + /* search all entries for a close match to black */ + for (i = pScreenPriv->maxColors - 1; i >= 0; i--) { + if (colors[i].red == 0 && colors[i].green == 0 && + colors[i].blue == 0) { + overscan = i; +#ifdef DEBUGOVERSCAN + ErrorF("Black found at index 0x%02x\n", i); +#endif + break; + } else { +#ifdef DEBUGOVERSCAN + ErrorF("0x%02x: ", i); +#endif + if (CMapCompareColors(&colors[i], &colors[tmpOverscan])) { + tmpOverscan = i; +#ifdef DEBUGOVERSCAN + ErrorF("possible \"Black\" at index 0x%02x\n", i); +#endif + } + } + } + if (i < 0) + overscan = tmpOverscan; + } else { + /* Check of the old overscan wasn't black */ + if (colors[overscan].red != 0 || colors[overscan].green != 0 || + colors[overscan].blue != 0) { + int oldOverscan = tmpOverscan = overscan; + /* See of there is now a better match */ + for (i = 0; i < defs; i++) { + index = indices[i]; + if (colors[index].red == 0 && colors[index].green == 0 && + colors[index].blue == 0) { + overscan = index; +#ifdef DEBUGOVERSCAN + ErrorF("Black found at index 0x%02x\n", index); +#endif + break; + } else { +#ifdef DEBUGOVERSCAN + ErrorF("0x%02x: ", index); +#endif + if (CMapCompareColors(&colors[index], + &colors[tmpOverscan])) { + tmpOverscan = index; +#ifdef DEBUGOVERSCAN + ErrorF("possible \"Black\" at index 0x%02x\n", + index); +#endif + } + } + } + if (i == defs) + overscan = tmpOverscan; + if (overscan != oldOverscan) + newOverscan = TRUE; + } + } + break; + } + if (newOverscan) { + pColPriv->overscan = overscan; + if (LOAD_PALETTE(pmap)) { +#ifdef DEBUGOVERSCAN + ErrorF("SetOverscan() called from CmapSetOverscan\n"); +#endif + pScrn->SetOverscan(pScreenPriv->pScrn, overscan); + } + } +} + +static void +CMapUnwrapScreen(ScreenPtr pScreen) +{ + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, CMapScreenKey); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + pScreen->CloseScreen = pScreenPriv->CloseScreen; + pScreen->CreateColormap = pScreenPriv->CreateColormap; + pScreen->DestroyColormap = pScreenPriv->DestroyColormap; + pScreen->InstallColormap = pScreenPriv->InstallColormap; + pScreen->StoreColors = pScreenPriv->StoreColors; + + pScrn->EnterVT = pScreenPriv->EnterVT; + pScrn->SwitchMode = pScreenPriv->SwitchMode; + pScrn->SetDGAMode = pScreenPriv->SetDGAMode; + pScrn->ChangeGamma = pScreenPriv->ChangeGamma; + + free(pScreenPriv->gamma); + free(pScreenPriv->PreAllocIndices); + free(pScreenPriv); +} + + +static void +ComputeGamma(CMapScreenPtr priv) +{ + int elements = priv->gammaElements - 1; + double RedGamma, GreenGamma, BlueGamma; + int i; + +#ifndef DONT_CHECK_GAMMA + /* This check is to catch drivers that are not initialising pScrn->gamma */ + if (priv->pScrn->gamma.red < GAMMA_MIN || + priv->pScrn->gamma.red > GAMMA_MAX || + priv->pScrn->gamma.green < GAMMA_MIN || + priv->pScrn->gamma.green > GAMMA_MAX || + priv->pScrn->gamma.blue < GAMMA_MIN || + priv->pScrn->gamma.blue > GAMMA_MAX) { + + xf86DrvMsgVerb(priv->pScrn->scrnIndex, X_WARNING, 0, + "The %s driver didn't call xf86SetGamma() to initialise\n" + "\tthe gamma values.\n", priv->pScrn->driverName); + xf86DrvMsgVerb(priv->pScrn->scrnIndex, X_WARNING, 0, + "PLEASE FIX THE `%s' DRIVER!\n", priv->pScrn->driverName); + priv->pScrn->gamma.red = 1.0; + priv->pScrn->gamma.green = 1.0; + priv->pScrn->gamma.blue = 1.0; + } +#endif + + RedGamma = 1.0 / (double)priv->pScrn->gamma.red; + GreenGamma = 1.0 / (double)priv->pScrn->gamma.green; + BlueGamma = 1.0 / (double)priv->pScrn->gamma.blue; + + for(i = 0; i <= elements; i++) { + if(RedGamma == 1.0) + priv->gamma[i].red = i; + else + priv->gamma[i].red = (CARD16)(pow((double)i/(double)elements, + RedGamma) * (double)elements + 0.5); + + if(GreenGamma == 1.0) + priv->gamma[i].green = i; + else + priv->gamma[i].green = (CARD16)(pow((double)i/(double)elements, + GreenGamma) * (double)elements + 0.5); + + if(BlueGamma == 1.0) + priv->gamma[i].blue = i; + else + priv->gamma[i].blue = (CARD16)(pow((double)i/(double)elements, + BlueGamma) * (double)elements + 0.5); + } +} + + +int +CMapChangeGamma( + int index, + Gamma gamma +){ + int ret = Success; + ScrnInfoPtr pScrn = xf86Screens[index]; + ScreenPtr pScreen = pScrn->pScreen; + CMapColormapPtr pColPriv; + CMapScreenPtr pScreenPriv; + CMapLinkPtr pLink; + + /* Is this sufficient checking ? */ + if(!CMapScreenKeyRegistered) + return BadImplementation; + + pScreenPriv = (CMapScreenPtr)dixLookupPrivate(&pScreen->devPrivates, + CMapScreenKey); + if(!pScreenPriv) + return BadImplementation; + + if (gamma.red < GAMMA_MIN || gamma.red > GAMMA_MAX || + gamma.green < GAMMA_MIN || gamma.green > GAMMA_MAX || + gamma.blue < GAMMA_MIN || gamma.blue > GAMMA_MAX) + return BadValue; + + pScrn->gamma.red = gamma.red; + pScrn->gamma.green = gamma.green; + pScrn->gamma.blue = gamma.blue; + + ComputeGamma(pScreenPriv); + + /* mark all colormaps on this screen */ + pLink = pScreenPriv->maps; + while(pLink) { + pColPriv = (CMapColormapPtr)dixLookupPrivate(&pLink->cmap->devPrivates, + CMapColormapKey); + pColPriv->recalculate = TRUE; + pLink = pLink->next; + } + + if(GetInstalledmiColormap(pScreen) && + ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || + pScrn->vtSema || pScreenPriv->isDGAmode)) { + ColormapPtr pMap = GetInstalledmiColormap(pScreen); + + if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) && + (pMap->pVisual->class == TrueColor) && + CMapColormapUseMax(pMap->pVisual, pScreenPriv)) { + + /* if the current map doesn't have a palette look + for another map to change the gamma on. */ + + pLink = pScreenPriv->maps; + while(pLink) { + if(pLink->cmap->pVisual->class == PseudoColor) + break; + pLink = pLink->next; + } + + if(pLink) { + /* need to trick CMapRefreshColors() into thinking + this is the currently installed map */ + SetInstalledmiColormap(pScreen, pLink->cmap); + CMapReinstallMap(pLink->cmap); + SetInstalledmiColormap(pScreen, pMap); + } + } else + CMapReinstallMap(pMap); + } + + pScrn->ChangeGamma = pScreenPriv->ChangeGamma; + if (pScrn->ChangeGamma) + ret = pScrn->ChangeGamma(index, gamma); + pScrn->ChangeGamma = CMapChangeGamma; + + return ret; +} + + +static void +ComputeGammaRamp ( + CMapScreenPtr priv, + unsigned short *red, + unsigned short *green, + unsigned short *blue +){ + int elements = priv->gammaElements; + LOCO *entry = priv->gamma; + int shift = 16 - priv->sigRGBbits; + + while(elements--) { + entry->red = *(red++) >> shift; + entry->green = *(green++) >> shift; + entry->blue = *(blue++) >> shift; + entry++; + } +} + +int +xf86ChangeGammaRamp( + ScreenPtr pScreen, + int size, + unsigned short *red, + unsigned short *green, + unsigned short *blue +){ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + CMapColormapPtr pColPriv; + CMapScreenPtr pScreenPriv; + CMapLinkPtr pLink; + + if (xf86_crtc_supports_gamma(pScrn)) { + RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); + + if (crtc) { + if (crtc->gammaSize != size) + return BadValue; + + RRCrtcGammaSet(crtc, red, green, blue); + + return Success; + } + } + + if(!CMapScreenKeyRegistered) + return BadImplementation; + + pScreenPriv = (CMapScreenPtr)dixLookupPrivate(&pScreen->devPrivates, + CMapScreenKey); + if(!pScreenPriv) + return BadImplementation; + + if(pScreenPriv->gammaElements != size) + return BadValue; + + ComputeGammaRamp(pScreenPriv, red, green, blue); + + /* mark all colormaps on this screen */ + pLink = pScreenPriv->maps; + while(pLink) { + pColPriv = (CMapColormapPtr)dixLookupPrivate(&pLink->cmap->devPrivates, + CMapColormapKey); + pColPriv->recalculate = TRUE; + pLink = pLink->next; + } + + if(GetInstalledmiColormap(pScreen) && + ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || + pScrn->vtSema || pScreenPriv->isDGAmode)) { + ColormapPtr pMap = GetInstalledmiColormap(pScreen); + + if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) && + (pMap->pVisual->class == TrueColor) && + CMapColormapUseMax(pMap->pVisual, pScreenPriv)) { + + /* if the current map doesn't have a palette look + for another map to change the gamma on. */ + + pLink = pScreenPriv->maps; + while(pLink) { + if(pLink->cmap->pVisual->class == PseudoColor) + break; + pLink = pLink->next; + } + + if(pLink) { + /* need to trick CMapRefreshColors() into thinking + this is the currently installed map */ + SetInstalledmiColormap(pScreen, pLink->cmap); + CMapReinstallMap(pLink->cmap); + SetInstalledmiColormap(pScreen, pMap); + } + } else + CMapReinstallMap(pMap); + } + + return Success; +} + +int +xf86GetGammaRampSize(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + CMapScreenPtr pScreenPriv; + + if (xf86_crtc_supports_gamma(pScrn)) { + RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); + + if (crtc) + return crtc->gammaSize; + } + + if(!CMapScreenKeyRegistered) return 0; + + pScreenPriv = (CMapScreenPtr)dixLookupPrivate(&pScreen->devPrivates, + CMapScreenKey); + if(!pScreenPriv) return 0; + + return pScreenPriv->gammaElements; +} + +int +xf86GetGammaRamp( + ScreenPtr pScreen, + int size, + unsigned short *red, + unsigned short *green, + unsigned short *blue +){ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + CMapScreenPtr pScreenPriv; + LOCO *entry; + int shift, sigbits; + + if (xf86_crtc_supports_gamma(pScrn)) { + RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); + + if (crtc) { + if (crtc->gammaSize < size) + return BadValue; + + if (!RRCrtcGammaGet(crtc)) + return BadImplementation; + + memcpy(red, crtc->gammaRed, size * sizeof(*red)); + memcpy(green, crtc->gammaGreen, size * sizeof(*green)); + memcpy(blue, crtc->gammaBlue, size * sizeof(*blue)); + + return Success; + } + } + + if(!CMapScreenKeyRegistered) + return BadImplementation; + + pScreenPriv = (CMapScreenPtr)dixLookupPrivate(&pScreen->devPrivates, + CMapScreenKey); + if(!pScreenPriv) + return BadImplementation; + + if(size > pScreenPriv->gammaElements) + return BadValue; + + entry = pScreenPriv->gamma; + sigbits = pScreenPriv->sigRGBbits; + + while(size--) { + *red = entry->red << (16 - sigbits); + *green = entry->green << (16 - sigbits); + *blue = entry->blue << (16 - sigbits); + shift = sigbits; + while(shift < 16) { + *red |= *red >> shift; + *green |= *green >> shift; + *blue |= *blue >> shift; + shift += sigbits; + } + red++; green++; blue++; + entry++; + } + + return Success; +} + +int +xf86ChangeGamma( + ScreenPtr pScreen, + Gamma gamma +){ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + if(pScrn->ChangeGamma) + return (*pScrn->ChangeGamma)(pScreen->myNum, gamma); + + return BadImplementation; +} diff --git a/hw/xfree86/common/xf86cmap.h b/hw/xfree86/common/xf86cmap.h new file mode 100644 index 0000000..649f078 --- /dev/null +++ b/hw/xfree86/common/xf86cmap.h @@ -0,0 +1,79 @@ + +/* + * Copyright (c) 1998-2001 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +#ifndef _XF86CMAP_H +#define _XF86CMAP_H + +#include "xf86str.h" +#include "colormapst.h" + +#define CMAP_PALETTED_TRUECOLOR 0x0000001 +#define CMAP_RELOAD_ON_MODE_SWITCH 0x0000002 +#define CMAP_LOAD_EVEN_IF_OFFSCREEN 0x0000004 + +extern _X_EXPORT Bool xf86HandleColormaps( + ScreenPtr pScreen, + int maxCol, + int sigRGBbits, + xf86LoadPaletteProc *loadPalette, + xf86SetOverscanProc *setOverscan, + unsigned int flags +); + +extern _X_EXPORT Bool xf86ColormapAllocatePrivates( + ScrnInfoPtr pScrn +); + +extern _X_EXPORT int +xf86ChangeGamma( + ScreenPtr pScreen, + Gamma newGamma +); + +extern _X_EXPORT int +xf86ChangeGammaRamp( + ScreenPtr pScreen, + int size, + unsigned short *red, + unsigned short *green, + unsigned short *blue +); + +extern _X_EXPORT int xf86GetGammaRampSize(ScreenPtr pScreen); + +extern _X_EXPORT int +xf86GetGammaRamp( + ScreenPtr pScreen, + int size, + unsigned short *red, + unsigned short *green, + unsigned short *blue +); + +#endif /* _XF86CMAP_H */ + diff --git a/hw/xfree86/common/xf86fbBus.c b/hw/xfree86/common/xf86fbBus.c new file mode 100644 index 0000000..059e378 --- /dev/null +++ b/hw/xfree86/common/xf86fbBus.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2000-2001 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * This file contains the interfaces to the bus-specific code + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <ctype.h> +#include <stdlib.h> +#include <unistd.h> +#include <X11/X.h> +#include "os.h" +#include "xf86.h" +#include "xf86Priv.h" + +#include "xf86Bus.h" + +#define XF86_OS_PRIVS +#include "xf86_OSproc.h" + +Bool fbSlotClaimed = FALSE; + +int +xf86ClaimFbSlot(DriverPtr drvp, int chipset, GDevPtr dev, Bool active) +{ + EntityPtr p; + int num; + + if (pciSlotClaimed) + return -1; +#if defined(__sparc__) || defined (__sparc64__) + if (sbusSlotClaimed) + return -1; +#endif + + num = xf86AllocateEntity(); + p = xf86Entities[num]; + p->driver = drvp; + p->chipset = 0; + p->bus.type = BUS_NONE; + p->active = active; + p->inUse = FALSE; + xf86AddDevToEntity(num, dev); + + fbSlotClaimed = TRUE; + return num; +} + +/* + * Get the list of FB "slots" claimed by a screen + */ +int +xf86GetFbInfoForScreen(int scrnIndex) +{ + int num = 0; + int i; + EntityPtr p; + + for (i = 0; i < xf86Screens[scrnIndex]->numEntities; i++) { + p = xf86Entities[xf86Screens[scrnIndex]->entityList[i]]; + if (p->bus.type == BUS_NONE) { + num++; + } + } + return num; +} diff --git a/hw/xfree86/common/xf86fbman.c b/hw/xfree86/common/xf86fbman.c new file mode 100644 index 0000000..e60e5c4 --- /dev/null +++ b/hw/xfree86/common/xf86fbman.c @@ -0,0 +1,1446 @@ + +/* + * Copyright (c) 1998-2001 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "misc.h" +#include "xf86.h" + +#include <X11/X.h> +#include "scrnintstr.h" +#include "regionstr.h" +#include "xf86fbman.h" + +/* +#define DEBUG +*/ + +static DevPrivateKeyRec xf86FBManagerKeyRec; +static DevPrivateKey xf86FBManagerKey; + +Bool xf86RegisterOffscreenManager( + ScreenPtr pScreen, + FBManagerFuncsPtr funcs +){ + + xf86FBManagerKey = &xf86FBManagerKeyRec; + + if (!dixRegisterPrivateKey(&xf86FBManagerKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + dixSetPrivate(&pScreen->devPrivates, xf86FBManagerKey, funcs); + + return TRUE; +} + + +Bool +xf86FBManagerRunning(ScreenPtr pScreen) +{ + if (xf86FBManagerKey == NULL) + return FALSE; + + if(!dixLookupPrivate(&pScreen->devPrivates, xf86FBManagerKey)) + return FALSE; + + return TRUE; +} + +Bool +xf86RegisterFreeBoxCallback( + ScreenPtr pScreen, + FreeBoxCallbackProcPtr FreeBoxCallback, + pointer devPriv +){ + FBManagerFuncsPtr funcs; + + if(xf86FBManagerKey == NULL) + return FALSE; + if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBManagerKey))) + return FALSE; + + return (*funcs->RegisterFreeBoxCallback)(pScreen, FreeBoxCallback, devPriv); +} + + +FBAreaPtr +xf86AllocateOffscreenArea( + ScreenPtr pScreen, + int w, int h, + int gran, + MoveAreaCallbackProcPtr moveCB, + RemoveAreaCallbackProcPtr removeCB, + pointer privData +){ + FBManagerFuncsPtr funcs; + + if(xf86FBManagerKey == NULL) + return NULL; + if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBManagerKey))) + return NULL; + + return (*funcs->AllocateOffscreenArea)( + pScreen, w, h, gran, moveCB, removeCB, privData); +} + + +FBLinearPtr +xf86AllocateOffscreenLinear( + ScreenPtr pScreen, + int length, + int gran, + MoveLinearCallbackProcPtr moveCB, + RemoveLinearCallbackProcPtr removeCB, + pointer privData +){ + FBManagerFuncsPtr funcs; + + if(xf86FBManagerKey == NULL) + return NULL; + if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBManagerKey))) + return NULL; + + return (*funcs->AllocateOffscreenLinear)( + pScreen, length, gran, moveCB, removeCB, privData); +} + + +void +xf86FreeOffscreenArea(FBAreaPtr area) +{ + FBManagerFuncsPtr funcs; + + if(!area) return; + + if(xf86FBManagerKey == NULL) + return; + if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate( + &area->pScreen->devPrivates, xf86FBManagerKey))) + return; + + (*funcs->FreeOffscreenArea)(area); + + return; +} + + +void +xf86FreeOffscreenLinear(FBLinearPtr linear) +{ + FBManagerFuncsPtr funcs; + + if(!linear) return; + + if(xf86FBManagerKey == NULL) + return; + if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate( + &linear->pScreen->devPrivates, xf86FBManagerKey))) + return; + + (*funcs->FreeOffscreenLinear)(linear); + + return; +} + + +Bool +xf86ResizeOffscreenArea( + FBAreaPtr resize, + int w, int h +){ + FBManagerFuncsPtr funcs; + + if(!resize) return FALSE; + + if(xf86FBManagerKey == NULL) + return FALSE; + if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate( + &resize->pScreen->devPrivates, xf86FBManagerKey))) + return FALSE; + + return (*funcs->ResizeOffscreenArea)(resize, w, h); +} + +Bool +xf86ResizeOffscreenLinear( + FBLinearPtr resize, + int size +){ + FBManagerFuncsPtr funcs; + + if(!resize) return FALSE; + + if(xf86FBManagerKey == NULL) + return FALSE; + if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate( + &resize->pScreen->devPrivates, xf86FBManagerKey))) + return FALSE; + + return (*funcs->ResizeOffscreenLinear)(resize, size); +} + + +Bool +xf86QueryLargestOffscreenArea( + ScreenPtr pScreen, + int *w, int *h, + int gran, + int preferences, + int severity +){ + FBManagerFuncsPtr funcs; + + *w = 0; + *h = 0; + + if(xf86FBManagerKey == NULL) + return FALSE; + if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBManagerKey))) + return FALSE; + + return (*funcs->QueryLargestOffscreenArea)( + pScreen, w, h, gran, preferences, severity); +} + +Bool +xf86QueryLargestOffscreenLinear( + ScreenPtr pScreen, + int *size, + int gran, + int severity +){ + FBManagerFuncsPtr funcs; + + *size = 0; + + if(xf86FBManagerKey == NULL) + return FALSE; + if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBManagerKey))) + return FALSE; + + return (*funcs->QueryLargestOffscreenLinear)( + pScreen, size, gran, severity); +} + + +Bool +xf86PurgeUnlockedOffscreenAreas(ScreenPtr pScreen) +{ + FBManagerFuncsPtr funcs; + + if(xf86FBManagerKey == NULL) + return FALSE; + if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBManagerKey))) + return FALSE; + + return (*funcs->PurgeOffscreenAreas)(pScreen); +} + +/************************************************************\ + + Below is a specific implementation of an offscreen manager. + +\************************************************************/ + +static DevPrivateKeyRec xf86FBScreenKeyRec; +#define xf86FBScreenKey (&xf86FBScreenKeyRec) + +typedef struct _FBLink { + FBArea area; + struct _FBLink *next; +} FBLink, *FBLinkPtr; + +typedef struct _FBLinearLink { + FBLinear linear; + int free; /* need to add free here as FBLinear is publicly accessible */ + FBAreaPtr area; /* only used if allocation came from XY area */ + struct _FBLinearLink *next; +} FBLinearLink, *FBLinearLinkPtr; + + +typedef struct { + ScreenPtr pScreen; + RegionPtr InitialBoxes; + RegionPtr FreeBoxes; + FBLinkPtr UsedAreas; + int NumUsedAreas; + FBLinearLinkPtr LinearAreas; + CloseScreenProcPtr CloseScreen; + int NumCallbacks; + FreeBoxCallbackProcPtr *FreeBoxesUpdateCallback; + DevUnion *devPrivates; +} FBManager, *FBManagerPtr; + + +static void +SendCallFreeBoxCallbacks(FBManagerPtr offman) +{ + int i = offman->NumCallbacks; + + while(i--) { + (*offman->FreeBoxesUpdateCallback[i])( + offman->pScreen, offman->FreeBoxes, offman->devPrivates[i].ptr); + } +} + +static Bool +localRegisterFreeBoxCallback( + ScreenPtr pScreen, + FreeBoxCallbackProcPtr FreeBoxCallback, + pointer devPriv +){ + FBManagerPtr offman; + FreeBoxCallbackProcPtr *newCallbacks; + DevUnion *newPrivates; + + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + newCallbacks = realloc( offman->FreeBoxesUpdateCallback, + sizeof(FreeBoxCallbackProcPtr) * (offman->NumCallbacks + 1)); + + newPrivates = realloc(offman->devPrivates, + sizeof(DevUnion) * (offman->NumCallbacks + 1)); + + if(!newCallbacks || !newPrivates) + return FALSE; + + offman->FreeBoxesUpdateCallback = newCallbacks; + offman->devPrivates = newPrivates; + + offman->FreeBoxesUpdateCallback[offman->NumCallbacks] = FreeBoxCallback; + offman->devPrivates[offman->NumCallbacks].ptr = devPriv; + offman->NumCallbacks++; + + SendCallFreeBoxCallbacks(offman); + + return TRUE; +} + + +static FBAreaPtr +AllocateArea( + FBManagerPtr offman, + int w, int h, + int granularity, + MoveAreaCallbackProcPtr moveCB, + RemoveAreaCallbackProcPtr removeCB, + pointer privData +){ + ScreenPtr pScreen = offman->pScreen; + FBLinkPtr link = NULL; + FBAreaPtr area = NULL; + RegionRec NewReg; + int i, x = 0, num; + BoxPtr boxp; + + if(granularity <= 1) granularity = 0; + + boxp = RegionRects(offman->FreeBoxes); + num = RegionNumRects(offman->FreeBoxes); + + /* look through the free boxes */ + for(i = 0; i < num; i++, boxp++) { + x = boxp->x1; + if (granularity > 1) + x = ((x + granularity - 1) / granularity) * granularity; + + if(((boxp->y2 - boxp->y1) < h) || ((boxp->x2 - x) < w)) + continue; + + link = malloc(sizeof(FBLink)); + if(!link) return NULL; + + area = &(link->area); + link->next = offman->UsedAreas; + offman->UsedAreas = link; + offman->NumUsedAreas++; + break; + } + + /* try to boot a removeable one out if we are not expendable ourselves */ + if(!area && !removeCB) { + link = offman->UsedAreas; + + while(link) { + if(!link->area.RemoveAreaCallback) { + link = link->next; + continue; + } + + boxp = &(link->area.box); + x = boxp->x1; + if (granularity > 1) + x = ((x + granularity - 1) / granularity) * granularity; + + if(((boxp->y2 - boxp->y1) < h) || ((boxp->x2 - x) < w)) { + link = link->next; + continue; + } + + /* bye, bye */ + (*link->area.RemoveAreaCallback)(&link->area); + RegionInit(&NewReg, &(link->area.box), 1); + RegionUnion(offman->FreeBoxes, offman->FreeBoxes, &NewReg); + RegionUninit(&NewReg); + + area = &(link->area); + break; + } + } + + if(area) { + area->pScreen = pScreen; + area->granularity = granularity; + area->box.x1 = x; + area->box.x2 = x + w; + area->box.y1 = boxp->y1; + area->box.y2 = boxp->y1 + h; + area->MoveAreaCallback = moveCB; + area->RemoveAreaCallback = removeCB; + area->devPrivate.ptr = privData; + + RegionInit(&NewReg, &(area->box), 1); + RegionSubtract(offman->FreeBoxes, offman->FreeBoxes, &NewReg); + RegionUninit(&NewReg); + } + + return area; +} + +static FBAreaPtr +localAllocateOffscreenArea( + ScreenPtr pScreen, + int w, int h, + int gran, + MoveAreaCallbackProcPtr moveCB, + RemoveAreaCallbackProcPtr removeCB, + pointer privData +){ + FBManagerPtr offman; + FBAreaPtr area = NULL; + + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + if((area = AllocateArea(offman, w, h, gran, moveCB, removeCB, privData))) + SendCallFreeBoxCallbacks(offman); + + return area; +} + + +static void +localFreeOffscreenArea(FBAreaPtr area) +{ + FBManagerPtr offman; + FBLinkPtr pLink, pLinkPrev = NULL; + RegionRec FreedRegion; + ScreenPtr pScreen; + + pScreen = area->pScreen; + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + pLink = offman->UsedAreas; + if(!pLink) return; + + while(&(pLink->area) != area) { + pLinkPrev = pLink; + pLink = pLink->next; + if(!pLink) return; + } + + /* put the area back into the pool */ + RegionInit(&FreedRegion, &(pLink->area.box), 1); + RegionUnion(offman->FreeBoxes, offman->FreeBoxes, &FreedRegion); + RegionUninit(&FreedRegion); + + if(pLinkPrev) + pLinkPrev->next = pLink->next; + else offman->UsedAreas = pLink->next; + + free(pLink); + offman->NumUsedAreas--; + + SendCallFreeBoxCallbacks(offman); +} + + + +static Bool +localResizeOffscreenArea( + FBAreaPtr resize, + int w, int h +){ + FBManagerPtr offman; + ScreenPtr pScreen; + BoxRec OrigArea; + RegionRec FreedReg; + FBAreaPtr area = NULL; + FBLinkPtr pLink, newLink, pLinkPrev = NULL; + + pScreen = resize->pScreen; + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + /* find this link */ + if(!(pLink = offman->UsedAreas)) + return FALSE; + + while(&(pLink->area) != resize) { + pLinkPrev = pLink; + pLink = pLink->next; + if(!pLink) return FALSE; + } + + OrigArea.x1 = resize->box.x1; + OrigArea.x2 = resize->box.x2; + OrigArea.y1 = resize->box.y1; + OrigArea.y2 = resize->box.y2; + + /* if it's smaller, this is easy */ + + if((w <= (resize->box.x2 - resize->box.x1)) && + (h <= (resize->box.y2 - resize->box.y1))) { + RegionRec NewReg; + + resize->box.x2 = resize->box.x1 + w; + resize->box.y2 = resize->box.y1 + h; + + if((resize->box.y2 == OrigArea.y2) && + (resize->box.x2 == OrigArea.x2)) + return TRUE; + + RegionInit(&FreedReg, &OrigArea, 1); + RegionInit(&NewReg, &(resize->box), 1); + RegionSubtract(&FreedReg, &FreedReg, &NewReg); + RegionUnion(offman->FreeBoxes, offman->FreeBoxes, &FreedReg); + RegionUninit(&FreedReg); + RegionUninit(&NewReg); + + SendCallFreeBoxCallbacks(offman); + + return TRUE; + } + + + /* otherwise we remove the old region */ + + RegionInit(&FreedReg, &OrigArea, 1); + RegionUnion(offman->FreeBoxes, offman->FreeBoxes, &FreedReg); + + /* remove the old link */ + if(pLinkPrev) + pLinkPrev->next = pLink->next; + else offman->UsedAreas = pLink->next; + + /* and try to add a new one */ + + if((area = AllocateArea(offman, w, h, resize->granularity, + resize->MoveAreaCallback, resize->RemoveAreaCallback, + resize->devPrivate.ptr))) { + + /* copy data over to our link and replace the new with old */ + memcpy(resize, area, sizeof(FBArea)); + + pLinkPrev = NULL; + newLink = offman->UsedAreas; + + while(&(newLink->area) != area) { + pLinkPrev = newLink; + newLink = newLink->next; + } + + if(pLinkPrev) + pLinkPrev->next = newLink->next; + else offman->UsedAreas = newLink->next; + + pLink->next = offman->UsedAreas; + offman->UsedAreas = pLink; + + free(newLink); + + /* AllocateArea added one but we really only exchanged one */ + offman->NumUsedAreas--; + } else { + /* reinstate the old region */ + RegionSubtract(offman->FreeBoxes, offman->FreeBoxes, &FreedReg); + RegionUninit(&FreedReg); + + pLink->next = offman->UsedAreas; + offman->UsedAreas = pLink; + return FALSE; + } + + + RegionUninit(&FreedReg); + + SendCallFreeBoxCallbacks(offman); + + return TRUE; +} + +static Bool +localQueryLargestOffscreenArea( + ScreenPtr pScreen, + int *width, int *height, + int granularity, + int preferences, + int severity +){ + FBManagerPtr offman; + RegionPtr newRegion = NULL; + BoxPtr pbox; + int nbox; + int x, w, h, area, oldArea; + + *width = *height = oldArea = 0; + + if(granularity <= 1) granularity = 0; + + if((preferences < 0) || (preferences > 3)) + return FALSE; + + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + if(severity < 0) severity = 0; + if(severity > 2) severity = 2; + + switch(severity) { + case 2: + if(offman->NumUsedAreas) { + FBLinkPtr pLink; + RegionRec tmpRegion; + newRegion = RegionCreate(NULL, 1); + RegionCopy(newRegion, offman->InitialBoxes); + pLink = offman->UsedAreas; + + while(pLink) { + if(!pLink->area.RemoveAreaCallback) { + RegionInit(&tmpRegion, &(pLink->area.box), 1); + RegionSubtract(newRegion, newRegion, &tmpRegion); + RegionUninit(&tmpRegion); + } + pLink = pLink->next; + } + + nbox = RegionNumRects(newRegion); + pbox = RegionRects(newRegion); + break; + } + case 1: + if(offman->NumUsedAreas) { + FBLinkPtr pLink; + RegionRec tmpRegion; + newRegion = RegionCreate(NULL, 1); + RegionCopy(newRegion, offman->FreeBoxes); + pLink = offman->UsedAreas; + + while(pLink) { + if(pLink->area.RemoveAreaCallback) { + RegionInit(&tmpRegion, &(pLink->area.box), 1); + RegionAppend(newRegion, &tmpRegion); + RegionUninit(&tmpRegion); + } + pLink = pLink->next; + } + + nbox = RegionNumRects(newRegion); + pbox = RegionRects(newRegion); + break; + } + default: + nbox = RegionNumRects(offman->FreeBoxes); + pbox = RegionRects(offman->FreeBoxes); + break; + } + + while(nbox--) { + x = pbox->x1; + if (granularity > 1) + x = ((x + granularity - 1) / granularity) * granularity; + + w = pbox->x2 - x; + h = pbox->y2 - pbox->y1; + area = w * h; + + if(w > 0) { + Bool gotIt = FALSE; + switch(preferences) { + case FAVOR_AREA_THEN_WIDTH: + if((area > oldArea) || ((area == oldArea) && (w > *width))) + gotIt = TRUE; + break; + case FAVOR_AREA_THEN_HEIGHT: + if((area > oldArea) || ((area == oldArea) && (h > *height))) + gotIt = TRUE; + break; + case FAVOR_WIDTH_THEN_AREA: + if((w > *width) || ((w == *width) && (area > oldArea))) + gotIt = TRUE; + break; + case FAVOR_HEIGHT_THEN_AREA: + if((h > *height) || ((h == *height) && (area > oldArea))) + gotIt = TRUE; + break; + } + if(gotIt) { + *width = w; + *height = h; + oldArea = area; + } + } + pbox++; + } + + if(newRegion) + RegionDestroy(newRegion); + + return TRUE; +} + +static Bool +localPurgeUnlockedOffscreenAreas(ScreenPtr pScreen) +{ + FBManagerPtr offman; + FBLinkPtr pLink, tmp, pPrev = NULL; + RegionRec FreedRegion; + Bool anyUsed = FALSE; + + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + pLink = offman->UsedAreas; + if(!pLink) return TRUE; + + while(pLink) { + if(pLink->area.RemoveAreaCallback) { + (*pLink->area.RemoveAreaCallback)(&pLink->area); + + RegionInit(&FreedRegion, &(pLink->area.box), 1); + RegionAppend(offman->FreeBoxes, &FreedRegion); + RegionUninit(&FreedRegion); + + if(pPrev) + pPrev->next = pLink->next; + else offman->UsedAreas = pLink->next; + + tmp = pLink; + pLink = pLink->next; + free(tmp); + offman->NumUsedAreas--; + anyUsed = TRUE; + } else { + pPrev = pLink; + pLink = pLink->next; + } + } + + if(anyUsed) { + RegionValidate(offman->FreeBoxes, &anyUsed); + SendCallFreeBoxCallbacks(offman); + } + + return TRUE; +} + +static void +LinearMoveCBWrapper(FBAreaPtr from, FBAreaPtr to) +{ + /* this will never get called */ +} + +static void +LinearRemoveCBWrapper(FBAreaPtr area) +{ + FBManagerPtr offman; + FBLinearLinkPtr pLink, pLinkPrev = NULL; + ScreenPtr pScreen = area->pScreen; + + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + pLink = offman->LinearAreas; + if(!pLink) return; + + while(pLink->area != area) { + pLinkPrev = pLink; + pLink = pLink->next; + if(!pLink) return; + } + + /* give the user the callback it is expecting */ + (*pLink->linear.RemoveLinearCallback)(&(pLink->linear)); + + if(pLinkPrev) + pLinkPrev->next = pLink->next; + else offman->LinearAreas = pLink->next; + + free(pLink); +} + +static void +DumpDebug(FBLinearLinkPtr pLink) +{ +#ifdef DEBUG + if (!pLink) ErrorF("MMmm, PLINK IS NULL!\n"); + + while (pLink) { + ErrorF(" Offset:%08x, Size:%08x, %s,%s\n", + pLink->linear.offset, + pLink->linear.size, + pLink->free ? "Free" : "Used", + pLink->area ? "Area" : "Linear"); + + pLink = pLink->next; + } +#endif +} + +static FBLinearPtr +AllocateLinear( + FBManagerPtr offman, + int size, + int granularity, + pointer privData +){ + ScreenPtr pScreen = offman->pScreen; + FBLinearLinkPtr linear = NULL; + FBLinearLinkPtr newlink = NULL; + int offset, end; + + if(size <= 0) return NULL; + + if (!offman->LinearAreas) return NULL; + + linear = offman->LinearAreas; + while (linear) { + /* Make sure we get a free area that's not an XY fallback case */ + if (!linear->area && linear->free) { + offset = linear->linear.offset; + if (granularity > 1) + offset = ((offset + granularity - 1) / granularity) * granularity; + end = offset+size; + if (end <= (linear->linear.offset + linear->linear.size)) + break; + } + linear = linear->next; + } + if (!linear) + return NULL; + + /* break left */ + if (offset > linear->linear.offset) { + newlink = malloc(sizeof(FBLinearLink)); + if (!newlink) + return NULL; + newlink->area = NULL; + newlink->linear.offset = offset; + newlink->linear.size = linear->linear.size - (offset - linear->linear.offset); + newlink->free = 1; + newlink->next = linear->next; + linear->linear.size -= newlink->linear.size; + linear->next = newlink; + linear = newlink; + } + + /* break right */ + if (size < linear->linear.size) { + newlink = malloc(sizeof(FBLinearLink)); + if (!newlink) + return NULL; + newlink->area = NULL; + newlink->linear.offset = offset + size; + newlink->linear.size = linear->linear.size - size; + newlink->free = 1; + newlink->next = linear->next; + linear->linear.size = size; + linear->next = newlink; + } + + /* p = middle block */ + linear->linear.granularity = granularity; + linear->free = 0; + linear->linear.pScreen = pScreen; + linear->linear.MoveLinearCallback = NULL; + linear->linear.RemoveLinearCallback = NULL; + linear->linear.devPrivate.ptr = NULL; + + DumpDebug(offman->LinearAreas); + + return &(linear->linear); +} + +static FBLinearPtr +localAllocateOffscreenLinear( + ScreenPtr pScreen, + int length, + int gran, + MoveLinearCallbackProcPtr moveCB, + RemoveLinearCallbackProcPtr removeCB, + pointer privData +){ + FBManagerPtr offman; + FBLinearLinkPtr link; + FBAreaPtr area; + FBLinearPtr linear = NULL; + BoxPtr extents; + int w, h, pitch; + + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + + /* Try to allocate from linear memory first...... */ + DebugF("ALLOCATING LINEAR\n"); + if ((linear = AllocateLinear(offman, length, gran, privData))) + return linear; + + DebugF("NOPE, ALLOCATING AREA\n"); + + if(!(link = malloc(sizeof(FBLinearLink)))) + return NULL; + + /* No linear available, so try and pinch some from the XY areas */ + extents = RegionExtents(offman->InitialBoxes); + pitch = extents->x2 - extents->x1; + + if (gran > 1) { + if (gran > pitch) { + /* we can't match the specified alignment with XY allocations */ + free(link); + return NULL; + } + + if (pitch % gran) { + /* pitch and granularity aren't a perfect match, let's allocate + * a bit more so we can align later on + */ + length += gran - 1; + } + } + + if(length < pitch) { /* special case */ + w = length; + h = 1; + } else { + w = pitch; + h = (length + pitch - 1) / pitch; + } + + if((area = localAllocateOffscreenArea(pScreen, w, h, gran, + moveCB ? LinearMoveCBWrapper : NULL, + removeCB ? LinearRemoveCBWrapper : NULL, + privData))) + { + link->area = area; + link->free = 0; + link->next = offman->LinearAreas; + offman->LinearAreas = link; + linear = &(link->linear); + linear->pScreen = pScreen; + linear->size = h * w; + linear->offset = (pitch * area->box.y1) + area->box.x1; + if (gran > 1) + linear->offset = ((linear->offset + gran - 1) / gran) * gran; + linear->granularity = gran; + linear->MoveLinearCallback = moveCB; + linear->RemoveLinearCallback = removeCB; + linear->devPrivate.ptr = privData; + } else + free(link); + + DumpDebug(offman->LinearAreas); + + return linear; +} + + +static void +localFreeOffscreenLinear(FBLinearPtr linear) +{ + FBManagerPtr offman; + FBLinearLinkPtr pLink, pLinkPrev = NULL; + ScreenPtr pScreen = linear->pScreen; + + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + pLink = offman->LinearAreas; + if(!pLink) return; + + while(&(pLink->linear) != linear) { + pLinkPrev = pLink; + pLink = pLink->next; + if(!pLink) return; + } + + if(pLink->area) { /* really an XY area */ + DebugF("FREEING AREA\n"); + localFreeOffscreenArea(pLink->area); + if(pLinkPrev) + pLinkPrev->next = pLink->next; + else offman->LinearAreas = pLink->next; + free(pLink); + DumpDebug(offman->LinearAreas); + return; + } + + pLink->free = 1; + + if (pLink->next && pLink->next->free) { + FBLinearLinkPtr p = pLink->next; + pLink->linear.size += p->linear.size; + pLink->next = p->next; + free(p); + } + + if(pLinkPrev) { + if (pLinkPrev->next && pLinkPrev->next->free && !pLinkPrev->area) { + FBLinearLinkPtr p = pLinkPrev->next; + pLinkPrev->linear.size += p->linear.size; + pLinkPrev->next = p->next; + free(p); + } + } + + DebugF("FREEING LINEAR\n"); + DumpDebug(offman->LinearAreas); +} + + +static Bool +localResizeOffscreenLinear(FBLinearPtr resize, int length) +{ + FBManagerPtr offman; + FBLinearLinkPtr pLink; + ScreenPtr pScreen = resize->pScreen; + + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + pLink = offman->LinearAreas; + if(!pLink) return FALSE; + + while(&(pLink->linear) != resize) { + pLink = pLink->next; + if(!pLink) return FALSE; + } + + /* This could actually be alot smarter and try to move allocations + from XY to linear when available. For now if it was XY, we keep + it XY */ + + if(pLink->area) { /* really an XY area */ + BoxPtr extents; + int pitch, w, h; + + extents = RegionExtents(offman->InitialBoxes); + pitch = extents->x2 - extents->x1; + + if(length < pitch) { /* special case */ + w = length; + h = 1; + } else { + w = pitch; + h = (length + pitch - 1) / pitch; + } + + if(localResizeOffscreenArea(pLink->area, w, h)) { + resize->size = h * w; + resize->offset = (pitch * pLink->area->box.y1) + pLink->area->box.x1; + return TRUE; + } + } else { + /* TODO!!!! resize the linear area */ + } + + return FALSE; +} + + +static Bool +localQueryLargestOffscreenLinear( + ScreenPtr pScreen, + int *size, + int gran, + int priority +) +{ + FBManagerPtr offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + FBLinearLinkPtr pLink; + FBLinearLinkPtr pLinkRet; + + *size = 0; + + pLink = offman->LinearAreas; + + if (pLink && !pLink->area) { + pLinkRet = pLink; + while (pLink) { + if (pLink->free) { + if (pLink->linear.size > pLinkRet->linear.size) + pLinkRet = pLink; + } + pLink = pLink->next; + } + + if (pLinkRet->free) { + *size = pLinkRet->linear.size; + return TRUE; + } + } else { + int w, h; + + if(localQueryLargestOffscreenArea(pScreen, &w, &h, gran, + FAVOR_WIDTH_THEN_AREA, priority)) + { + FBManagerPtr offman; + BoxPtr extents; + + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + extents = RegionExtents(offman->InitialBoxes); + if((extents->x2 - extents->x1) == w) + *size = w * h; + return TRUE; + } + } + + return FALSE; +} + + + +static FBManagerFuncs xf86FBManFuncs = { + localAllocateOffscreenArea, + localFreeOffscreenArea, + localResizeOffscreenArea, + localQueryLargestOffscreenArea, + localRegisterFreeBoxCallback, + localAllocateOffscreenLinear, + localFreeOffscreenLinear, + localResizeOffscreenLinear, + localQueryLargestOffscreenLinear, + localPurgeUnlockedOffscreenAreas + }; + + +static Bool +xf86FBCloseScreen (int i, ScreenPtr pScreen) +{ + FBLinkPtr pLink, tmp; + FBLinearLinkPtr pLinearLink, tmp2; + FBManagerPtr offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + + pScreen->CloseScreen = offman->CloseScreen; + + pLink = offman->UsedAreas; + while(pLink) { + tmp = pLink; + pLink = pLink->next; + free(tmp); + } + + pLinearLink = offman->LinearAreas; + while(pLinearLink) { + tmp2 = pLinearLink; + pLinearLink = pLinearLink->next; + free(tmp2); + } + + RegionDestroy(offman->InitialBoxes); + RegionDestroy(offman->FreeBoxes); + + free(offman->FreeBoxesUpdateCallback); + free(offman->devPrivates); + free(offman); + dixSetPrivate(&pScreen->devPrivates, xf86FBScreenKey, NULL); + + return (*pScreen->CloseScreen) (i, pScreen); +} + +Bool +xf86InitFBManager( + ScreenPtr pScreen, + BoxPtr FullBox +){ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RegionRec ScreenRegion; + RegionRec FullRegion; + BoxRec ScreenBox; + Bool ret; + + ScreenBox.x1 = 0; + ScreenBox.y1 = 0; + ScreenBox.x2 = pScrn->virtualX; + ScreenBox.y2 = pScrn->virtualY; + + if((FullBox->x1 > ScreenBox.x1) || (FullBox->y1 > ScreenBox.y1) || + (FullBox->x2 < ScreenBox.x2) || (FullBox->y2 < ScreenBox.y2)) { + return FALSE; + } + + if (FullBox->y2 < FullBox->y1) return FALSE; + if (FullBox->x2 < FullBox->x1) return FALSE; + + RegionInit(&ScreenRegion, &ScreenBox, 1); + RegionInit(&FullRegion, FullBox, 1); + + RegionSubtract(&FullRegion, &FullRegion, &ScreenRegion); + + ret = xf86InitFBManagerRegion(pScreen, &FullRegion); + + RegionUninit(&ScreenRegion); + RegionUninit(&FullRegion); + + return ret; +} + +Bool +xf86InitFBManagerArea( + ScreenPtr pScreen, + int PixelArea, + int Verbosity +) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xRectangle Rect[3]; + RegionPtr pRegion, pScreenRegion; + int nRect; + Bool ret = FALSE; + + if (PixelArea < (pScrn->displayWidth * pScrn->virtualY)) + return FALSE; + + Rect[0].x = Rect[0].y = 0; + Rect[0].width = pScrn->displayWidth; + Rect[0].height = PixelArea / pScrn->displayWidth; + nRect = 1; + + /* Add a possible partial scanline */ + if ((Rect[1].height = Rect[1].width = PixelArea % pScrn->displayWidth)) { + Rect[1].x = 0; + Rect[1].y = Rect[0].height; + Rect[1].height = 1; + nRect++; + } + + /* Factor out virtual resolution */ + pRegion = RegionFromRects(nRect, Rect, 0); + if (pRegion) { + if (!RegionNar(pRegion)) { + Rect[2].x = Rect[2].y = 0; + Rect[2].width = pScrn->virtualX; + Rect[2].height = pScrn->virtualY; + + pScreenRegion = RegionFromRects(1, &Rect[2], 0); + if (pScreenRegion) { + if (!RegionNar(pScreenRegion)) { + RegionSubtract(pRegion, pRegion, pScreenRegion); + + ret = xf86InitFBManagerRegion(pScreen, pRegion); + + if (ret && xf86GetVerbosity() >= Verbosity) { + int scrnIndex = pScrn->scrnIndex; + + xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, + "Largest offscreen areas (with overlaps):\n"); + + if (Rect[2].width < Rect[0].width) { + xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, + "\t%d x %d rectangle at %d,0\n", + Rect[0].width - Rect[2].width, + Rect[0].height, + Rect[2].width); + } + if (Rect[2].width < Rect[1].width) { + xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, + "\t%d x %d rectangle at %d,0\n", + Rect[1].width - Rect[2].width, + Rect[0].height + Rect[1].height, + Rect[2].width); + } + if (Rect[2].height < Rect[0].height) { + xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, + "\t%d x %d rectangle at 0,%d\n", + Rect[0].width, + Rect[0].height - Rect[2].height, + Rect[2].height); + } + if (Rect[1].height) { + xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, + "\t%d x %d rectangle at 0,%d\n", + Rect[1].width, + Rect[0].height - Rect[2].height + + Rect[1].height, + Rect[2].height); + } + } + } + + RegionDestroy(pScreenRegion); + } + } + + RegionDestroy(pRegion); + } + + return ret; +} + +Bool +xf86InitFBManagerRegion( + ScreenPtr pScreen, + RegionPtr FullRegion +){ + FBManagerPtr offman; + + if(RegionNil(FullRegion)) + return FALSE; + + if (!dixRegisterPrivateKey(&xf86FBScreenKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + if(!xf86RegisterOffscreenManager(pScreen, &xf86FBManFuncs)) + return FALSE; + + offman = malloc(sizeof(FBManager)); + if(!offman) return FALSE; + + dixSetPrivate(&pScreen->devPrivates, xf86FBScreenKey, offman); + + offman->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = xf86FBCloseScreen; + + offman->InitialBoxes = RegionCreate(NULL, 1); + offman->FreeBoxes = RegionCreate(NULL, 1); + + RegionCopy(offman->InitialBoxes, FullRegion); + RegionCopy(offman->FreeBoxes, FullRegion); + + offman->pScreen = pScreen; + offman->UsedAreas = NULL; + offman->LinearAreas = NULL; + offman->NumUsedAreas = 0; + offman->NumCallbacks = 0; + offman->FreeBoxesUpdateCallback = NULL; + offman->devPrivates = NULL; + + return TRUE; +} + +Bool +xf86InitFBManagerLinear( + ScreenPtr pScreen, + int offset, + int size +){ + FBManagerPtr offman; + FBLinearLinkPtr link; + FBLinearPtr linear; + + if (size <= 0) + return FALSE; + + /* we expect people to have called the Area setup first for pixmap cache */ + if (!dixLookupPrivate(&pScreen->devPrivates, xf86FBScreenKey)) + return FALSE; + + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + offman->LinearAreas = malloc(sizeof(FBLinearLink)); + if (!offman->LinearAreas) + return FALSE; + + link = offman->LinearAreas; + link->area = NULL; + link->next = NULL; + link->free = 1; + linear = &(link->linear); + linear->pScreen = pScreen; + linear->size = size; + linear->offset = offset; + linear->granularity = 0; + linear->MoveLinearCallback = NULL; + linear->RemoveLinearCallback = NULL; + linear->devPrivate.ptr = NULL; + + return TRUE; +} + + +/* This is an implementation specific function and should + disappear after the next release. People should use the + real linear functions instead */ + +FBAreaPtr +xf86AllocateLinearOffscreenArea ( + ScreenPtr pScreen, + int length, + int gran, + MoveAreaCallbackProcPtr moveCB, + RemoveAreaCallbackProcPtr removeCB, + pointer privData +){ + FBManagerFuncsPtr funcs; + FBManagerPtr offman; + BoxPtr extents; + int w, h; + + if(xf86FBManagerKey == NULL) + return NULL; + if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBManagerKey))) + return NULL; + + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + extents = RegionExtents(offman->InitialBoxes); + w = extents->x2 - extents->x1; + + if (gran > 1) { + if (gran > w) + return NULL; + + if (w % gran) + length += gran - 1; + } + + if(length <= w) { /* special case */ + h = 1; + w = length; + } else { + h = (length + w - 1) / w; + } + + return (*funcs->AllocateOffscreenArea)( + pScreen, w, h, gran, moveCB, removeCB, privData); +} diff --git a/hw/xfree86/common/xf86fbman.h b/hw/xfree86/common/xf86fbman.h new file mode 100644 index 0000000..1b3c316 --- /dev/null +++ b/hw/xfree86/common/xf86fbman.h @@ -0,0 +1,226 @@ + +/* + * Copyright (c) 1998-2001 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +#ifndef _XF86FBMAN_H +#define _XF86FBMAN_H + + +#include "scrnintstr.h" +#include "regionstr.h" + + +#define FAVOR_AREA_THEN_WIDTH 0 +#define FAVOR_AREA_THEN_HEIGHT 1 +#define FAVOR_WIDTH_THEN_AREA 2 +#define FAVOR_HEIGHT_THEN_AREA 3 + +#define PRIORITY_LOW 0 +#define PRIORITY_NORMAL 1 +#define PRIORITY_EXTREME 2 + + +typedef struct _FBArea { + ScreenPtr pScreen; + BoxRec box; + int granularity; + void (*MoveAreaCallback)(struct _FBArea*, struct _FBArea*); + void (*RemoveAreaCallback)(struct _FBArea*); + DevUnion devPrivate; +} FBArea, *FBAreaPtr; + +typedef struct _FBLinear { + ScreenPtr pScreen; + int size; + int offset; + int granularity; + void (*MoveLinearCallback)(struct _FBLinear*, struct _FBLinear*); + void (*RemoveLinearCallback)(struct _FBLinear*); + DevUnion devPrivate; +} FBLinear, *FBLinearPtr; + +typedef void (*FreeBoxCallbackProcPtr)(ScreenPtr, RegionPtr, pointer); +typedef void (*MoveAreaCallbackProcPtr)(FBAreaPtr, FBAreaPtr); +typedef void (*RemoveAreaCallbackProcPtr)(FBAreaPtr); + +typedef void (*MoveLinearCallbackProcPtr)(FBLinearPtr, FBLinearPtr); +typedef void (*RemoveLinearCallbackProcPtr)(FBLinearPtr); + + +typedef struct { + FBAreaPtr (*AllocateOffscreenArea)( + ScreenPtr pScreen, + int w, int h, + int granularity, + MoveAreaCallbackProcPtr moveCB, + RemoveAreaCallbackProcPtr removeCB, + pointer privData); + void (*FreeOffscreenArea)(FBAreaPtr area); + Bool (*ResizeOffscreenArea)(FBAreaPtr area, int w, int h); + Bool (*QueryLargestOffscreenArea)( + ScreenPtr pScreen, + int *width, int *height, + int granularity, + int preferences, + int priority); + Bool (*RegisterFreeBoxCallback)( + ScreenPtr pScreen, + FreeBoxCallbackProcPtr FreeBoxCallback, + pointer devPriv); +/* linear functions */ + FBLinearPtr (*AllocateOffscreenLinear)( + ScreenPtr pScreen, + int size, + int granularity, + MoveLinearCallbackProcPtr moveCB, + RemoveLinearCallbackProcPtr removeCB, + pointer privData); + void (*FreeOffscreenLinear)(FBLinearPtr area); + Bool (*ResizeOffscreenLinear)(FBLinearPtr area, int size); + Bool (*QueryLargestOffscreenLinear)( + ScreenPtr pScreen, + int *size, + int granularity, + int priority); + Bool (*PurgeOffscreenAreas) (ScreenPtr); +} FBManagerFuncs, *FBManagerFuncsPtr; + + +extern _X_EXPORT Bool xf86RegisterOffscreenManager( + ScreenPtr pScreen, + FBManagerFuncsPtr funcs +); + +extern _X_EXPORT Bool +xf86InitFBManagerRegion( + ScreenPtr pScreen, + RegionPtr ScreenRegion +); + +extern _X_EXPORT Bool +xf86InitFBManagerArea( + ScreenPtr pScreen, + int PixalArea, + int Verbosity +); + +extern _X_EXPORT Bool +xf86InitFBManager( + ScreenPtr pScreen, + BoxPtr FullBox +); + +extern _X_EXPORT Bool +xf86InitFBManagerLinear( + ScreenPtr pScreen, + int offset, + int size +); + +extern _X_EXPORT Bool +xf86FBManagerRunning( + ScreenPtr pScreen +); + +extern _X_EXPORT FBAreaPtr +xf86AllocateOffscreenArea ( + ScreenPtr pScreen, + int w, int h, + int granularity, + MoveAreaCallbackProcPtr moveCB, + RemoveAreaCallbackProcPtr removeCB, + pointer privData +); + +extern _X_EXPORT FBAreaPtr +xf86AllocateLinearOffscreenArea ( + ScreenPtr pScreen, + int length, + int granularity, + MoveAreaCallbackProcPtr moveCB, + RemoveAreaCallbackProcPtr removeCB, + pointer privData +); + +extern _X_EXPORT FBLinearPtr +xf86AllocateOffscreenLinear ( + ScreenPtr pScreen, + int length, + int granularity, + MoveLinearCallbackProcPtr moveCB, + RemoveLinearCallbackProcPtr removeCB, + pointer privData +); + +extern _X_EXPORT void xf86FreeOffscreenArea(FBAreaPtr area); +extern _X_EXPORT void xf86FreeOffscreenLinear(FBLinearPtr area); + +extern _X_EXPORT Bool +xf86ResizeOffscreenArea( + FBAreaPtr resize, + int w, int h +); + +extern _X_EXPORT Bool +xf86ResizeOffscreenLinear( + FBLinearPtr resize, + int size +); + + +extern _X_EXPORT Bool +xf86RegisterFreeBoxCallback( + ScreenPtr pScreen, + FreeBoxCallbackProcPtr FreeBoxCallback, + pointer devPriv +); + +extern _X_EXPORT Bool +xf86PurgeUnlockedOffscreenAreas( + ScreenPtr pScreen +); + + +extern _X_EXPORT Bool +xf86QueryLargestOffscreenArea( + ScreenPtr pScreen, + int *width, int *height, + int granularity, + int preferences, + int priority +); + +extern _X_EXPORT Bool +xf86QueryLargestOffscreenLinear( + ScreenPtr pScreen, + int *size, + int granularity, + int priority +); + + +#endif /* _XF86FBMAN_H */ diff --git a/hw/xfree86/common/xf86noBus.c b/hw/xfree86/common/xf86noBus.c new file mode 100644 index 0000000..0b96349 --- /dev/null +++ b/hw/xfree86/common/xf86noBus.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2000-2002 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * This file contains the interfaces to the bus-specific code + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <ctype.h> +#include <stdlib.h> +#include <unistd.h> +#include <X11/X.h> +#include "os.h" +#include "xf86.h" +#include "xf86Priv.h" + +#include "xf86Bus.h" + +#define XF86_OS_PRIVS +#include "xf86_OSproc.h" + +int +xf86ClaimNoSlot(DriverPtr drvp, int chipset, GDevPtr dev, Bool active) +{ + EntityPtr p; + int num; + + num = xf86AllocateEntity(); + p = xf86Entities[num]; + p->driver = drvp; + p->chipset = 0; + p->bus.type = BUS_NONE; + p->active = active; + p->inUse = FALSE; + xf86AddDevToEntity(num, dev); + + return num; +} diff --git a/hw/xfree86/common/xf86pciBus.c b/hw/xfree86/common/xf86pciBus.c new file mode 100644 index 0000000..447b192 --- /dev/null +++ b/hw/xfree86/common/xf86pciBus.c @@ -0,0 +1,1359 @@ +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * This file contains the interfaces to the bus-specific code + */ +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <ctype.h> +#include <stdlib.h> +#include <unistd.h> +#include <X11/X.h> +#include <pciaccess.h> +#include "os.h" +#include "Pci.h" +#include "xf86.h" +#include "xf86Priv.h" +#include "dirent.h" /* DIR, FILE type definitions */ + +/* Bus-specific headers */ +#include "xf86Bus.h" + +#define XF86_OS_PRIVS +#include "xf86_OSproc.h" + + +/* Bus-specific globals */ +Bool pciSlotClaimed = FALSE; + +#define PCIINFOCLASSES(c) \ + ( (((c) & 0x00ff0000) == (PCI_CLASS_PREHISTORIC << 16)) \ + || (((c) & 0x00ff0000) == (PCI_CLASS_DISPLAY << 16)) \ + || ((((c) & 0x00ffff00) \ + == ((PCI_CLASS_MULTIMEDIA << 16) | (PCI_SUBCLASS_MULTIMEDIA_VIDEO << 8)))) \ + || ((((c) & 0x00ffff00) \ + == ((PCI_CLASS_PROCESSOR << 16) | (PCI_SUBCLASS_PROCESSOR_COPROC << 8)))) ) + +/* + * PCI classes that have messages printed always. The others are only + * have a message printed when the vendor/dev IDs are recognised. + */ +#define PCIALWAYSPRINTCLASSES(c) \ + ( (((c) & 0x00ffff00) \ + == ((PCI_CLASS_PREHISTORIC << 16) | (PCI_SUBCLASS_PREHISTORIC_VGA << 8))) \ + || (((c) & 0x00ff0000) == (PCI_CLASS_DISPLAY << 16)) \ + || ((((c) & 0x00ffff00) \ + == ((PCI_CLASS_MULTIMEDIA << 16) | (PCI_SUBCLASS_MULTIMEDIA_VIDEO << 8)))) ) + +#define IS_VGA(c) \ + (((c) & 0x00ffff00) \ + == ((PCI_CLASS_DISPLAY << 16) | (PCI_SUBCLASS_DISPLAY_VGA << 8))) + + +static struct pci_slot_match xf86IsolateDevice = { + PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0 +}; + +void +xf86FormatPciBusNumber(int busnum, char *buffer) +{ + /* 'buffer' should be at least 8 characters long */ + if (busnum < 256) + sprintf(buffer, "%d", busnum); + else + sprintf(buffer, "%d@%d", busnum & 0x00ff, busnum >> 8); +} + +/* + * xf86Bus.c interface + */ + +void +xf86PciProbe(void) +{ + int i = 0, k; + int num = 0; + struct pci_device *info; + struct pci_device_iterator *iter; + struct pci_device ** xf86PciVideoInfo = NULL; + + + if (!xf86scanpci()) { + xf86PciVideoInfo = NULL; + return; + } + + iter = pci_slot_match_iterator_create(& xf86IsolateDevice); + while ((info = pci_device_next(iter)) != NULL) { + if (PCIINFOCLASSES(info->device_class)) { + num++; + xf86PciVideoInfo = xnfrealloc(xf86PciVideoInfo, + (sizeof(struct pci_device *) + * (num + 1))); + xf86PciVideoInfo[num] = NULL; + xf86PciVideoInfo[num - 1] = info; + + pci_device_probe(info); +#ifdef HAVE_PCI_DEVICE_IS_BOOT_VGA + if (pci_device_is_boot_vga(info)) { + primaryBus.type = BUS_PCI; + primaryBus.id.pci = info; + } +#endif + info->user_data = 0; + } + } + free(iter); + + /* If we haven't found a primary device try a different heuristic */ + if (primaryBus.type == BUS_NONE && num) { + for (i = 0; i < num; i++) { + uint16_t command; + + info = xf86PciVideoInfo[i]; + pci_device_cfg_read_u16(info, & command, 4); + + if ((command & PCI_CMD_MEM_ENABLE) + && ((num == 1) || IS_VGA(info->device_class))) { + if (primaryBus.type == BUS_NONE) { + primaryBus.type = BUS_PCI; + primaryBus.id.pci = info; + } else { + xf86Msg(X_NOTICE, + "More than one possible primary device found\n"); + primaryBus.type ^= (BusType)(-1); + } + } + } + } + + /* Print a summary of the video devices found */ + for (k = 0; k < num; k++) { + const char *prim = " "; + Bool memdone = FALSE, iodone = FALSE; + + + info = xf86PciVideoInfo[k]; + + if (!PCIALWAYSPRINTCLASSES(info->device_class)) + continue; + + if (xf86IsPrimaryPci(info)) + prim = "*"; + + xf86Msg(X_PROBED, "PCI:%s(%u:%u:%u:%u) %04x:%04x:%04x:%04x ", prim, + info->domain, info->bus, info->dev, info->func, + info->vendor_id, info->device_id, + info->subvendor_id, info->subdevice_id); + + xf86ErrorF("rev %d", info->revision); + + for (i = 0; i < 6; i++) { + struct pci_mem_region * r = & info->regions[i]; + + if ( r->size && ! r->is_IO ) { + if (!memdone) { + xf86ErrorF(", Mem @ "); + memdone = TRUE; + } else + xf86ErrorF(", "); + xf86ErrorF("0x%08lx/%ld", (long)r->base_addr, (long)r->size); + } + } + + for (i = 0; i < 6; i++) { + struct pci_mem_region * r = & info->regions[i]; + + if ( r->size && r->is_IO ) { + if (!iodone) { + xf86ErrorF(", I/O @ "); + iodone = TRUE; + } else + xf86ErrorF(", "); + xf86ErrorF("0x%08lx/%ld", (long)r->base_addr, (long)r->size); + } + } + + if ( info->rom_size ) { + xf86ErrorF(", BIOS @ 0x\?\?\?\?\?\?\?\?/%ld", (long)info->rom_size); + } + + xf86ErrorF("\n"); + } + free(xf86PciVideoInfo); +} + +/* + * If the slot requested is already in use, return -1. + * Otherwise, claim the slot for the screen requesting it. + */ + +int +xf86ClaimPciSlot(struct pci_device * d, DriverPtr drvp, + int chipset, GDevPtr dev, Bool active) +{ + EntityPtr p = NULL; + int num; + + if (xf86CheckPciSlot(d)) { + num = xf86AllocateEntity(); + p = xf86Entities[num]; + p->driver = drvp; + p->chipset = chipset; + p->bus.type = BUS_PCI; + p->bus.id.pci = d; + p->active = active; + p->inUse = FALSE; + if (dev) + xf86AddDevToEntity(num, dev); + pciSlotClaimed = TRUE; + + if (active) { + /* Map in this domain's I/O space */ + p->domainIO = xf86MapLegacyIO(d); + } + + return num; + } else + return -1; +} + +/* + * Unclaim PCI slot, e.g. if probing failed, so that a different driver can claim. + */ +void +xf86UnclaimPciSlot(struct pci_device *d) +{ + int i; + + for (i = 0; i < xf86NumEntities; i++) { + const EntityPtr p = xf86Entities[i]; + + if ((p->bus.type == BUS_PCI) && (p->bus.id.pci == d)) { + /* Probably the slot should be deallocated? */ + p->bus.type = BUS_NONE; + return; + } + } +} + +/* + * Parse a BUS ID string, and return the PCI bus parameters if it was + * in the correct format for a PCI bus id. + */ + +Bool +xf86ParsePciBusString(const char *busID, int *bus, int *device, int *func) +{ + /* + * The format is assumed to be "bus[@domain]:device[:func]", where domain, + * bus, device and func are decimal integers. domain and func may be + * omitted and assumed to be zero, although doing this isn't encouraged. + */ + + char *p, *s, *d; + const char *id; + int i; + + if (StringToBusType(busID, &id) != BUS_PCI) + return FALSE; + + s = xstrdup(id); + p = strtok(s, ":"); + if (p == NULL || *p == 0) { + free(s); + return FALSE; + } + d = strpbrk(p, "@"); + if (d != NULL) { + *(d++) = 0; + for (i = 0; d[i] != 0; i++) { + if (!isdigit(d[i])) { + free(s); + return FALSE; + } + } + } + for (i = 0; p[i] != 0; i++) { + if (!isdigit(p[i])) { + free(s); + return FALSE; + } + } + *bus = atoi(p); + if (d != NULL && *d != 0) + *bus += atoi(d) << 8; + p = strtok(NULL, ":"); + if (p == NULL || *p == 0) { + free(s); + return FALSE; + } + for (i = 0; p[i] != 0; i++) { + if (!isdigit(p[i])) { + free(s); + return FALSE; + } + } + *device = atoi(p); + *func = 0; + p = strtok(NULL, ":"); + if (p == NULL || *p == 0) { + free(s); + return TRUE; + } + for (i = 0; p[i] != 0; i++) { + if (!isdigit(p[i])) { + free(s); + return FALSE; + } + } + *func = atoi(p); + free(s); + return TRUE; +} + +/* + * Compare a BUS ID string with a PCI bus id. Return TRUE if they match. + */ + +Bool +xf86ComparePciBusString(const char *busID, int bus, int device, int func) +{ + int ibus, idevice, ifunc; + + if (xf86ParsePciBusString(busID, &ibus, &idevice, &ifunc)) { + return bus == ibus && device == idevice && func == ifunc; + } else { + return FALSE; + } +} + +/* + * xf86IsPrimaryPci() -- return TRUE if primary device + * is PCI and bus, dev and func numbers match. + */ + +Bool +xf86IsPrimaryPci(struct pci_device *pPci) +{ + return ((primaryBus.type == BUS_PCI) && (pPci == primaryBus.id.pci)); +} + +/* + * xf86GetPciInfoForEntity() -- Get the pciVideoRec of entity. + */ +struct pci_device * +xf86GetPciInfoForEntity(int entityIndex) +{ + EntityPtr p; + + if (entityIndex >= xf86NumEntities) + return NULL; + + p = xf86Entities[entityIndex]; + return (p->bus.type == BUS_PCI) ? p->bus.id.pci : NULL; +} + +/* + * xf86CheckPciMemBase() checks that the memory base value matches one of the + * PCI base address register values for the given PCI device. + */ +Bool +xf86CheckPciMemBase( struct pci_device * pPci, memType base ) +{ + int i; + + for (i = 0; i < 6; i++) + if (base == pPci->regions[i].base_addr) + return TRUE; + return FALSE; +} + +/* + * Check if the slot requested is free. If it is already in use, return FALSE. + */ + +Bool +xf86CheckPciSlot(const struct pci_device *d) +{ + int i; + + for (i = 0; i < xf86NumEntities; i++) { + const EntityPtr p = xf86Entities[i]; + + if ((p->bus.type == BUS_PCI) && (p->bus.id.pci == d)) { + return FALSE; + } + } + return TRUE; +} + +#define END_OF_MATCHES(m) \ + (((m).vendor_id == 0) && ((m).device_id == 0) && ((m).subvendor_id == 0)) + +Bool +xf86PciAddMatchingDev(DriverPtr drvp) +{ + const struct pci_id_match * const devices = drvp->supported_devices; + int j; + struct pci_device *pPci; + struct pci_device_iterator *iter; + int numFound = 0; + + + iter = pci_id_match_iterator_create(NULL); + while ((pPci = pci_device_next(iter)) != NULL) { + /* Determine if this device is supported by the driver. If it is, + * add it to the list of devices to configure. + */ + for (j = 0 ; ! END_OF_MATCHES(devices[j]) ; j++) { + if ( PCI_ID_COMPARE( devices[j].vendor_id, pPci->vendor_id ) + && PCI_ID_COMPARE( devices[j].device_id, pPci->device_id ) + && ((devices[j].device_class_mask & pPci->device_class) + == devices[j].device_class) ) { + if (xf86CheckPciSlot(pPci)) { + GDevPtr pGDev = xf86AddBusDeviceToConfigure( + drvp->driverName, BUS_PCI, pPci, -1); + if (pGDev != NULL) { + /* After configure pass 1, chipID and chipRev are + * treated as over-rides, so clobber them here. + */ + pGDev->chipID = -1; + pGDev->chipRev = -1; + } + + numFound++; + } + + break; + } + } + } + + pci_iterator_destroy(iter); + + return numFound != 0; +} + +Bool +xf86PciProbeDev(DriverPtr drvp) +{ + int i, j; + struct pci_device * pPci; + Bool foundScreen = FALSE; + const struct pci_id_match * const devices = drvp->supported_devices; + GDevPtr *devList; + const unsigned numDevs = xf86MatchDevice(drvp->driverName, & devList); + + for ( i = 0 ; i < numDevs ; i++ ) { + struct pci_device_iterator *iter; + unsigned device_id; + + + /* Find the pciVideoRec associated with this device section. + */ + iter = pci_id_match_iterator_create(NULL); + while ((pPci = pci_device_next(iter)) != NULL) { + if (devList[i]->busID && *devList[i]->busID) { + if (xf86ComparePciBusString(devList[i]->busID, + ((pPci->domain << 8) + | pPci->bus), + pPci->dev, + pPci->func)) { + break; + } + } + else if (xf86IsPrimaryPci(pPci)) { + break; + } + } + + pci_iterator_destroy(iter); + + if (pPci == NULL) { + continue; + } + device_id = (devList[i]->chipID > 0) + ? devList[i]->chipID : pPci->device_id; + + + /* Once the pciVideoRec is found, determine if the device is supported + * by the driver. If it is, probe it! + */ + for ( j = 0 ; ! END_OF_MATCHES( devices[j] ) ; j++ ) { + if ( PCI_ID_COMPARE( devices[j].vendor_id, pPci->vendor_id ) + && PCI_ID_COMPARE( devices[j].device_id, device_id ) + && ((devices[j].device_class_mask & pPci->device_class) + == devices[j].device_class) ) { + int entry; + + /* Allow the same entity to be used more than once for + * devices with multiple screens per entity. This assumes + * implicitly that there will be a screen == 0 instance. + * + * FIXME Need to make sure that two different drivers don't + * FIXME claim the same screen > 0 instance. + */ + if ((devList[i]->screen == 0) && !xf86CheckPciSlot(pPci)) + continue; + + DebugF("%s: card at %d:%d:%d is claimed by a Device section\n", + drvp->driverName, pPci->bus, pPci->dev, pPci->func); + + /* Allocate an entry in the lists to be returned */ + entry = xf86ClaimPciSlot(pPci, drvp, device_id, + devList[i], devList[i]->active); + + if ((entry == -1) && (devList[i]->screen > 0)) { + unsigned k; + + for (k = 0; k < xf86NumEntities; k++ ) { + EntityPtr pEnt = xf86Entities[k]; + if (pEnt->bus.type != BUS_PCI) + continue; + if (pEnt->bus.id.pci == pPci) { + entry = k; + xf86AddDevToEntity(k, devList[i]); + break; + } + } + } + + if (entry != -1) { + if ((*drvp->PciProbe)(drvp, entry, pPci, + devices[j].match_data)) { + foundScreen = TRUE; + } else + xf86UnclaimPciSlot(pPci); + } + + break; + } + } + } + free(devList); + + return foundScreen; +} + +void +xf86PciIsolateDevice(char *argument) +{ + int bus, device, func; + + if (sscanf(argument, "PCI:%d:%d:%d", &bus, &device, &func) == 3) { + xf86IsolateDevice.domain = PCI_DOM_FROM_BUS(bus); + xf86IsolateDevice.bus = PCI_BUS_NO_DOMAIN(bus); + xf86IsolateDevice.dev = device; + xf86IsolateDevice.func = func; + } else + FatalError("Invalid isolated device specification\n"); +} + +static Bool +pciDeviceHasBars(struct pci_device *pci) +{ + int i; + + for (i = 0; i < 6; i++) + if (pci->regions[i].size) + return TRUE; + + if (pci->rom_size) + return TRUE; + + return FALSE; +} + +struct Inst { + struct pci_device * pci; + GDevPtr dev; + Bool foundHW; /* PCIid in list of supported chipsets */ + Bool claimed; /* BusID matches with a device section */ + int chip; + int screen; +}; + + +/** + * Find set of unclaimed devices matching a given vendor ID. + * + * Used by drivers to find as yet unclaimed devices matching the specified + * vendor ID. + * + * \param driverName Name of the driver. This is used to find Device + * sections in the config file. + * \param vendorID PCI vendor ID of associated devices. If zero, then + * the true vendor ID must be encoded in the \c PCIid + * fields of the \c PCIchipsets entries. + * \param chipsets Symbol table used to associate chipset names with + * PCI IDs. + * \param devList List of Device sections parsed from the config file. + * \param numDevs Number of entries in \c devList. + * \param drvp Pointer the driver's control structure. + * \param foundEntities Returned list of entity indicies associated with the + * driver. + * + * \returns + * The number of elements in returned in \c foundEntities on success or zero + * on failure. + * + * \todo + * This function does a bit more than short description says. Fill in some + * more of the details of its operation. + * + * \todo + * The \c driverName parameter is redundant. It is the same as + * \c DriverRec::driverName. In a future version of this function, remove + * that parameter. + */ +int +xf86MatchPciInstances(const char *driverName, int vendorID, + SymTabPtr chipsets, PciChipsets *PCIchipsets, + GDevPtr *devList, int numDevs, DriverPtr drvp, + int **foundEntities) +{ + int i,j; + struct pci_device * pPci; + struct pci_device_iterator *iter; + struct Inst *instances = NULL; + int numClaimedInstances = 0; + int allocatedInstances = 0; + int numFound = 0; + SymTabRec *c; + PciChipsets *id; + int *retEntities = NULL; + + *foundEntities = NULL; + + + /* Each PCI device will contribute at least one entry. Each device + * section can contribute at most one entry. The sum of the two is + * guaranteed to be larger than the maximum possible number of entries. + * Do this calculation and memory allocation once now to eliminate the + * need for realloc calls inside the loop. + */ + if (!(xf86DoConfigure && xf86DoConfigurePass1)) { + unsigned max_entries = numDevs; + + iter = pci_slot_match_iterator_create(NULL); + while ((pPci = pci_device_next(iter)) != NULL) { + max_entries++; + } + + pci_iterator_destroy(iter); + instances = xnfalloc(max_entries * sizeof(struct Inst)); + } + + iter = pci_slot_match_iterator_create(NULL); + while ((pPci = pci_device_next(iter)) != NULL) { + unsigned device_class = pPci->device_class; + Bool foundVendor = FALSE; + + + /* Convert the pre-PCI 2.0 device class for a VGA adapter to the + * 2.0 version of the same class. + */ + if ( device_class == 0x00000101 ) { + device_class = 0x00030000; + } + + + /* Find PCI devices that match the given vendor ID. The vendor ID is + * either specified explicitly as a parameter to the function or + * implicitly encoded in the high bits of id->PCIid. + * + * The first device with a matching vendor is recorded, even if the + * device ID doesn't match. This is done because the Device section + * in the xorg.conf file can over-ride the device ID. A matching PCI + * ID might not be found now, but after the device ID over-ride is + * applied there /might/ be a match. + */ + for (id = PCIchipsets; id->PCIid != -1; id++) { + const unsigned vendor_id = ((id->PCIid & 0xFFFF0000) >> 16) + | vendorID; + const unsigned device_id = (id->PCIid & 0x0000FFFF); + const unsigned match_class = 0x00030000 | id->PCIid; + + if ((vendor_id == pPci->vendor_id) + || ((vendorID == PCI_VENDOR_GENERIC) && (match_class == device_class))) { + if (!foundVendor && (instances != NULL)) { + ++allocatedInstances; + instances[allocatedInstances - 1].pci = pPci; + instances[allocatedInstances - 1].dev = NULL; + instances[allocatedInstances - 1].claimed = FALSE; + instances[allocatedInstances - 1].foundHW = FALSE; + instances[allocatedInstances - 1].screen = 0; + } + + foundVendor = TRUE; + + if ( (device_id == pPci->device_id) + || ((vendorID == PCI_VENDOR_GENERIC) + && (match_class == device_class)) ) { + if ( instances != NULL ) { + instances[allocatedInstances - 1].foundHW = TRUE; + instances[allocatedInstances - 1].chip = id->numChipset; + } + + + if ( xf86DoConfigure && xf86DoConfigurePass1 ) { + if (xf86CheckPciSlot(pPci)) { + GDevPtr pGDev = + xf86AddBusDeviceToConfigure(drvp->driverName, + BUS_PCI, pPci, -1); + if (pGDev) { + /* After configure pass 1, chipID and chipRev + * are treated as over-rides, so clobber them + * here. + */ + pGDev->chipID = -1; + pGDev->chipRev = -1; + } + + numFound++; + } + } + else { + numFound++; + } + + break; + } + } + } + } + + pci_iterator_destroy(iter); + + + /* In "probe only" or "configure" mode (signaled by instances being NULL), + * our work is done. Return the number of detected devices. + */ + if ( instances == NULL ) { + return numFound; + } + + + /* + * This may be debatable, but if no PCI devices with a matching vendor + * type is found, return zero now. It is probably not desirable to + * allow the config file to override this. + */ + if (allocatedInstances <= 0) { + free(instances); + return 0; + } + + + DebugF("%s instances found: %d\n", driverName, allocatedInstances); + + /* + * Check for devices that need duplicated instances. This is required + * when there is more than one screen per entity. + * + * XXX This currently doesn't work for cases where the BusID isn't + * specified explicitly in the config file. + */ + + for (j = 0; j < numDevs; j++) { + if (devList[j]->screen > 0 && devList[j]->busID + && *devList[j]->busID) { + for (i = 0; i < allocatedInstances; i++) { + pPci = instances[i].pci; + if (xf86ComparePciBusString(devList[j]->busID, + PCI_MAKE_BUS( pPci->domain, pPci->bus ), + pPci->dev, + pPci->func)) { + allocatedInstances++; + instances[allocatedInstances - 1] = instances[i]; + instances[allocatedInstances - 1].screen = devList[j]->screen; + numFound++; + break; + } + } + } + } + + for (i = 0; i < allocatedInstances; i++) { + GDevPtr dev = NULL; + GDevPtr devBus = NULL; + + pPci = instances[i].pci; + for (j = 0; j < numDevs; j++) { + if (devList[j]->busID && *devList[j]->busID) { + if (xf86ComparePciBusString(devList[j]->busID, + PCI_MAKE_BUS( pPci->domain, pPci->bus ), + pPci->dev, + pPci->func) && + devList[j]->screen == instances[i].screen) { + + if (devBus) + xf86MsgVerb(X_WARNING,0, + "%s: More than one matching Device section for " + "instances\n\t(BusID: %s) found: %s\n", + driverName, devList[j]->busID, + devList[j]->identifier); + else + devBus = devList[j]; + } + } else { + /* + * if device section without BusID is found + * only assign to it to the primary device. + */ + if (xf86IsPrimaryPci(pPci)) { + xf86Msg(X_PROBED, "Assigning device section with no busID" + " to primary device\n"); + if (dev || devBus) + xf86MsgVerb(X_WARNING, 0, + "%s: More than one matching Device section " + "found: %s\n", driverName, devList[j]->identifier); + else + dev = devList[j]; + } + } + } + if (devBus) dev = devBus; /* busID preferred */ + if (!dev) { + if (xf86CheckPciSlot(pPci) && pciDeviceHasBars(pPci)) { + xf86MsgVerb(X_WARNING, 0, "%s: No matching Device section " + "for instance (BusID PCI:%u@%u:%u:%u) found\n", + driverName, pPci->domain, pPci->bus, pPci->dev, + pPci->func); + } + } else { + numClaimedInstances++; + instances[i].claimed = TRUE; + instances[i].dev = dev; + } + } + DebugF("%s instances found: %d\n", driverName, numClaimedInstances); + /* + * Now check that a chipset or chipID override in the device section + * is valid. Chipset has precedence over chipID. + * If chipset is not valid ignore BusSlot completely. + */ + for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) { + MessageType from = X_PROBED; + + if (!instances[i].claimed) { + continue; + } + if (instances[i].dev->chipset) { + for (c = chipsets; c->token >= 0; c++) { + if (xf86NameCmp(c->name, instances[i].dev->chipset) == 0) + break; + } + if (c->token == -1) { + instances[i].claimed = FALSE; + numClaimedInstances--; + xf86MsgVerb(X_WARNING, 0, "%s: Chipset \"%s\" in Device " + "section \"%s\" isn't valid for this driver\n", + driverName, instances[i].dev->chipset, + instances[i].dev->identifier); + } else { + instances[i].chip = c->token; + + for (id = PCIchipsets; id->numChipset >= 0; id++) { + if (id->numChipset == instances[i].chip) + break; + } + if(id->numChipset >=0){ + xf86Msg(X_CONFIG,"Chipset override: %s\n", + instances[i].dev->chipset); + from = X_CONFIG; + } else { + instances[i].claimed = FALSE; + numClaimedInstances--; + xf86MsgVerb(X_WARNING, 0, "%s: Chipset \"%s\" in Device " + "section \"%s\" isn't a valid PCI chipset\n", + driverName, instances[i].dev->chipset, + instances[i].dev->identifier); + } + } + } else if (instances[i].dev->chipID > 0) { + for (id = PCIchipsets; id->numChipset >= 0; id++) { + if (id->PCIid == instances[i].dev->chipID) + break; + } + if (id->numChipset == -1) { + instances[i].claimed = FALSE; + numClaimedInstances--; + xf86MsgVerb(X_WARNING, 0, "%s: ChipID 0x%04X in Device " + "section \"%s\" isn't valid for this driver\n", + driverName, instances[i].dev->chipID, + instances[i].dev->identifier); + } else { + instances[i].chip = id->numChipset; + + xf86Msg( X_CONFIG,"ChipID override: 0x%04X\n", + instances[i].dev->chipID); + from = X_CONFIG; + } + } else if (!instances[i].foundHW) { + /* + * This means that there was no override and the PCI chipType + * doesn't match one that is supported + */ + instances[i].claimed = FALSE; + numClaimedInstances--; + } + if (instances[i].claimed == TRUE){ + for (c = chipsets; c->token >= 0; c++) { + if (c->token == instances[i].chip) + break; + } + xf86Msg(from,"Chipset %s found\n", + c->name); + } + } + + /* + * Of the claimed instances, check that another driver hasn't already + * claimed its slot. + */ + numFound = 0; + for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) { + if (!instances[i].claimed) + continue; + pPci = instances[i].pci; + + + /* + * Allow the same entity to be used more than once for devices with + * multiple screens per entity. This assumes implicitly that there + * will be a screen == 0 instance. + * + * XXX Need to make sure that two different drivers don't claim + * the same screen > 0 instance. + */ + if (instances[i].screen == 0 && !xf86CheckPciSlot( pPci )) + continue; + + DebugF("%s: card at %d:%d:%d is claimed by a Device section\n", + driverName, pPci->bus, pPci->dev, pPci->func); + + /* Allocate an entry in the lists to be returned */ + numFound++; + retEntities = xnfrealloc(retEntities, numFound * sizeof(int)); + retEntities[numFound - 1] = xf86ClaimPciSlot( pPci, drvp, + instances[i].chip, + instances[i].dev, + instances[i].dev->active); + if (retEntities[numFound - 1] == -1 && instances[i].screen > 0) { + for (j = 0; j < xf86NumEntities; j++) { + EntityPtr pEnt = xf86Entities[j]; + if (pEnt->bus.type != BUS_PCI) + continue; + if (pEnt->bus.id.pci == pPci) { + retEntities[numFound - 1] = j; + xf86AddDevToEntity(j, instances[i].dev); + break; + } + } + } + } + free(instances); + if (numFound > 0) { + *foundEntities = retEntities; + } + + return numFound; +} + +/* + * xf86ConfigPciEntityInactive() -- This function can be used + * to configure an inactive entity as well as to reconfigure an + * previously active entity inactive. If the entity has been + * assigned to a screen before it will be removed. If p_chip is + * non-NULL all static resources listed there will be registered. + */ +static void +xf86ConfigPciEntityInactive(EntityInfoPtr pEnt, PciChipsets *p_chip, + EntityProc init, EntityProc enter, + EntityProc leave, pointer private) +{ + ScrnInfoPtr pScrn; + + if ((pScrn = xf86FindScreenForEntity(pEnt->index))) + xf86RemoveEntityFromScreen(pScrn,pEnt->index); + + /* shared resources are only needed when entity is active: remove */ + xf86SetEntityFuncs(pEnt->index,init,enter,leave,private); +} + +ScrnInfoPtr +xf86ConfigPciEntity(ScrnInfoPtr pScrn, int scrnFlag, int entityIndex, + PciChipsets *p_chip, void *dummy, EntityProc init, + EntityProc enter, EntityProc leave, pointer private) +{ + EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex); + if (!pEnt) return pScrn; + + if (!(pEnt->location.type == BUS_PCI) + || !xf86GetPciInfoForEntity(entityIndex)) { + free(pEnt); + return pScrn; + } + if (!pEnt->active) { + xf86ConfigPciEntityInactive(pEnt, p_chip, init, enter, + leave, private); + free(pEnt); + return pScrn; + } + + if (!pScrn) + pScrn = xf86AllocateScreen(pEnt->driver,scrnFlag); + if (xf86IsEntitySharable(entityIndex)) { + xf86SetEntityShared(entityIndex); + } + xf86AddEntityToScreen(pScrn,entityIndex); + if (xf86IsEntityShared(entityIndex)) { + return pScrn; + } + free(pEnt); + + xf86SetEntityFuncs(entityIndex,init,enter,leave,private); + + return pScrn; +} + +/* + * OBSOLETE ! xf86ConfigActivePciEntity() is an obsolete function. + * It is likely to be removed. Don't use! + */ +Bool +xf86ConfigActivePciEntity(ScrnInfoPtr pScrn, int entityIndex, + PciChipsets *p_chip, void *dummy, EntityProc init, + EntityProc enter, EntityProc leave, pointer private) +{ + EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex); + if (!pEnt) return FALSE; + + if (!pEnt->active || !(pEnt->location.type == BUS_PCI)) { + free(pEnt); + return FALSE; + } + xf86AddEntityToScreen(pScrn,entityIndex); + + free(pEnt); + if (!xf86SetEntityFuncs(entityIndex,init,enter,leave,private)) + return FALSE; + + return TRUE; +} + +static int +videoPtrToDriverList(struct pci_device *dev, + char *returnList[], int returnListMax) +{ + int i; + /* Add more entries here if we ever return more than 4 drivers for + any device */ + char *driverList[5] = { NULL, NULL, NULL, NULL, NULL }; + + switch (dev->vendor_id) + { + /* AMD Geode LX */ + case 0x1022: + if (dev->device_id == 0x2081) + driverList[0] = "geode"; + break; + /* older Geode products acquired by AMD still carry an NSC vendor_id */ + case 0x100b: + if (dev->device_id == 0x0030) { + /* NSC Geode GX2 specifically */ + driverList[0] = "geode"; + /* GX2 support started its life in the NSC tree and was later + forked by AMD for GEODE so we keep it as a backup */ + driverList[1] = "nsc"; + } else + /* other NSC variant e.g. 0x0104 (SC1400), 0x0504 (SCx200) */ + driverList[0] = "nsc"; + break; + /* Cyrix Geode GX1 */ + case 0x1078: + if (dev->device_id == 0x0104) + driverList[0] = "cyrix"; + break; + case 0x1142: driverList[0] = "apm"; break; + case 0xedd8: driverList[0] = "ark"; break; + case 0x1a03: driverList[0] = "ast"; break; + case 0x1002: driverList[0] = "ati"; break; + case 0x102c: driverList[0] = "chips"; break; + case 0x1013: driverList[0] = "cirrus"; break; + case 0x3d3d: driverList[0] = "glint"; break; + case 0x105d: driverList[0] = "i128"; break; + case 0x8086: + if ((dev->device_id == 0x00d1) || (dev->device_id == 0x7800)) { + driverList[0] = "i740"; + } else if (dev->device_id == 0x8108) { + break; /* "hooray" for poulsbo */ + } else { + driverList[0] = "intel"; + } + break; + case 0x102b: driverList[0] = "mga"; break; + case 0x10c8: driverList[0] = "neomagic"; break; + case 0x10de: case 0x12d2: driverList[0] = "nv"; break; + case 0x1106: driverList[0] = "openchrome"; break; + case 0x1b36: driverList[0] = "qxl"; break; + case 0x1163: driverList[0] = "rendition"; break; + case 0x5333: + switch (dev->device_id) + { + case 0x88d0: case 0x88d1: case 0x88f0: case 0x8811: + case 0x8812: case 0x8814: case 0x8901: + driverList[0] = "s3"; break; + case 0x5631: case 0x883d: case 0x8a01: case 0x8a10: + case 0x8c01: case 0x8c03: case 0x8904: case 0x8a13: + driverList[0] = "s3virge"; break; + default: + driverList[0] = "savage"; break; + } + break; + case 0x1039: driverList[0] = "sis"; break; + case 0x126f: driverList[0] = "siliconmotion"; break; + case 0x121a: + if (dev->device_id < 0x0003) + driverList[0] = "voodoo"; + else + driverList[0] = "tdfx"; + break; + case 0x1011: driverList[0] = "tga"; break; + case 0x1023: driverList[0] = "trident"; break; + case 0x100c: driverList[0] = "tseng"; break; + case 0x80ee: driverList[0] = "vboxvideo"; break; + case 0x15ad: driverList[0] = "vmware"; break; + case 0x18ca: + if (dev->device_id == 0x47) + driverList[0] = "xgixp"; + else + driverList[0] = "xgi"; + break; + default: break; + } + for (i = 0; (i < returnListMax) && (driverList[i] != NULL); i++) { + returnList[i] = xnfstrdup(driverList[i]); + } + return i; /* Number of entries added */ +} + +#ifdef __linux__ +static int +xchomp(char *line) +{ + size_t len = 0; + + if (!line) { + return 1; + } + + len = strlen(line); + if (line[len - 1] == '\n' && len > 0) { + line[len - 1] = '\0'; + } + return 0; +} + +/* This function is used to provide a workaround for binary drivers that + * don't export their PCI ID's properly. If distros don't end up using this + * feature it can and should be removed because the symbol-based resolution + * scheme should be the primary one */ +static void +matchDriverFromFiles (char** matches, uint16_t match_vendor, uint16_t match_chip) +{ + DIR *idsdir; + FILE *fp; + struct dirent *direntry; + char *line = NULL; + size_t len; + ssize_t read; + char path_name[256], vendor_str[5], chip_str[5]; + uint16_t vendor, chip; + int i, j; + + idsdir = opendir(PCI_TXT_IDS_PATH); + if (!idsdir) + return; + + xf86Msg(X_INFO, "Scanning %s directory for additional PCI ID's supported by the drivers\n", PCI_TXT_IDS_PATH); + direntry = readdir(idsdir); + /* Read the directory */ + while (direntry) { + if (direntry->d_name[0] == '.') { + direntry = readdir(idsdir); + continue; + } + len = strlen(direntry->d_name); + /* A tiny bit of sanity checking. We should probably do better */ + if (strncmp(&(direntry->d_name[len-4]), ".ids", 4) == 0) { + /* We need the full path name to open the file */ + strncpy(path_name, PCI_TXT_IDS_PATH, 256); + strncat(path_name, "/", 1); + strncat(path_name, direntry->d_name, (256 - strlen(path_name) - 1)); + fp = fopen(path_name, "r"); + if (fp == NULL) { + xf86Msg(X_ERROR, "Could not open %s for reading. Exiting.\n", path_name); + goto end; + } + /* Read the file */ +#ifdef __GLIBC__ + while ((read = getline(&line, &len, fp)) != -1) { +#else + while ((line = fgetln(fp, &len)) != (char *)NULL) { +#endif /* __GLIBC __ */ + xchomp(line); + if (isdigit(line[0])) { + strncpy(vendor_str, line, 4); + vendor_str[4] = '\0'; + vendor = (int)strtol(vendor_str, NULL, 16); + if ((strlen(&line[4])) == 0) { + chip_str[0] = '\0'; + chip = -1; + } else { + /* Handle trailing whitespace */ + if (isspace(line[4])) { + chip_str[0] = '\0'; + chip = -1; + } else { + /* Ok, it's a real ID */ + strncpy(chip_str, &line[4], 4); + chip_str[4] = '\0'; + chip = (int)strtol(chip_str, NULL, 16); + } + } + if (vendor == match_vendor && chip == match_chip ) { + i = 0; + while (matches[i]) { + i++; + } + matches[i] = (char*)malloc(sizeof(char) * strlen(direntry->d_name) - 3); + if (!matches[i]) { + xf86Msg(X_ERROR, "Could not allocate space for the module name. Exiting.\n"); + goto end; + } + /* hack off the .ids suffix. This should guard + * against other problems, but it will end up + * taking off anything after the first '.' */ + for (j = 0; j < (strlen(direntry->d_name) - 3) ; j++) { + if (direntry->d_name[j] == '.') { + matches[i][j] = '\0'; + break; + } else { + matches[i][j] = direntry->d_name[j]; + } + } + xf86Msg(X_INFO, "Matched %s from file name %s\n", matches[i], direntry->d_name); + } + } else { + /* TODO Handle driver overrides here */ + } + } + fclose(fp); + } + direntry = readdir(idsdir); + } + end: + free(line); + closedir(idsdir); +} +#endif /* __linux__ */ + +/** + * @return The numbers of found devices that match with the current system + * drivers. + */ +int +xf86PciMatchDriver(char* matches[], int nmatches) { + int i; + struct pci_device * info = NULL; + struct pci_device_iterator *iter; + + /* Find the primary device, and get some information about it. */ + iter = pci_slot_match_iterator_create(NULL); + while ((info = pci_device_next(iter)) != NULL) { + if (xf86IsPrimaryPci(info)) { + break; + } + } + + pci_iterator_destroy(iter); +#ifdef __linux__ + if (info) + matchDriverFromFiles(matches, info->vendor_id, info->device_id); +#endif + + for (i = 0; (i < nmatches) && (matches[i]); i++) { + /* find end of matches list */ + } + + if ((info != NULL) && (i < nmatches)) { + i += videoPtrToDriverList(info, &(matches[i]), nmatches - i); + } + + return i; +} + +Bool +xf86PciConfigure(void *busData, struct pci_device *pDev) +{ + struct pci_device * pVideo = NULL; + + pVideo = (struct pci_device *) busData; + if (pDev && + (pDev->domain == pVideo->domain) && + (pDev->bus == pVideo->bus) && + (pDev->dev == pVideo->dev) && + (pDev->func == pVideo->func)) + return 0; + + return 1; +} + +void +xf86PciConfigureNewDev(void *busData, struct pci_device *pVideo, + GDevRec *GDev, int *chipset) +{ + char busnum[8]; + + pVideo = (struct pci_device *) busData; + + xf86FormatPciBusNumber(pVideo->bus, busnum); + XNFasprintf(&GDev->busID, "PCI:%s:%d:%d", + busnum, pVideo->dev, pVideo->func); + + GDev->chipID = pVideo->device_id; + GDev->chipRev = pVideo->revision; + + if (*chipset < 0) + *chipset = (pVideo->vendor_id << 16) | pVideo->device_id; +} diff --git a/hw/xfree86/common/xf86pciBus.h b/hw/xfree86/common/xf86pciBus.h new file mode 100644 index 0000000..e625e51 --- /dev/null +++ b/hw/xfree86/common/xf86pciBus.h @@ -0,0 +1,45 @@ + +/* + * Copyright (c) 1999-2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#ifndef _XF86_PCI_BUS_H +#define _XF86_PCI_BUS_H + +void xf86PciProbe(void); +Bool xf86PciAddMatchingDev(DriverPtr drvp); +Bool xf86PciProbeDev(DriverPtr drvp); +void xf86PciIsolateDevice(char *argument); +int xf86PciMatchDriver(char* matches[], int nmatches); +Bool xf86PciConfigure(void *busData, struct pci_device *pDev); +void xf86PciConfigureNewDev(void *busData, struct pci_device *pVideo, + GDevRec *GDev, int *chipset); + +#endif /* _XF86_PCI_BUS_H */ diff --git a/hw/xfree86/common/xf86sbusBus.c b/hw/xfree86/common/xf86sbusBus.c new file mode 100644 index 0000000..181c6ab --- /dev/null +++ b/hw/xfree86/common/xf86sbusBus.c @@ -0,0 +1,714 @@ +/* + * SBUS bus-specific code. + * + * Copyright (C) 2000 Jakub Jelinek (jakub@redhat.com) + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * JAKUB JELINEK 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. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <ctype.h> +#include <stdio.h> +#include <unistd.h> +#include <X11/X.h> +#include "os.h" +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" +#include "xf86cmap.h" + +#include "xf86Bus.h" + +#include "xf86sbusBus.h" +#include "xf86Sbus.h" + +Bool sbusSlotClaimed = FALSE; + +static int xf86nSbusInfo; + +static void +CheckSbusDevice(const char *device, int fbNum) +{ + int fd, i; + struct fbgattr fbattr; + sbusDevicePtr psdp; + + fd = open(device, O_RDONLY, 0); + if (fd < 0) + return; + memset(&fbattr, 0, sizeof(fbattr)); + if (ioctl(fd, FBIOGATTR, &fbattr) < 0) { + if (ioctl(fd, FBIOGTYPE, &fbattr.fbtype) < 0) { + close(fd); + return; + } + } + close(fd); + for (i = 0; sbusDeviceTable[i].devId; i++) + if (sbusDeviceTable[i].fbType == fbattr.fbtype.fb_type) + break; + if (! sbusDeviceTable[i].devId) + return; + xf86SbusInfo = xnfrealloc(xf86SbusInfo, sizeof(psdp) * (++xf86nSbusInfo + 1)); + xf86SbusInfo[xf86nSbusInfo] = NULL; + xf86SbusInfo[xf86nSbusInfo - 1] = psdp = xnfcalloc(sizeof (sbusDevice), 1); + psdp->devId = sbusDeviceTable[i].devId; + psdp->fbNum = fbNum; + psdp->device = xnfstrdup(device); + psdp->width = fbattr.fbtype.fb_width; + psdp->height = fbattr.fbtype.fb_height; + psdp->fd = -1; +} + +void +xf86SbusProbe(void) +{ + int i, useProm = 0; + char fbDevName[32]; + sbusDevicePtr psdp, *psdpp; + + xf86SbusInfo = malloc(sizeof(psdp)); + *xf86SbusInfo = NULL; + for (i = 0; i < 32; i++) { + sprintf(fbDevName, "/dev/fb%d", i); + CheckSbusDevice(fbDevName, i); + } + if (sparcPromInit() >= 0) { + useProm = 1; + sparcPromAssignNodes(); + } + for (psdpp = xf86SbusInfo; (psdp = *psdpp); psdpp++) { + for (i = 0; sbusDeviceTable[i].devId; i++) + if (sbusDeviceTable[i].devId == psdp->devId) + psdp->descr = sbusDeviceTable[i].descr; + /* + * If we can use PROM information and found the PROM node for this + * device, we can tell more about the card. + */ + if (useProm && psdp->node.node) { + char *prop, *promPath; + int len, chiprev, vmsize; + + switch (psdp->devId) { + case SBUS_DEVICE_MGX: + prop = sparcPromGetProperty(&psdp->node, "fb_size", &len); + if (prop && len == 4 && *(int *)prop == 0x400000) + psdp->descr = "Quantum 3D MGXplus with 4M VRAM"; + break; + case SBUS_DEVICE_CG6: + chiprev = 0; + vmsize = 0; + prop = sparcPromGetProperty(&psdp->node, "chiprev", &len); + if (prop && len == 4) + chiprev = *(int *)prop; + prop = sparcPromGetProperty(&psdp->node, "vmsize", &len); + if (prop && len == 4) + vmsize = *(int *)prop; + switch (chiprev) { + case 1: + case 2: + case 3: + case 4: + psdp->descr = "Sun Double width GX"; break; + case 5: + case 6: + case 7: + case 8: + case 9: + psdp->descr = "Sun Single width GX"; break; + case 11: + switch (vmsize) { + case 2: + psdp->descr = "Sun Turbo GX with 1M VSIMM"; break; + case 4: + psdp->descr = "Sun Turbo GX Plus"; break; + default: + psdp->descr = "Sun Turbo GX"; break; + } + } + break; + case SBUS_DEVICE_CG14: + prop = sparcPromGetProperty(&psdp->node, "reg", &len); + vmsize = 0; + if (prop && !(len % 12) && len > 0) + vmsize = *(int *)(prop + len - 4); + switch (vmsize) { + case 0x400000: + psdp->descr = "Sun SX with 4M VSIMM"; break; + case 0x800000: + psdp->descr = "Sun SX with 8M VSIMM"; break; + } + break; + case SBUS_DEVICE_LEO: + prop = sparcPromGetProperty(&psdp->node, "model", &len); + if (prop && len > 0 && !strstr(prop, "501-2503")) + psdp->descr = "Sun Turbo ZX"; + break; + case SBUS_DEVICE_TCX: + if (sparcPromGetBool(&psdp->node, "tcx-8-bit")) + psdp->descr = "Sun TCX (8bit)"; + else + psdp->descr = "Sun TCX (S24)"; + break; + case SBUS_DEVICE_FFB: + prop = sparcPromGetProperty(&psdp->node, "name", &len); + chiprev = 0; + prop = sparcPromGetProperty(&psdp->node, "board_type", &len); + if (prop && len == 4) + chiprev = *(int *)prop; + if (strstr (prop, "afb")) { + if (chiprev == 3) + psdp->descr = "Sun|Elite3D-M6 Horizontal"; + } else { + switch (chiprev) { + case 0x08: + psdp->descr = "Sun FFB 67MHz Creator"; break; + case 0x0b: + psdp->descr = "Sun FFB 67MHz Creator 3D"; break; + case 0x1b: + psdp->descr = "Sun FFB 75MHz Creator 3D"; break; + case 0x20: + case 0x28: + psdp->descr = "Sun FFB2 Vertical Creator"; break; + case 0x23: + case 0x2b: + psdp->descr = "Sun FFB2 Vertical Creator 3D"; break; + case 0x30: + psdp->descr = "Sun FFB2+ Vertical Creator"; break; + case 0x33: + psdp->descr = "Sun FFB2+ Vertical Creator 3D"; break; + case 0x40: + case 0x48: + psdp->descr = "Sun FFB2 Horizontal Creator"; break; + case 0x43: + case 0x4b: + psdp->descr = "Sun FFB2 Horizontal Creator 3D"; break; + } + } + break; + } + + xf86Msg(X_PROBED, "SBUS:(0x%08x) %s", psdp->node.node, psdp->descr); + promPath = sparcPromNode2Pathname (&psdp->node); + if (promPath) { + xf86ErrorF(" at %s", promPath); + free(promPath); + } + } else + xf86Msg(X_PROBED, "SBUS: %s", psdp->descr); + xf86ErrorF("\n"); + } + if (useProm) + sparcPromClose(); +} + +/* + * Parse a BUS ID string, and return the SBUS bus parameters if it was + * in the correct format for a SBUS bus id. + */ + +Bool +xf86ParseSbusBusString(const char *busID, int *fbNum) +{ + /* + * The format is assumed to be one of: + * "fbN", e.g. "fb1", which means the device corresponding to /dev/fbN + * "nameN", e.g. "cgsix0", which means Nth instance of card NAME + * "/prompath", e.g. "/sbus@0,10001000/cgsix@3,0" which is PROM pathname + * to the device. + */ + + const char *id; + int i, len; + + if (StringToBusType(busID, &id) != BUS_SBUS) + return FALSE; + + if (*id != '/') { + if (!strncmp (id, "fb", 2)) { + if (!isdigit(id[2])) + return FALSE; + *fbNum = atoi(id + 2); + return TRUE; + } else { + sbusDevicePtr *psdpp; + int devId; + + for (i = 0, len = 0; sbusDeviceTable[i].devId; i++) { + len = strlen(sbusDeviceTable[i].promName); + if (!strncmp (sbusDeviceTable[i].promName, id, len) + && isdigit(id[len])) + break; + } + devId = sbusDeviceTable[i].devId; + if (!devId) return FALSE; + i = atoi(id + len); + for (psdpp = xf86SbusInfo; *psdpp; ++psdpp) { + if ((*psdpp)->devId != devId) + continue; + if (!i) { + *fbNum = (*psdpp)->fbNum; + return TRUE; + } + i--; + } + } + return FALSE; + } + + if (sparcPromInit() >= 0) { + i = sparcPromPathname2Node(id); + sparcPromClose(); + if (i) { + sbusDevicePtr *psdpp; + for (psdpp = xf86SbusInfo; *psdpp; ++psdpp) { + if ((*psdpp)->node.node == i) { + *fbNum = (*psdpp)->fbNum; + return TRUE; + } + } + } + } + return FALSE; +} + +/* + * Compare a BUS ID string with a SBUS bus id. Return TRUE if they match. + */ + +Bool +xf86CompareSbusBusString(const char *busID, int fbNum) +{ + int iFbNum; + + if (xf86ParseSbusBusString(busID, &iFbNum)) { + return fbNum == iFbNum; + } else { + return FALSE; + } +} + +/* + * Check if the slot requested is free. If it is already in use, return FALSE. + */ + +Bool +xf86CheckSbusSlot(int fbNum) +{ + int i; + EntityPtr p; + + for (i = 0; i < xf86NumEntities; i++) { + p = xf86Entities[i]; + /* Check if this SBUS slot is taken */ + if (p->bus.type == BUS_SBUS && p->bus.id.sbus.fbNum == fbNum) + return FALSE; + } + + return TRUE; +} + +/* + * If the slot requested is already in use, return -1. + * Otherwise, claim the slot for the screen requesting it. + */ + +int +xf86ClaimSbusSlot(sbusDevicePtr psdp, DriverPtr drvp, + GDevPtr dev, Bool active) +{ + EntityPtr p = NULL; + + int num; + + if (xf86CheckSbusSlot(psdp->fbNum)) { + num = xf86AllocateEntity(); + p = xf86Entities[num]; + p->driver = drvp; + p->chipset = -1; + p->bus.type = BUS_SBUS; + xf86AddDevToEntity(num, dev); + p->bus.id.sbus.fbNum = psdp->fbNum; + p->active = active; + p->inUse = FALSE; + sbusSlotClaimed = TRUE; + return num; + } else + return -1; +} + +int +xf86MatchSbusInstances(const char *driverName, int sbusDevId, + GDevPtr *devList, int numDevs, DriverPtr drvp, + int **foundEntities) +{ + int i,j; + sbusDevicePtr psdp, *psdpp; + int numClaimedInstances = 0; + int allocatedInstances = 0; + int numFound = 0; + GDevPtr devBus = NULL; + GDevPtr dev = NULL; + int *retEntities = NULL; + int useProm = 0; + + struct Inst { + sbusDevicePtr sbus; + GDevPtr dev; + Bool claimed; /* BusID matches with a device section */ + } *instances = NULL; + + *foundEntities = NULL; + for (psdpp = xf86SbusInfo, psdp = *psdpp; psdp; psdp = *++psdpp) { + if (psdp->devId != sbusDevId) + continue; + if (psdp->fd == -2) + continue; + ++allocatedInstances; + instances = xnfrealloc(instances, + allocatedInstances * sizeof(struct Inst)); + instances[allocatedInstances - 1].sbus = psdp; + instances[allocatedInstances - 1].dev = NULL; + instances[allocatedInstances - 1].claimed = FALSE; + numFound++; + } + + /* + * This may be debatable, but if no SBUS devices with a matching vendor + * type is found, return zero now. It is probably not desirable to + * allow the config file to override this. + */ + if (allocatedInstances <= 0) { + free(instances); + return 0; + } + + if (sparcPromInit() >= 0) + useProm = 1; + + if (xf86DoConfigure && xf86DoConfigurePass1) { + GDevPtr pGDev; + int actualcards = 0; + for (i = 0; i < allocatedInstances; i++) { + actualcards++; + pGDev = xf86AddBusDeviceToConfigure(drvp->driverName, BUS_SBUS, + instances[i].sbus, -1); + if (pGDev) { + /* + * XF86Match???Instances() treat chipID and chipRev as + * overrides, so clobber them here. + */ + pGDev->chipID = pGDev->chipRev = -1; + } + } + free(instances); + if (useProm) + sparcPromClose(); + return actualcards; + } + + DebugF("%s instances found: %d\n", driverName, allocatedInstances); + + for (i = 0; i < allocatedInstances; i++) { + char *promPath = NULL; + + psdp = instances[i].sbus; + devBus = NULL; + dev = NULL; + if (useProm && psdp->node.node) + promPath = sparcPromNode2Pathname(&psdp->node); + + for (j = 0; j < numDevs; j++) { + if (devList[j]->busID && *devList[j]->busID) { + if (xf86CompareSbusBusString(devList[j]->busID, psdp->fbNum)) { + if (devBus) + xf86MsgVerb(X_WARNING,0, + "%s: More than one matching Device section for " + "instance (BusID: %s) found: %s\n", + driverName,devList[j]->identifier, + devList[j]->busID); + else + devBus = devList[j]; + } + } else { + if (!dev && !devBus) { + if (promPath) + xf86Msg(X_PROBED, "Assigning device section with no busID to SBUS:%s\n", + promPath); + else + xf86Msg(X_PROBED, "Assigning device section with no busID to SBUS:fb%d\n", + psdp->fbNum); + dev = devList[j]; + } else + xf86MsgVerb(X_WARNING, 0, + "%s: More than one matching Device section " + "found: %s\n", driverName, devList[j]->identifier); + } + } + if (devBus) dev = devBus; /* busID preferred */ + if (!dev && psdp->fd != -2) { + if (promPath) { + xf86MsgVerb(X_WARNING, 0, "%s: No matching Device section " + "for instance (BusID SBUS:%s) found\n", + driverName, promPath); + } else + xf86MsgVerb(X_WARNING, 0, "%s: No matching Device section " + "for instance (BusID SBUS:fb%d) found\n", + driverName, psdp->fbNum); + } else if (dev) { + numClaimedInstances++; + instances[i].claimed = TRUE; + instances[i].dev = dev; + } + free(promPath); + } + + DebugF("%s instances found: %d\n", driverName, numClaimedInstances); + + /* + * Of the claimed instances, check that another driver hasn't already + * claimed its slot. + */ + numFound = 0; + for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) { + if (!instances[i].claimed) + continue; + psdp = instances[i].sbus; + if (!xf86CheckSbusSlot(psdp->fbNum)) + continue; + + DebugF("%s: card at fb%d %08x is claimed by a Device section\n", + driverName, psdp->fbNum, psdp->node.node); + + /* Allocate an entry in the lists to be returned */ + numFound++; + retEntities = xnfrealloc(retEntities, numFound * sizeof(int)); + retEntities[numFound - 1] + = xf86ClaimSbusSlot(psdp, drvp, instances[i].dev,instances[i].dev->active ? + TRUE : FALSE); + } + free(instances); + if (numFound > 0) { + *foundEntities = retEntities; + } + + if (useProm) + sparcPromClose(); + + return numFound; +} + +/* + * xf86GetSbusInfoForEntity() -- Get the sbusDevicePtr of entity. + */ +sbusDevicePtr +xf86GetSbusInfoForEntity(int entityIndex) +{ + sbusDevicePtr *psdpp; + EntityPtr p = xf86Entities[entityIndex]; + + if (entityIndex >= xf86NumEntities + || p->bus.type != BUS_SBUS) return NULL; + + for (psdpp = xf86SbusInfo; *psdpp != NULL; psdpp++) { + if (p->bus.id.sbus.fbNum == (*psdpp)->fbNum) + return *psdpp; + } + return NULL; +} + +int +xf86GetEntityForSbusInfo(sbusDevicePtr psdp) +{ + int i; + + for (i = 0; i < xf86NumEntities; i++) { + EntityPtr p = xf86Entities[i]; + if (p->bus.type != BUS_SBUS) continue; + + if (p->bus.id.sbus.fbNum == psdp->fbNum) + return i; + } + return -1; +} + +void +xf86SbusUseBuiltinMode(ScrnInfoPtr pScrn, sbusDevicePtr psdp) +{ + DisplayModePtr mode; + + mode = xnfcalloc(sizeof(DisplayModeRec), 1); + mode->name = "current"; + mode->next = mode; + mode->prev = mode; + mode->type = M_T_BUILTIN; + mode->Clock = 100000000; + mode->HDisplay = psdp->width; + mode->HSyncStart = psdp->width; + mode->HSyncEnd = psdp->width; + mode->HTotal = psdp->width; + mode->VDisplay = psdp->height; + mode->VSyncStart = psdp->height; + mode->VSyncEnd = psdp->height; + mode->VTotal = psdp->height; + mode->SynthClock = mode->Clock; + mode->CrtcHDisplay = mode->HDisplay; + mode->CrtcHSyncStart = mode->HSyncStart; + mode->CrtcHSyncEnd = mode->HSyncEnd; + mode->CrtcHTotal = mode->HTotal; + mode->CrtcVDisplay = mode->VDisplay; + mode->CrtcVSyncStart = mode->VSyncStart; + mode->CrtcVSyncEnd = mode->VSyncEnd; + mode->CrtcVTotal = mode->VTotal; + mode->CrtcHAdjusted = FALSE; + mode->CrtcVAdjusted = FALSE; + pScrn->modes = mode; + pScrn->virtualX = psdp->width; + pScrn->virtualY = psdp->height; +} + +static sbusPaletteKeyIndex; +static DevPrivateKey sbusPaletteKey = &sbusPaletteKeyIndex; +typedef struct _sbusCmap { + sbusDevicePtr psdp; + CloseScreenProcPtr CloseScreen; + Bool origCmapValid; + unsigned char origRed[16]; + unsigned char origGreen[16]; + unsigned char origBlue[16]; +} sbusCmapRec, *sbusCmapPtr; + +#define SBUSCMAPPTR(pScreen) ((sbusCmapPtr) \ + dixLookupPrivate(&(pScreen)->devPrivates, sbusPaletteKey)) + +static void +xf86SbusCmapLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, + LOCO *colors, VisualPtr pVisual) +{ + int i, index; + sbusCmapPtr cmap; + struct fbcmap fbcmap; + unsigned char *data = malloc(numColors*3); + + cmap = SBUSCMAPPTR(pScrn->pScreen); + if (!cmap) return; + fbcmap.count = 0; + fbcmap.index = indices[0]; + fbcmap.red = data; + fbcmap.green = data + numColors; + fbcmap.blue = fbcmap.green + numColors; + for (i = 0; i < numColors; i++) { + index = indices[i]; + if (fbcmap.count && index != fbcmap.index + fbcmap.count) { + ioctl (cmap->psdp->fd, FBIOPUTCMAP, &fbcmap); + fbcmap.count = 0; + fbcmap.index = index; + } + fbcmap.red[fbcmap.count] = colors[index].red; + fbcmap.green[fbcmap.count] = colors[index].green; + fbcmap.blue[fbcmap.count++] = colors[index].blue; + } + ioctl (cmap->psdp->fd, FBIOPUTCMAP, &fbcmap); + free(data); +} + +static Bool +xf86SbusCmapCloseScreen(int i, ScreenPtr pScreen) +{ + sbusCmapPtr cmap; + struct fbcmap fbcmap; + + cmap = SBUSCMAPPTR(pScreen); + if (cmap->origCmapValid) { + fbcmap.index = 0; + fbcmap.count = 16; + fbcmap.red = cmap->origRed; + fbcmap.green = cmap->origGreen; + fbcmap.blue = cmap->origBlue; + ioctl (cmap->psdp->fd, FBIOPUTCMAP, &fbcmap); + } + pScreen->CloseScreen = cmap->CloseScreen; + free(cmap); + return (*pScreen->CloseScreen) (i, pScreen); +} + +Bool +xf86SbusHandleColormaps(ScreenPtr pScreen, sbusDevicePtr psdp) +{ + sbusCmapPtr cmap; + struct fbcmap fbcmap; + unsigned char data[2]; + + cmap = xnfcalloc(1, sizeof(sbusCmapRec)); + dixSetPrivate(&pScreen->devPrivates, sbusPaletteKey, cmap); + cmap->psdp = psdp; + fbcmap.index = 0; + fbcmap.count = 16; + fbcmap.red = cmap->origRed; + fbcmap.green = cmap->origGreen; + fbcmap.blue = cmap->origBlue; + if (ioctl (psdp->fd, FBIOGETCMAP, &fbcmap) >= 0) + cmap->origCmapValid = TRUE; + fbcmap.index = 0; + fbcmap.count = 2; + fbcmap.red = data; + fbcmap.green = data; + fbcmap.blue = data; + if (pScreen->whitePixel == 0) { + data[0] = 255; + data[1] = 0; + } else { + data[0] = 0; + data[1] = 255; + } + ioctl (psdp->fd, FBIOPUTCMAP, &fbcmap); + cmap->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = xf86SbusCmapCloseScreen; + return xf86HandleColormaps(pScreen, 256, 8, + xf86SbusCmapLoadPalette, NULL, 0); +} + +Bool +xf86SbusConfigure(void *busData, sbusDevicePtr sBus) +{ + if (sBus && sBus->fbNum == ((sbusDevicePtr) busData)->fbNum) + return 0; + return 1; +} + +void +xf86SbusConfigureNewDev(void *busData, sbusDevicePtr sBus, GDevRec *GDev) +{ + char *promPath = NULL; + + sBus = (sbusDevicePtr) busData; + GDev->identifier = sBus->descr; + if (sparcPromInit() >= 0) { + promPath = sparcPromNode2Pathname(&sBus->node); + sparcPromClose(); + } + if (promPath) { + XNFasprintf(&GDev->busID, "SBUS:%s", promPath); + free(promPath); + } else { + XNFasprintf(&GDev->busID, "SBUS:fb%d", sBus->fbNum); + } +} diff --git a/hw/xfree86/common/xf86sbusBus.h b/hw/xfree86/common/xf86sbusBus.h new file mode 100644 index 0000000..66a96e3 --- /dev/null +++ b/hw/xfree86/common/xf86sbusBus.h @@ -0,0 +1,104 @@ +/* + * SBUS bus-specific declarations + * + * Copyright (C) 2000 Jakub Jelinek (jakub@redhat.com) + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * JAKUB JELINEK 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. + */ + +#ifndef _XF86_SBUSBUS_H +#define _XF86_SBUSBUS_H + +#include "xf86str.h" + +#define SBUS_DEVICE_BW2 0x0001 +#define SBUS_DEVICE_CG2 0x0002 +#define SBUS_DEVICE_CG3 0x0003 +#define SBUS_DEVICE_CG4 0x0004 +#define SBUS_DEVICE_CG6 0x0005 +#define SBUS_DEVICE_CG8 0x0006 +#define SBUS_DEVICE_CG12 0x0007 +#define SBUS_DEVICE_CG14 0x0008 +#define SBUS_DEVICE_LEO 0x0009 +#define SBUS_DEVICE_TCX 0x000a +#define SBUS_DEVICE_FFB 0x000b +#define SBUS_DEVICE_GT 0x000c +#define SBUS_DEVICE_MGX 0x000d + +typedef struct sbus_prom_node { + int node; + /* Because of misdesigned openpromio */ + int cookie[2]; +} sbusPromNode, *sbusPromNodePtr; + +typedef struct sbus_device { + int devId; + int fbNum; + int fd; + int width, height; + sbusPromNode node; + char *descr; + char *device; +} sbusDevice, *sbusDevicePtr; + +struct sbus_devtable { + int devId; + int fbType; + char *promName; + char *driverName; + char *descr; +}; + +extern _X_EXPORT void xf86SbusProbe(void); +extern _X_EXPORT sbusDevicePtr *xf86SbusInfo; +extern _X_EXPORT struct sbus_devtable sbusDeviceTable[]; + +extern _X_EXPORT int xf86MatchSbusInstances(const char *driverName, int sbusDevId, + GDevPtr *devList, int numDevs, DriverPtr drvp, + int **foundEntities); +extern _X_EXPORT sbusDevicePtr xf86GetSbusInfoForEntity(int entityIndex); +extern _X_EXPORT int xf86GetEntityForSbusInfo(sbusDevicePtr psdp); +extern _X_EXPORT void xf86SbusUseBuiltinMode(ScrnInfoPtr pScrn, sbusDevicePtr psdp); +extern _X_EXPORT pointer xf86MapSbusMem(sbusDevicePtr psdp, unsigned long offset, + unsigned long size); +extern _X_EXPORT void xf86UnmapSbusMem(sbusDevicePtr psdp, pointer addr, unsigned long size); +extern _X_EXPORT void xf86SbusHideOsHwCursor(sbusDevicePtr psdp); +extern _X_EXPORT void xf86SbusSetOsHwCursorCmap(sbusDevicePtr psdp, int bg, int fg); +extern _X_EXPORT Bool xf86SbusHandleColormaps(ScreenPtr pScreen, sbusDevicePtr psdp); + +extern _X_EXPORT int promRootNode; + +extern _X_EXPORT int promGetSibling(int node); +extern _X_EXPORT int promGetChild(int node); +extern _X_EXPORT char * promGetProperty(const char *prop, int *lenp); +extern _X_EXPORT int promGetBool(const char *prop); + +extern _X_EXPORT int sparcPromInit(void); +extern _X_EXPORT void sparcPromClose(void); +extern _X_EXPORT char * sparcPromGetProperty(sbusPromNodePtr pnode, const char *prop, int *lenp); +extern _X_EXPORT int sparcPromGetBool(sbusPromNodePtr pnode, const char *prop); +extern _X_EXPORT void sparcPromAssignNodes(void); +extern _X_EXPORT char * sparcPromNode2Pathname(sbusPromNodePtr pnode); +extern _X_EXPORT int sparcPromPathname2Node(const char *pathName); +extern _X_EXPORT char *sparcDriverName(void); + +extern Bool xf86SbusConfigure(void *busData, sbusDevicePtr sBus); +extern void xf86SbusConfigureNewDev(void *busData, sbusDevicePtr sBus, + GDevRec *GDev); + +#endif /* _XF86_SBUSBUS_H */ diff --git a/hw/xfree86/common/xf86str.h b/hw/xfree86/common/xf86str.h new file mode 100644 index 0000000..0493dc5 --- /dev/null +++ b/hw/xfree86/common/xf86str.h @@ -0,0 +1,906 @@ + +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * This file contains definitions of the public XFree86 data structures/types. + * Any data structures that video drivers need to access should go here. + */ + +#ifndef _XF86STR_H +#define _XF86STR_H + +#include "misc.h" +#include "input.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "colormapst.h" +#include "xf86Module.h" +#include "xf86Opt.h" +#include "xf86Pci.h" + +#include <pciaccess.h> + +/** + * Integer type that is of the size of the addressable memory (machine size). + * On most platforms \c uintptr_t will suffice. However, on some mixed + * 32-bit / 64-bit platforms, such as 32-bit binaries on 64-bit PowerPC, this + * must be 64-bits. + */ +#include <inttypes.h> +#if defined(__powerpc__) +typedef uint64_t memType; +#else +typedef uintptr_t memType; +#endif + + +/* Video mode flags */ + +typedef enum { + V_PHSYNC = 0x0001, + V_NHSYNC = 0x0002, + V_PVSYNC = 0x0004, + V_NVSYNC = 0x0008, + V_INTERLACE = 0x0010, + V_DBLSCAN = 0x0020, + V_CSYNC = 0x0040, + V_PCSYNC = 0x0080, + V_NCSYNC = 0x0100, + V_HSKEW = 0x0200, /* hskew provided */ + V_BCAST = 0x0400, + V_PIXMUX = 0x1000, + V_DBLCLK = 0x2000, + V_CLKDIV2 = 0x4000 +} ModeFlags; + +typedef enum { + INTERLACE_HALVE_V = 0x0001 /* Halve V values for interlacing */ +} CrtcAdjustFlags; + +/* Flags passed to ChipValidMode() */ +typedef enum { + MODECHECK_INITIAL = 0, + MODECHECK_FINAL = 1 +} ModeCheckFlags; + +/* These are possible return values for xf86CheckMode() and ValidMode() */ +typedef enum { + MODE_OK = 0, /* Mode OK */ + MODE_HSYNC, /* hsync out of range */ + MODE_VSYNC, /* vsync out of range */ + MODE_H_ILLEGAL, /* mode has illegal horizontal timings */ + MODE_V_ILLEGAL, /* mode has illegal horizontal timings */ + MODE_BAD_WIDTH, /* requires an unsupported linepitch */ + MODE_NOMODE, /* no mode with a maching name */ + MODE_NO_INTERLACE, /* interlaced mode not supported */ + MODE_NO_DBLESCAN, /* doublescan mode not supported */ + MODE_NO_VSCAN, /* multiscan mode not supported */ + MODE_MEM, /* insufficient video memory */ + MODE_VIRTUAL_X, /* mode width too large for specified virtual size */ + MODE_VIRTUAL_Y, /* mode height too large for specified virtual size */ + MODE_MEM_VIRT, /* insufficient video memory given virtual size */ + MODE_NOCLOCK, /* no fixed clock available */ + MODE_CLOCK_HIGH, /* clock required is too high */ + MODE_CLOCK_LOW, /* clock required is too low */ + MODE_CLOCK_RANGE, /* clock/mode isn't in a ClockRange */ + MODE_BAD_HVALUE, /* horizontal timing was out of range */ + MODE_BAD_VVALUE, /* vertical timing was out of range */ + MODE_BAD_VSCAN, /* VScan value out of range */ + MODE_HSYNC_NARROW, /* horizontal sync too narrow */ + MODE_HSYNC_WIDE, /* horizontal sync too wide */ + MODE_HBLANK_NARROW, /* horizontal blanking too narrow */ + MODE_HBLANK_WIDE, /* horizontal blanking too wide */ + MODE_VSYNC_NARROW, /* vertical sync too narrow */ + MODE_VSYNC_WIDE, /* vertical sync too wide */ + MODE_VBLANK_NARROW, /* vertical blanking too narrow */ + MODE_VBLANK_WIDE, /* vertical blanking too wide */ + MODE_PANEL, /* exceeds panel dimensions */ + MODE_INTERLACE_WIDTH, /* width too large for interlaced mode */ + MODE_ONE_WIDTH, /* only one width is supported */ + MODE_ONE_HEIGHT, /* only one height is supported */ + MODE_ONE_SIZE, /* only one resolution is supported */ + MODE_NO_REDUCED, /* monitor doesn't accept reduced blanking */ + MODE_BANDWIDTH, /* mode requires too much memory bandwidth */ + MODE_BAD = -2, /* unspecified reason */ + MODE_ERROR = -1 /* error condition */ +} ModeStatus; + +/* + * The mode sets are, from best to worst: USERDEF, DRIVER, and DEFAULT/BUILTIN. + * Preferred will bubble a mode to the top within a set. + */ +# define M_T_BUILTIN 0x01 /* built-in mode */ +# define M_T_CLOCK_C (0x02 | M_T_BUILTIN) /* built-in mode - configure clock */ +# define M_T_CRTC_C (0x04 | M_T_BUILTIN) /* built-in mode - configure CRTC */ +# define M_T_CLOCK_CRTC_C (M_T_CLOCK_C | M_T_CRTC_C) + /* built-in mode - configure CRTC and clock */ +# define M_T_PREFERRED 0x08 /* preferred mode within a set */ +# define M_T_DEFAULT 0x10 /* (VESA) default modes */ +# define M_T_USERDEF 0x20 /* One of the modes from the config file */ +# define M_T_DRIVER 0x40 /* Supplied by the driver (EDID, etc) */ +# define M_T_USERPREF 0x80 /* mode preferred by the user config */ + +/* Video mode */ +typedef struct _DisplayModeRec { + struct _DisplayModeRec * prev; + struct _DisplayModeRec * next; + char * name; /* identifier for the mode */ + ModeStatus status; + int type; + + /* These are the values that the user sees/provides */ + int Clock; /* pixel clock freq (kHz) */ + int HDisplay; /* horizontal timing */ + int HSyncStart; + int HSyncEnd; + int HTotal; + int HSkew; + int VDisplay; /* vertical timing */ + int VSyncStart; + int VSyncEnd; + int VTotal; + int VScan; + int Flags; + + /* These are the values the hardware uses */ + int ClockIndex; + int SynthClock; /* Actual clock freq to + * be programmed (kHz) */ + int CrtcHDisplay; + int CrtcHBlankStart; + int CrtcHSyncStart; + int CrtcHSyncEnd; + int CrtcHBlankEnd; + int CrtcHTotal; + int CrtcHSkew; + int CrtcVDisplay; + int CrtcVBlankStart; + int CrtcVSyncStart; + int CrtcVSyncEnd; + int CrtcVBlankEnd; + int CrtcVTotal; + Bool CrtcHAdjusted; + Bool CrtcVAdjusted; + int PrivSize; + INT32 * Private; + int PrivFlags; + + float HSync, VRefresh; +} DisplayModeRec, *DisplayModePtr; + +/* The monitor description */ + +#define MAX_HSYNC 8 +#define MAX_VREFRESH 8 + +typedef struct { float hi, lo; } range; + +typedef struct { CARD32 red, green, blue; } rgb; + +typedef struct { float red, green, blue; } Gamma; + +/* The permitted gamma range is 1 / GAMMA_MAX <= g <= GAMMA_MAX */ +#define GAMMA_MAX 10.0 +#define GAMMA_MIN (1.0 / GAMMA_MAX) +#define GAMMA_ZERO (GAMMA_MIN / 100.0) + +typedef struct { + char * id; + char * vendor; + char * model; + int nHsync; + range hsync[MAX_HSYNC]; + int nVrefresh; + range vrefresh[MAX_VREFRESH]; + DisplayModePtr Modes; /* Start of the monitor's mode list */ + DisplayModePtr Last; /* End of the monitor's mode list */ + Gamma gamma; /* Gamma of the monitor */ + int widthmm; + int heightmm; + pointer options; + pointer DDC; + Bool reducedblanking; /* Allow CVT reduced blanking modes? */ + int maxPixClock; /* in kHz, like mode->Clock */ +} MonRec, *MonPtr; + +/* the list of clock ranges */ +typedef struct x_ClockRange { + struct x_ClockRange *next; + int minClock; /* (kHz) */ + int maxClock; /* (kHz) */ + int clockIndex; /* -1 for programmable clocks */ + Bool interlaceAllowed; + Bool doubleScanAllowed; + int ClockMulFactor; + int ClockDivFactor; + int PrivFlags; +} ClockRange, *ClockRangePtr; + +/* + * The driverFunc. xorgDriverFuncOp specifies the action driver should + * perform. If requested option is not supported function should return + * FALSE. pointer can be used to pass arguments to the function or + * to return data to the caller. + */ +typedef struct _ScrnInfoRec *ScrnInfoPtr; + +/* do not change order */ +typedef enum { + RR_GET_INFO, + RR_SET_CONFIG, + RR_GET_MODE_MM, + GET_REQUIRED_HW_INTERFACES = 10 +} xorgDriverFuncOp; + +typedef Bool xorgDriverFuncProc (ScrnInfoPtr, xorgDriverFuncOp, + pointer); + +/* RR_GET_INFO, RR_SET_CONFIG */ +typedef struct { + int rotation; + int rate; + int width; + int height; +} xorgRRConfig; + +typedef union { + short RRRotations; + xorgRRConfig RRConfig; +} xorgRRRotation, *xorgRRRotationPtr; + +/* RR_GET_MODE_MM */ +typedef struct { + DisplayModePtr mode; + int virtX; + int virtY; + int mmWidth; + int mmHeight; +} xorgRRModeMM, *xorgRRModeMMPtr; + +/* GET_REQUIRED_HW_INTERFACES */ +#define HW_IO 1 +#define HW_MMIO 2 +#define HW_SKIP_CONSOLE 4 +#define NEED_IO_ENABLED(x) (x & HW_IO) + +typedef CARD32 xorgHWFlags; + +/* + * The driver list struct. This contains the information required for each + * driver before a ScrnInfoRec has been allocated. + */ +struct _DriverRec; + +typedef struct { + int driverVersion; + char * driverName; + void (*Identify)(int flags); + Bool (*Probe)(struct _DriverRec *drv, int flags); + const OptionInfoRec * (*AvailableOptions)(int chipid, int bustype); + pointer module; + int refCount; +} DriverRec1; + +struct _SymTabRec; +struct _PciChipsets; + +typedef struct _DriverRec { + int driverVersion; + char * driverName; + void (*Identify)(int flags); + Bool (*Probe)(struct _DriverRec *drv, int flags); + const OptionInfoRec * (*AvailableOptions)(int chipid, int bustype); + pointer module; + int refCount; + xorgDriverFuncProc *driverFunc; + + const struct pci_id_match * supported_devices; + Bool (*PciProbe)( struct _DriverRec * drv, int entity_num, + struct pci_device * dev, intptr_t match_data ); +} DriverRec, *DriverPtr; + +/* + * AddDriver flags + */ +#define HaveDriverFuncs 1 + +/* + * These are the private bus types. New types can be added here. Types + * required for the public interface should be added to xf86str.h, with + * function prototypes added to xf86.h. + */ + +/* Tolerate prior #include <linux/input.h> */ +#if defined(linux) && defined(_INPUT_H) +#undef BUS_NONE +#undef BUS_PCI +#undef BUS_SBUS +#undef BUS_last +#endif + +typedef enum { + BUS_NONE, + BUS_PCI, + BUS_SBUS, + BUS_last /* Keep last */ +} BusType; + +struct pci_device; + +typedef struct { + int fbNum; +} SbusBusId; + +typedef struct _bus { + BusType type; + union { + struct pci_device *pci; + SbusBusId sbus; + } id; +} BusRec, *BusPtr; + +#define MAXCLOCKS 128 +typedef enum { + DAC_BPP8 = 0, + DAC_BPP16, + DAC_BPP24, + DAC_BPP32, + MAXDACSPEEDS +} DacSpeedIndex; + +typedef struct { + char * identifier; + char * vendor; + char * board; + char * chipset; + char * ramdac; + char * driver; + struct _confscreenrec * myScreenSection; + Bool claimed; + int dacSpeeds[MAXDACSPEEDS]; + int numclocks; + int clock[MAXCLOCKS]; + char * clockchip; + char * busID; + Bool active; + Bool inUse; + int videoRam; + int textClockFreq; + unsigned long BiosBase; /* Base address of video BIOS */ + unsigned long MemBase; /* Frame buffer base address */ + unsigned long IOBase; + int chipID; + int chipRev; + pointer options; + int irq; + int screen; /* For multi-CRTC cards */ +} GDevRec, *GDevPtr; + +typedef struct { + int frameX0; + int frameY0; + int virtualX; + int virtualY; + int depth; + int fbbpp; + rgb weight; + rgb blackColour; + rgb whiteColour; + int defaultVisual; + char ** modes; + pointer options; +} DispRec, *DispPtr; + +typedef struct _confxvportrec { + char * identifier; + pointer options; +} confXvPortRec, *confXvPortPtr; + +typedef struct _confxvadaptrec { + char * identifier; + int numports; + confXvPortPtr ports; + pointer options; +} confXvAdaptorRec, *confXvAdaptorPtr; + +typedef struct _confscreenrec { + char * id; + int screennum; + int defaultdepth; + int defaultbpp; + int defaultfbbpp; + MonPtr monitor; + GDevPtr device; + int numdisplays; + DispPtr displays; + int numxvadaptors; + confXvAdaptorPtr xvadaptors; + pointer options; +} confScreenRec, *confScreenPtr; + +typedef enum { + PosObsolete = -1, + PosAbsolute = 0, + PosRightOf, + PosLeftOf, + PosAbove, + PosBelow, + PosRelative +} PositionType; + +typedef struct _screenlayoutrec { + confScreenPtr screen; + char * topname; + confScreenPtr top; + char * bottomname; + confScreenPtr bottom; + char * leftname; + confScreenPtr left; + char * rightname; + confScreenPtr right; + PositionType where; + int x; + int y; + char * refname; + confScreenPtr refscreen; +} screenLayoutRec, *screenLayoutPtr; + +typedef struct _InputInfoRec InputInfoRec; + +typedef struct _serverlayoutrec { + char * id; + screenLayoutPtr screens; + GDevPtr inactives; + InputInfoRec** inputs; /* NULL terminated */ + pointer options; +} serverLayoutRec, *serverLayoutPtr; + +typedef struct _confdribufferrec { + int count; + int size; + enum { + XF86DRI_WC_HINT = 0x0001 /* Placeholder: not implemented */ + } flags; +} confDRIBufferRec, *confDRIBufferPtr; + +typedef struct _confdrirec { + int group; + int mode; + int bufs_count; + confDRIBufferRec *bufs; +} confDRIRec, *confDRIPtr; + +/* These values should be adjusted when new fields are added to ScrnInfoRec */ +#define NUM_RESERVED_INTS 16 +#define NUM_RESERVED_POINTERS 14 +#define NUM_RESERVED_FUNCS 10 + +typedef pointer (*funcPointer)(void); + +/* flags for depth 24 pixmap options */ +typedef enum { + Pix24DontCare = 0, + Pix24Use24, + Pix24Use32 +} Pix24Flags; + +/* Power management events: so far we only support APM */ + +typedef enum { + XF86_APM_UNKNOWN = -1, + XF86_APM_SYS_STANDBY, + XF86_APM_SYS_SUSPEND, + XF86_APM_CRITICAL_SUSPEND, + XF86_APM_USER_STANDBY, + XF86_APM_USER_SUSPEND, + XF86_APM_STANDBY_RESUME, + XF86_APM_NORMAL_RESUME, + XF86_APM_CRITICAL_RESUME, + XF86_APM_LOW_BATTERY, + XF86_APM_POWER_STATUS_CHANGE, + XF86_APM_UPDATE_TIME, + XF86_APM_CAPABILITY_CHANGED, + XF86_APM_STANDBY_FAILED, + XF86_APM_SUSPEND_FAILED +} pmEvent; + +typedef enum { + PM_WAIT, + PM_CONTINUE, + PM_FAILED, + PM_NONE +} pmWait; + +typedef struct _PciChipsets { + /** + * Key used to match this device with its name in an array of + * \c SymTabRec. + */ + int numChipset; + + /** + * This value is quirky. Depending on the driver, it can take on one of + * three meanings. In drivers that have exactly one vendor ID (e.g., + * radeon, mga, i810) the low 16-bits are the device ID. + * + * In drivers that can have multiple vendor IDs (e.g., the glint driver + * can have either 3dlabs' ID or TI's ID, the i740 driver can have either + * Intel's ID or Real3D's ID, etc.) the low 16-bits are the device ID and + * the high 16-bits are the vendor ID. + * + * In drivers that don't have a specific vendor (e.g., vga) contains the + * device ID for either the generic VGA or generic 8514 devices. This + * turns out to be the same as the subclass and programming interface + * value (e.g., the full 24-bit class for the VGA device is 0x030000 (or + * 0x000101) and for 8514 is 0x030001). + */ + int PCIid; + +/* dummy place holders for drivers to build against old/new servers */ +#define RES_UNDEFINED NULL +#define RES_EXCLUSIVE_VGA NULL +#define RES_SHARED_VGA NULL + void *dummy; +} PciChipsets; + + +/* Entity properties */ +typedef void (*EntityProc)(int entityIndex,pointer private); + +typedef struct _entityInfo { + int index; + BusRec location; + int chipset; + Bool active; + GDevPtr device; + DriverPtr driver; +} EntityInfoRec, *EntityInfoPtr; + +/* DGA */ + +typedef struct { + int num; /* A unique identifier for the mode (num > 0) */ + DisplayModePtr mode; + int flags; /* DGA_CONCURRENT_ACCESS, etc... */ + int imageWidth; /* linear accessible portion (pixels) */ + int imageHeight; + int pixmapWidth; /* Xlib accessible portion (pixels) */ + int pixmapHeight; /* both fields ignored if no concurrent access */ + int bytesPerScanline; + int byteOrder; /* MSBFirst, LSBFirst */ + int depth; + int bitsPerPixel; + unsigned long red_mask; + unsigned long green_mask; + unsigned long blue_mask; + short visualClass; + int viewportWidth; + int viewportHeight; + int xViewportStep; /* viewport position granularity */ + int yViewportStep; + int maxViewportX; /* max viewport origin */ + int maxViewportY; + int viewportFlags; /* types of page flipping possible */ + int offset; /* offset into physical memory */ + unsigned char *address; /* server's mapped framebuffer */ + int reserved1; + int reserved2; +} DGAModeRec, *DGAModePtr; + +typedef struct { + DGAModePtr mode; + PixmapPtr pPix; +} DGADeviceRec, *DGADevicePtr; + +/* + * Flags for driver Probe() functions. + */ +#define PROBE_DEFAULT 0x00 +#define PROBE_DETECT 0x01 +#define PROBE_TRYHARD 0x02 + +/* + * Driver entry point types + */ + +typedef Bool xf86ProbeProc (DriverPtr, int); +typedef Bool xf86PreInitProc (ScrnInfoPtr, int); +typedef Bool xf86ScreenInitProc (int, ScreenPtr, int, char**); +typedef Bool xf86SwitchModeProc (int, DisplayModePtr, int); +typedef void xf86AdjustFrameProc (int, int, int, int); +typedef Bool xf86EnterVTProc (int, int); +typedef void xf86LeaveVTProc (int, int); +typedef void xf86FreeScreenProc (int, int); +typedef ModeStatus xf86ValidModeProc (int, DisplayModePtr, Bool, int); +typedef void xf86EnableDisableFBAccessProc(int, Bool); +typedef int xf86SetDGAModeProc (int, int, DGADevicePtr); +typedef int xf86ChangeGammaProc (int, Gamma); +typedef void xf86PointerMovedProc (int, int, int); +typedef Bool xf86PMEventProc (int, pmEvent, Bool); +typedef void xf86DPMSSetProc (ScrnInfoPtr, int, int); +typedef void xf86LoadPaletteProc (ScrnInfoPtr, int, int *, LOCO *, VisualPtr); +typedef void xf86SetOverscanProc (ScrnInfoPtr, int); +typedef void xf86ModeSetProc (ScrnInfoPtr); + + +/* + * ScrnInfoRec + * + * There is one of these for each screen, and it holds all the screen-specific + * information. + * + * Note: the size and layout must be kept the same across versions. New + * fields are to be added in place of the "reserved*" fields. No fields + * are to be dependent on compile-time defines. + */ + + +typedef struct _ScrnInfoRec { + int driverVersion; + char * driverName; /* canonical name used in */ + /* the config file */ + ScreenPtr pScreen; /* Pointer to the ScreenRec */ + int scrnIndex; /* Number of this screen */ + Bool configured; /* Is this screen valid */ + int origIndex; /* initial number assigned to + * this screen before + * finalising the number of + * available screens */ + + /* Display-wide screenInfo values needed by this screen */ + int imageByteOrder; + int bitmapScanlineUnit; + int bitmapScanlinePad; + int bitmapBitOrder; + int numFormats; + PixmapFormatRec formats[MAXFORMATS]; + PixmapFormatRec fbFormat; + + int bitsPerPixel; /* fb bpp */ + Pix24Flags pixmap24; /* pixmap pref for depth 24 */ + int depth; /* depth of default visual */ + MessageType depthFrom; /* set from config? */ + MessageType bitsPerPixelFrom; /* set from config? */ + rgb weight; /* r/g/b weights */ + rgb mask; /* rgb masks */ + rgb offset; /* rgb offsets */ + int rgbBits; /* Number of bits in r/g/b */ + Gamma gamma; /* Gamma of the monitor */ + int defaultVisual; /* default visual class */ + int maxHValue; /* max horizontal timing */ + int maxVValue; /* max vertical timing value */ + int virtualX; /* Virtual width */ + int virtualY; /* Virtual height */ + int xInc; /* Horizontal timing increment */ + MessageType virtualFrom; /* set from config? */ + int displayWidth; /* memory pitch */ + int frameX0; /* viewport position */ + int frameY0; + int frameX1; + int frameY1; + int zoomLocked; /* Disallow mode changes */ + DisplayModePtr modePool; /* list of compatible modes */ + DisplayModePtr modes; /* list of actual modes */ + DisplayModePtr currentMode; /* current mode + * This was previously + * overloaded with the modes + * field, which is a pointer + * into a circular list */ + confScreenPtr confScreen; /* Screen config info */ + MonPtr monitor; /* Monitor information */ + DispPtr display; /* Display information */ + int * entityList; /* List of device entities */ + int numEntities; + int widthmm; /* physical display dimensions + * in mm */ + int heightmm; + int xDpi; /* width DPI */ + int yDpi; /* height DPI */ + char * name; /* Name to prefix messages */ + pointer driverPrivate; /* Driver private area */ + DevUnion * privates; /* Other privates can hook in + * here */ + DriverPtr drv; /* xf86DriverList[] entry */ + pointer module; /* Pointer to module head */ + int colorKey; + int overlayFlags; + + /* Some of these may be moved out of here into the driver private area */ + + char * chipset; /* chipset name */ + char * ramdac; /* ramdac name */ + char * clockchip; /* clock name */ + Bool progClock; /* clock is programmable */ + int numClocks; /* number of clocks */ + int clock[MAXCLOCKS]; /* list of clock frequencies */ + int videoRam; /* amount of video ram (kb) */ + unsigned long biosBase; /* Base address of video BIOS */ + unsigned long memPhysBase; /* Physical address of FB */ + unsigned long fbOffset; /* Offset of FB in the above */ + IOADDRESS domainIOBase; /* Domain I/O base address */ + int memClk; /* memory clock */ + int textClockFreq; /* clock of text mode */ + Bool flipPixels; /* swap default black/white */ + pointer options; + + int chipID; + int chipRev; + + /* Allow screens to be enabled/disabled individually */ + Bool vtSema; + + /* hw cursor moves at SIGIO time */ + Bool silkenMouse; + + /* Storage for clockRanges and adjustFlags for use with the VidMode ext */ + ClockRangePtr clockRanges; + int adjustFlags; + + /* + * These can be used when the minor ABI version is incremented. + * The NUM_* parameters must be reduced appropriately to keep the + * structure size and alignment unchanged. + */ + int reservedInt[NUM_RESERVED_INTS]; + + int * entityInstanceList; + struct pci_device *vgaDev; + + pointer reservedPtr[NUM_RESERVED_POINTERS]; + + /* + * Driver entry points. + * + */ + + xf86ProbeProc *Probe; + xf86PreInitProc *PreInit; + xf86ScreenInitProc *ScreenInit; + xf86SwitchModeProc *SwitchMode; + xf86AdjustFrameProc *AdjustFrame; + xf86EnterVTProc *EnterVT; + xf86LeaveVTProc *LeaveVT; + xf86FreeScreenProc *FreeScreen; + xf86ValidModeProc *ValidMode; + xf86EnableDisableFBAccessProc *EnableDisableFBAccess; + xf86SetDGAModeProc *SetDGAMode; + xf86ChangeGammaProc *ChangeGamma; + xf86PointerMovedProc *PointerMoved; + xf86PMEventProc *PMEvent; + xf86DPMSSetProc *DPMSSet; + xf86LoadPaletteProc *LoadPalette; + xf86SetOverscanProc *SetOverscan; + xorgDriverFuncProc *DriverFunc; + xf86ModeSetProc *ModeSet; + + /* + * This can be used when the minor ABI version is incremented. + * The NUM_* parameter must be reduced appropriately to keep the + * structure size and alignment unchanged. + */ + funcPointer reservedFuncs[NUM_RESERVED_FUNCS]; + +} ScrnInfoRec; + + +typedef struct { + Bool (*OpenFramebuffer)( + ScrnInfoPtr pScrn, + char **name, + unsigned char **mem, + int *size, + int *offset, + int *extra + ); + void (*CloseFramebuffer)(ScrnInfoPtr pScrn); + Bool (*SetMode)(ScrnInfoPtr pScrn, DGAModePtr pMode); + void (*SetViewport)(ScrnInfoPtr pScrn, int x, int y, int flags); + int (*GetViewport)(ScrnInfoPtr pScrn); + void (*Sync)(ScrnInfoPtr); + void (*FillRect)( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned long color + ); + void (*BlitRect)( + ScrnInfoPtr pScrn, + int srcx, int srcy, + int w, int h, + int dstx, int dsty + ); + void (*BlitTransRect)( + ScrnInfoPtr pScrn, + int srcx, int srcy, + int w, int h, + int dstx, int dsty, + unsigned long color + ); +} DGAFunctionRec, *DGAFunctionPtr; + +typedef struct _SymTabRec { + int token; /* id of the token */ + const char * name; /* token name */ +} SymTabRec, *SymTabPtr; + +/* flags for xf86LookupMode */ +typedef enum { + LOOKUP_DEFAULT = 0, /* Use default mode lookup method */ + LOOKUP_BEST_REFRESH, /* Pick modes with best refresh */ + LOOKUP_CLOSEST_CLOCK, /* Pick modes with the closest clock */ + LOOKUP_LIST_ORDER, /* Pick first useful mode in list */ + LOOKUP_CLKDIV2 = 0x0100, /* Allow half clocks */ + LOOKUP_OPTIONAL_TOLERANCES = 0x0200 /* Allow missing hsync/vrefresh */ +} LookupModeFlags; + +#define NoDepth24Support 0x00 +#define Support24bppFb 0x01 /* 24bpp framebuffer supported */ +#define Support32bppFb 0x02 /* 32bpp framebuffer supported */ +#define SupportConvert24to32 0x04 /* Can convert 24bpp pixmap to 32bpp */ +#define SupportConvert32to24 0x08 /* Can convert 32bpp pixmap to 24bpp */ +#define PreferConvert24to32 0x10 /* prefer 24bpp pixmap to 32bpp conv */ +#define PreferConvert32to24 0x20 /* prefer 32bpp pixmap to 24bpp conv */ + + +/* For DPMS */ +typedef void (*DPMSSetProcPtr)(ScrnInfoPtr, int, int); + +/* Input handler proc */ +typedef void (*InputHandlerProc)(int fd, pointer data); + +/* These are used by xf86GetClocks */ +#define CLK_REG_SAVE -1 +#define CLK_REG_RESTORE -2 + +/* + * misc constants + */ +#define INTERLACE_REFRESH_WEIGHT 1.5 +#define SYNC_TOLERANCE 0.01 /* 1 percent */ +#define CLOCK_TOLERANCE 2000 /* Clock matching tolerance (2MHz) */ + + +#define OVERLAY_8_32_DUALFB 0x00000001 +#define OVERLAY_8_24_DUALFB 0x00000002 +#define OVERLAY_8_16_DUALFB 0x00000004 +#define OVERLAY_8_32_PLANAR 0x00000008 + +/* Values of xf86Info.mouseFlags */ +#define MF_CLEAR_DTR 1 +#define MF_CLEAR_RTS 2 + +/* Action Events */ +typedef enum { + ACTION_TERMINATE = 0, /* Terminate Server */ + ACTION_NEXT_MODE = 10, /* Switch to next video mode */ + ACTION_PREV_MODE, + ACTION_SWITCHSCREEN = 100, /* VT switch */ + ACTION_SWITCHSCREEN_NEXT, + ACTION_SWITCHSCREEN_PREV, +} ActionEvent; + +#endif /* _XF86STR_H */ diff --git a/hw/xfree86/common/xf86xv.c b/hw/xfree86/common/xf86xv.c new file mode 100644 index 0000000..53ebe8f --- /dev/null +++ b/hw/xfree86/common/xf86xv.c @@ -0,0 +1,2183 @@ +/* + * XFree86 Xv DDX written by Mark Vojkovich (markv@valinux.com) + */ +/* + * Copyright (c) 1998-2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "scrnintstr.h" +#include "regionstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "mivalidate.h" +#include "validate.h" +#include "resource.h" +#include "gcstruct.h" +#include "dixstruct.h" + +#include <X11/extensions/Xv.h> +#include <X11/extensions/Xvproto.h> +#include "xvdix.h" +#include "xvmodproc.h" + +#include "xf86xvpriv.h" + + +/* XvScreenRec fields */ + +static Bool xf86XVCloseScreen(int, ScreenPtr); +static int xf86XVQueryAdaptors(ScreenPtr, XvAdaptorPtr *, int *); + +/* XvAdaptorRec fields */ + +static int xf86XVAllocatePort(unsigned long, XvPortPtr, XvPortPtr*); +static int xf86XVFreePort(XvPortPtr); +static int xf86XVPutVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); +static int xf86XVPutStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); +static int xf86XVGetVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); +static int xf86XVGetStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); +static int xf86XVStopVideo(ClientPtr, XvPortPtr, DrawablePtr); +static int xf86XVSetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32); +static int xf86XVGetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32*); +static int xf86XVQueryBestSize(ClientPtr, XvPortPtr, CARD8, + CARD16, CARD16,CARD16, CARD16, + unsigned int*, unsigned int*); +static int xf86XVPutImage(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16, + XvImagePtr, unsigned char*, Bool, + CARD16, CARD16); +static int xf86XVQueryImageAttributes(ClientPtr, XvPortPtr, XvImagePtr, + CARD16*, CARD16*, int*, int*); + + +/* ScreenRec fields */ + +static Bool xf86XVDestroyWindow(WindowPtr pWin); +static void xf86XVWindowExposures(WindowPtr pWin, RegionPtr r1, RegionPtr r2); +static void xf86XVPostValidateTree(WindowPtr pWin, WindowPtr pLayerWin, VTKind kind); +static void xf86XVClipNotify(WindowPtr pWin, int dx, int dy); + +#define PostValidateTreeUndefined ((PostValidateTreeProcPtr)-1) + +/* ScrnInfoRec functions */ + +static Bool xf86XVEnterVT(int, int); +static void xf86XVLeaveVT(int, int); +static void xf86XVAdjustFrame(int index, int x, int y, int flags); +static void xf86XVModeSet(ScrnInfoPtr pScrn); + +/* misc */ + +static Bool xf86XVInitAdaptors(ScreenPtr, XF86VideoAdaptorPtr*, int); + + +static DevPrivateKeyRec XF86XVWindowKeyRec; +#define XF86XVWindowKey (&XF86XVWindowKeyRec) + +DevPrivateKey XF86XvScreenKey; + +static unsigned long PortResource = 0; + +DevPrivateKey (*XvGetScreenKeyProc)(void) = NULL; +unsigned long (*XvGetRTPortProc)(void) = NULL; +int (*XvScreenInitProc)(ScreenPtr) = NULL; + +#define GET_XV_SCREEN(pScreen) \ + ((XvScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, XF86XvScreenKey)) + +#define GET_XF86XV_SCREEN(pScreen) \ + ((XF86XVScreenPtr)(GET_XV_SCREEN(pScreen)->devPriv.ptr)) + +#define GET_XF86XV_WINDOW(pWin) \ + ((XF86XVWindowPtr)dixLookupPrivate(&(pWin)->devPrivates, XF86XVWindowKey)) + +static xf86XVInitGenericAdaptorPtr *GenDrivers = NULL; +static int NumGenDrivers = 0; + +int +xf86XVRegisterGenericAdaptorDriver( + xf86XVInitGenericAdaptorPtr InitFunc +){ + xf86XVInitGenericAdaptorPtr *newdrivers; + + newdrivers = realloc(GenDrivers, sizeof(xf86XVInitGenericAdaptorPtr) * + (1 + NumGenDrivers)); + if (!newdrivers) + return 0; + GenDrivers = newdrivers; + + GenDrivers[NumGenDrivers++] = InitFunc; + + return 1; +} + +int +xf86XVListGenericAdaptors( + ScrnInfoPtr pScrn, + XF86VideoAdaptorPtr **adaptors +){ + int i,j,n,num; + XF86VideoAdaptorPtr *DrivAdap,*new; + + num = 0; + *adaptors = NULL; + /* + * The v4l driver registers itself first, but can use surfaces registered + * by other drivers. So, call the v4l driver last. + */ + for (i = NumGenDrivers; --i >= 0; ) { + DrivAdap = NULL; + n = (*GenDrivers[i])(pScrn, &DrivAdap); + if (0 == n) + continue; + new = realloc(*adaptors, sizeof(XF86VideoAdaptorPtr) * (num+n)); + if (NULL == new) + continue; + *adaptors = new; + for (j = 0; j < n; j++, num++) + (*adaptors)[num] = DrivAdap[j]; + } + return num; +} + + +/**************** Offscreen surface stuff *******************/ + +typedef struct { + XF86OffscreenImagePtr images; + int num; +} OffscreenImageRec; + +static DevPrivateKeyRec OffscreenPrivateKeyRec; +#define OffscreenPrivateKey (&OffscreenPrivateKeyRec) +#define GetOffscreenImage(pScreen) ((OffscreenImageRec *) dixLookupPrivate(&(pScreen)->devPrivates, OffscreenPrivateKey)) + +Bool +xf86XVRegisterOffscreenImages( + ScreenPtr pScreen, + XF86OffscreenImagePtr images, + int num +){ + OffscreenImageRec *OffscreenImage; + /* This function may be called before xf86XVScreenInit, so there's + * no better place than this to call dixRegisterPrivateKey to ensure we + * have space reserved. After the first call it is a no-op. */ + if(!dixRegisterPrivateKey(OffscreenPrivateKey, PRIVATE_SCREEN, sizeof(OffscreenImageRec)) || + !(OffscreenImage = GetOffscreenImage(pScreen))) + /* Every X.org driver assumes this function always succeeds, so + * just die on allocation failure. */ + FatalError("Could not allocate private storage for XV offscreen images.\n"); + + OffscreenImage->num = num; + OffscreenImage->images = images; + return TRUE; +} + +XF86OffscreenImagePtr +xf86XVQueryOffscreenImages( + ScreenPtr pScreen, + int *num +){ + OffscreenImageRec *OffscreenImage = GetOffscreenImage(pScreen); + *num = OffscreenImage->num; + return OffscreenImage->images; +} + + +XF86VideoAdaptorPtr +xf86XVAllocateVideoAdaptorRec(ScrnInfoPtr pScrn) +{ + return calloc(1, sizeof(XF86VideoAdaptorRec)); +} + +void +xf86XVFreeVideoAdaptorRec(XF86VideoAdaptorPtr ptr) +{ + free(ptr); +} + + +Bool +xf86XVScreenInit( + ScreenPtr pScreen, + XF86VideoAdaptorPtr *adaptors, + int num +){ + ScrnInfoPtr pScrn; + XF86XVScreenPtr ScreenPriv; + XvScreenPtr pxvs; + + if(num <= 0 || + !XvGetScreenKeyProc || !XvGetRTPortProc || !XvScreenInitProc) + return FALSE; + + if(Success != (*XvScreenInitProc)(pScreen)) return FALSE; + + if (!dixRegisterPrivateKey(&XF86XVWindowKeyRec, PRIVATE_WINDOW, 0)) + return FALSE; + + XF86XvScreenKey = (*XvGetScreenKeyProc)(); + + PortResource = (*XvGetRTPortProc)(); + + pxvs = GET_XV_SCREEN(pScreen); + + /* Anyone initializing the Xv layer must provide these two. + The Xv di layer calls them without even checking if they exist! */ + + pxvs->ddCloseScreen = xf86XVCloseScreen; + pxvs->ddQueryAdaptors = xf86XVQueryAdaptors; + + /* The Xv di layer provides us with a private hook so that we don't + have to allocate our own screen private. They also provide + a CloseScreen hook so that we don't have to wrap it. I'm not + sure that I appreciate that. */ + + ScreenPriv = malloc(sizeof(XF86XVScreenRec)); + pxvs->devPriv.ptr = (pointer)ScreenPriv; + + if(!ScreenPriv) return FALSE; + + pScrn = xf86Screens[pScreen->myNum]; + + ScreenPriv->DestroyWindow = pScreen->DestroyWindow; + ScreenPriv->WindowExposures = pScreen->WindowExposures; + ScreenPriv->PostValidateTree = PostValidateTreeUndefined; + ScreenPriv->ClipNotify = pScreen->ClipNotify; + ScreenPriv->EnterVT = pScrn->EnterVT; + ScreenPriv->LeaveVT = pScrn->LeaveVT; + ScreenPriv->AdjustFrame = pScrn->AdjustFrame; + ScreenPriv->ModeSet = pScrn->ModeSet; + + pScreen->DestroyWindow = xf86XVDestroyWindow; + pScreen->WindowExposures = xf86XVWindowExposures; + pScreen->ClipNotify = xf86XVClipNotify; + pScrn->EnterVT = xf86XVEnterVT; + pScrn->LeaveVT = xf86XVLeaveVT; + if(pScrn->AdjustFrame) + pScrn->AdjustFrame = xf86XVAdjustFrame; + pScrn->ModeSet = xf86XVModeSet; + + if(!xf86XVInitAdaptors(pScreen, adaptors, num)) + return FALSE; + + return TRUE; +} + +static void +xf86XVFreeAdaptor(XvAdaptorPtr pAdaptor) +{ + int i; + + free(pAdaptor->name); + + if(pAdaptor->pEncodings) { + XvEncodingPtr pEncode = pAdaptor->pEncodings; + + for(i = 0; i < pAdaptor->nEncodings; i++, pEncode++) + free(pEncode->name); + free(pAdaptor->pEncodings); + } + + free(pAdaptor->pFormats); + + if(pAdaptor->pPorts) { + XvPortPtr pPort = pAdaptor->pPorts; + XvPortRecPrivatePtr pPriv; + + for(i = 0; i < pAdaptor->nPorts; i++, pPort++) { + pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr; + if(pPriv) { + if(pPriv->clientClip) + RegionDestroy(pPriv->clientClip); + if(pPriv->pCompositeClip && pPriv->FreeCompositeClip) + RegionDestroy(pPriv->pCompositeClip); + if (pPriv->ckeyFilled) + RegionDestroy(pPriv->ckeyFilled); + free(pPriv); + } + } + free(pAdaptor->pPorts); + } + + if(pAdaptor->nAttributes) { + XvAttributePtr pAttribute = pAdaptor->pAttributes; + + for(i = 0; i < pAdaptor->nAttributes; i++, pAttribute++) + free(pAttribute->name); + free(pAdaptor->pAttributes); + } + + free(pAdaptor->pImages); + free(pAdaptor->devPriv.ptr); +} + +static Bool +xf86XVInitAdaptors( + ScreenPtr pScreen, + XF86VideoAdaptorPtr *infoPtr, + int number +) { + XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + XF86VideoAdaptorPtr adaptorPtr; + XvAdaptorPtr pAdaptor, pa; + XvAdaptorRecPrivatePtr adaptorPriv; + int na, numAdaptor; + XvPortRecPrivatePtr portPriv; + XvPortPtr pPort, pp; + int numPort; + XF86AttributePtr attributePtr; + XvAttributePtr pAttribute, pat; + XF86VideoFormatPtr formatPtr; + XvFormatPtr pFormat, pf; + int numFormat, totFormat; + XF86VideoEncodingPtr encodingPtr; + XvEncodingPtr pEncode, pe; + XF86ImagePtr imagePtr; + XvImagePtr pImage, pi; + int numVisuals; + VisualPtr pVisual; + int i; + + pxvs->nAdaptors = 0; + pxvs->pAdaptors = NULL; + + if(!(pAdaptor = calloc(number, sizeof(XvAdaptorRec)))) + return FALSE; + + for(pa = pAdaptor, na = 0, numAdaptor = 0; na < number; na++, adaptorPtr++) { + adaptorPtr = infoPtr[na]; + + if(!adaptorPtr->StopVideo || !adaptorPtr->SetPortAttribute || + !adaptorPtr->GetPortAttribute || !adaptorPtr->QueryBestSize) + continue; + + /* client libs expect at least one encoding */ + if(!adaptorPtr->nEncodings || !adaptorPtr->pEncodings) + continue; + + pa->type = adaptorPtr->type; + + if(!adaptorPtr->PutVideo && !adaptorPtr->GetVideo) + pa->type &= ~XvVideoMask; + + if(!adaptorPtr->PutStill && !adaptorPtr->GetStill) + pa->type &= ~XvStillMask; + + if(!adaptorPtr->PutImage || !adaptorPtr->QueryImageAttributes) + pa->type &= ~XvImageMask; + + if(!adaptorPtr->PutVideo && !adaptorPtr->PutImage && + !adaptorPtr->PutStill) + pa->type &= ~XvInputMask; + + if(!adaptorPtr->GetVideo && !adaptorPtr->GetStill) + pa->type &= ~XvOutputMask; + + if(!(adaptorPtr->type & (XvPixmapMask | XvWindowMask))) + continue; + if(!(adaptorPtr->type & (XvImageMask | XvVideoMask | XvStillMask))) + continue; + + pa->pScreen = pScreen; + pa->ddAllocatePort = xf86XVAllocatePort; + pa->ddFreePort = xf86XVFreePort; + pa->ddPutVideo = xf86XVPutVideo; + pa->ddPutStill = xf86XVPutStill; + pa->ddGetVideo = xf86XVGetVideo; + pa->ddGetStill = xf86XVGetStill; + pa->ddStopVideo = xf86XVStopVideo; + pa->ddPutImage = xf86XVPutImage; + pa->ddSetPortAttribute = xf86XVSetPortAttribute; + pa->ddGetPortAttribute = xf86XVGetPortAttribute; + pa->ddQueryBestSize = xf86XVQueryBestSize; + pa->ddQueryImageAttributes = xf86XVQueryImageAttributes; + pa->name = strdup(adaptorPtr->name); + + if(adaptorPtr->nEncodings && + (pEncode = calloc(adaptorPtr->nEncodings, sizeof(XvEncodingRec)))) { + + for(pe = pEncode, encodingPtr = adaptorPtr->pEncodings, i = 0; + i < adaptorPtr->nEncodings; pe++, i++, encodingPtr++) + { + pe->id = encodingPtr->id; + pe->pScreen = pScreen; + pe->name = strdup(encodingPtr->name); + pe->width = encodingPtr->width; + pe->height = encodingPtr->height; + pe->rate.numerator = encodingPtr->rate.numerator; + pe->rate.denominator = encodingPtr->rate.denominator; + } + pa->nEncodings = adaptorPtr->nEncodings; + pa->pEncodings = pEncode; + } + + if(adaptorPtr->nImages && + (pImage = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) { + + for(i = 0, pi = pImage, imagePtr = adaptorPtr->pImages; + i < adaptorPtr->nImages; i++, pi++, imagePtr++) + { + pi->id = imagePtr->id; + pi->type = imagePtr->type; + pi->byte_order = imagePtr->byte_order; + memcpy(pi->guid, imagePtr->guid, 16); + pi->bits_per_pixel = imagePtr->bits_per_pixel; + pi->format = imagePtr->format; + pi->num_planes = imagePtr->num_planes; + pi->depth = imagePtr->depth; + pi->red_mask = imagePtr->red_mask; + pi->green_mask = imagePtr->green_mask; + pi->blue_mask = imagePtr->blue_mask; + pi->y_sample_bits = imagePtr->y_sample_bits; + pi->u_sample_bits = imagePtr->u_sample_bits; + pi->v_sample_bits = imagePtr->v_sample_bits; + pi->horz_y_period = imagePtr->horz_y_period; + pi->horz_u_period = imagePtr->horz_u_period; + pi->horz_v_period = imagePtr->horz_v_period; + pi->vert_y_period = imagePtr->vert_y_period; + pi->vert_u_period = imagePtr->vert_u_period; + pi->vert_v_period = imagePtr->vert_v_period; + memcpy(pi->component_order, imagePtr->component_order, 32); + pi->scanline_order = imagePtr->scanline_order; + } + pa->nImages = adaptorPtr->nImages; + pa->pImages = pImage; + } + + if(adaptorPtr->nAttributes && + (pAttribute = calloc(adaptorPtr->nAttributes, sizeof(XvAttributeRec)))) + { + for(pat = pAttribute, attributePtr = adaptorPtr->pAttributes, i = 0; + i < adaptorPtr->nAttributes; pat++, i++, attributePtr++) + { + pat->flags = attributePtr->flags; + pat->min_value = attributePtr->min_value; + pat->max_value = attributePtr->max_value; + pat->name = strdup(attributePtr->name); + } + pa->nAttributes = adaptorPtr->nAttributes; + pa->pAttributes = pAttribute; + } + + + totFormat = adaptorPtr->nFormats; + + if(!(pFormat = calloc(totFormat, sizeof(XvFormatRec)))) { + xf86XVFreeAdaptor(pa); + continue; + } + for(pf = pFormat, i = 0, numFormat = 0, formatPtr = adaptorPtr->pFormats; + i < adaptorPtr->nFormats; i++, formatPtr++) + { + numVisuals = pScreen->numVisuals; + pVisual = pScreen->visuals; + + while(numVisuals--) { + if((pVisual->class == formatPtr->class) && + (pVisual->nplanes == formatPtr->depth)) { + + if(numFormat >= totFormat) { + void *moreSpace; + totFormat *= 2; + moreSpace = realloc(pFormat, + totFormat * sizeof(XvFormatRec)); + if(!moreSpace) break; + pFormat = moreSpace; + pf = pFormat + numFormat; + } + + pf->visual = pVisual->vid; + pf->depth = formatPtr->depth; + + pf++; + numFormat++; + } + pVisual++; + } + } + pa->nFormats = numFormat; + pa->pFormats = pFormat; + if(!numFormat) { + xf86XVFreeAdaptor(pa); + continue; + } + + if(!(adaptorPriv = calloc(1, sizeof(XvAdaptorRecPrivate)))) { + xf86XVFreeAdaptor(pa); + continue; + } + + adaptorPriv->flags = adaptorPtr->flags; + adaptorPriv->PutVideo = adaptorPtr->PutVideo; + adaptorPriv->PutStill = adaptorPtr->PutStill; + adaptorPriv->GetVideo = adaptorPtr->GetVideo; + adaptorPriv->GetStill = adaptorPtr->GetStill; + adaptorPriv->StopVideo = adaptorPtr->StopVideo; + adaptorPriv->SetPortAttribute = adaptorPtr->SetPortAttribute; + adaptorPriv->GetPortAttribute = adaptorPtr->GetPortAttribute; + adaptorPriv->QueryBestSize = adaptorPtr->QueryBestSize; + adaptorPriv->QueryImageAttributes = adaptorPtr->QueryImageAttributes; + adaptorPriv->PutImage = adaptorPtr->PutImage; + adaptorPriv->ReputImage = adaptorPtr->ReputImage; /* image/still */ + + pa->devPriv.ptr = (pointer)adaptorPriv; + + if(!(pPort = calloc(adaptorPtr->nPorts, sizeof(XvPortRec)))) { + xf86XVFreeAdaptor(pa); + continue; + } + for(pp = pPort, i = 0, numPort = 0; + i < adaptorPtr->nPorts; i++) { + + if(!(pp->id = FakeClientID(0))) + continue; + + if(!(portPriv = calloc(1, sizeof(XvPortRecPrivate)))) + continue; + + if(!AddResource(pp->id, PortResource, pp)) { + free(portPriv); + continue; + } + + pp->pAdaptor = pa; + pp->pNotify = (XvPortNotifyPtr)NULL; + pp->pDraw = (DrawablePtr)NULL; + pp->client = (ClientPtr)NULL; + pp->grab.client = (ClientPtr)NULL; + pp->time = currentTime; + pp->devPriv.ptr = portPriv; + + portPriv->pScrn = pScrn; + portPriv->AdaptorRec = adaptorPriv; + portPriv->DevPriv.ptr = adaptorPtr->pPortPrivates[i].ptr; + + pp++; + numPort++; + } + pa->nPorts = numPort; + pa->pPorts = pPort; + if(!numPort) { + xf86XVFreeAdaptor(pa); + continue; + } + + pa->base_id = pPort->id; + + pa++; + numAdaptor++; + } + + if(numAdaptor) { + pxvs->nAdaptors = numAdaptor; + pxvs->pAdaptors = pAdaptor; + } else { + free(pAdaptor); + return FALSE; + } + + return TRUE; +} + +/* Video should be clipped to the intersection of the window cliplist + and the client cliplist specified in the GC for which the video was + initialized. When we need to reclip a window, the GC that started + the video may not even be around anymore. That's why we save the + client clip from the GC when the video is initialized. We then + use xf86XVUpdateCompositeClip to calculate the new composite clip + when we need it. This is different from what DEC did. They saved + the GC and used it's clip list when they needed to reclip the window, + even if the client clip was different from the one the video was + initialized with. If the original GC was destroyed, they had to stop + the video. I like the new method better (MArk). + + This function only works for windows. Will need to rewrite when + (if) we support pixmap rendering. +*/ + +static void +xf86XVUpdateCompositeClip(XvPortRecPrivatePtr portPriv) +{ + RegionPtr pregWin, pCompositeClip; + WindowPtr pWin; + Bool freeCompClip = FALSE; + + if(portPriv->pCompositeClip) + return; + + pWin = (WindowPtr)portPriv->pDraw; + + /* get window clip list */ + if(portPriv->subWindowMode == IncludeInferiors) { + pregWin = NotClippedByChildren(pWin); + freeCompClip = TRUE; + } else + pregWin = &pWin->clipList; + + if(!portPriv->clientClip) { + portPriv->pCompositeClip = pregWin; + portPriv->FreeCompositeClip = freeCompClip; + return; + } + + pCompositeClip = RegionCreate(NullBox, 1); + RegionCopy(pCompositeClip, portPriv->clientClip); + RegionTranslate(pCompositeClip, + portPriv->pDraw->x, portPriv->pDraw->y); + RegionIntersect(pCompositeClip, pregWin, pCompositeClip); + + portPriv->pCompositeClip = pCompositeClip; + portPriv->FreeCompositeClip = TRUE; + + if(freeCompClip) { + RegionDestroy(pregWin); + } +} + +/* Save the current clientClip and update the CompositeClip whenever + we have a fresh GC */ + +static void +xf86XVCopyClip( + XvPortRecPrivatePtr portPriv, + GCPtr pGC +){ + /* copy the new clip if it exists */ + if((pGC->clientClipType == CT_REGION) && pGC->clientClip) { + if(!portPriv->clientClip) + portPriv->clientClip = RegionCreate(NullBox, 1); + /* Note: this is in window coordinates */ + RegionCopy(portPriv->clientClip, pGC->clientClip); + RegionTranslate(portPriv->clientClip, + pGC->clipOrg.x, pGC->clipOrg.y); + } else if(portPriv->clientClip) { /* free the old clientClip */ + RegionDestroy(portPriv->clientClip); + portPriv->clientClip = NULL; + } + + /* get rid of the old clip list */ + if(portPriv->pCompositeClip && portPriv->FreeCompositeClip) { + RegionDestroy(portPriv->pCompositeClip); + } + + portPriv->pCompositeClip = pGC->pCompositeClip; + portPriv->FreeCompositeClip = FALSE; + portPriv->subWindowMode = pGC->subWindowMode; +} + +static void +xf86XVCopyCompositeClip(XvPortRecPrivatePtr portPriv, + GCPtr pGC, + DrawablePtr pDraw) +{ + if (!portPriv->clientClip) + portPriv->clientClip = RegionCreate(NullBox, 1); + /* Keep the original GC composite clip around for ReputImage */ + RegionCopy(portPriv->clientClip, pGC->pCompositeClip); + RegionTranslate(portPriv->clientClip, + -pDraw->x, -pDraw->y); + + /* get rid of the old clip list */ + if (portPriv->pCompositeClip && portPriv->FreeCompositeClip) + RegionDestroy(portPriv->pCompositeClip); + + portPriv->pCompositeClip = pGC->pCompositeClip; + portPriv->FreeCompositeClip = FALSE; + portPriv->subWindowMode = pGC->subWindowMode; +} + +static int +xf86XVRegetVideo(XvPortRecPrivatePtr portPriv) +{ + RegionRec WinRegion; + RegionRec ClipRegion; + BoxRec WinBox; + int ret = Success; + Bool clippedAway = FALSE; + + xf86XVUpdateCompositeClip(portPriv); + + /* translate the video region to the screen */ + WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x; + WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y; + WinBox.x2 = WinBox.x1 + portPriv->drw_w; + WinBox.y2 = WinBox.y1 + portPriv->drw_h; + + /* clip to the window composite clip */ + RegionInit(&WinRegion, &WinBox, 1); + RegionNull(&ClipRegion); + RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip); + + /* that's all if it's totally obscured */ + if(!RegionNotEmpty(&ClipRegion)) { + clippedAway = TRUE; + goto CLIP_VIDEO_BAILOUT; + } + + if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { + RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion); + } + + ret = (*portPriv->AdaptorRec->GetVideo)(portPriv->pScrn, + portPriv->vid_x, portPriv->vid_y, + WinBox.x1, WinBox.y1, + portPriv->vid_w, portPriv->vid_h, + portPriv->drw_w, portPriv->drw_h, + &ClipRegion, portPriv->DevPriv.ptr, + portPriv->pDraw); + + if(ret == Success) + portPriv->isOn = XV_ON; + +CLIP_VIDEO_BAILOUT: + + if((clippedAway || (ret != Success)) && portPriv->isOn == XV_ON) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); + portPriv->isOn = XV_PENDING; + } + + /* This clip was copied and only good for one shot */ + if(!portPriv->FreeCompositeClip) + portPriv->pCompositeClip = NULL; + + RegionUninit(&WinRegion); + RegionUninit(&ClipRegion); + + return ret; +} + + +static int +xf86XVReputVideo(XvPortRecPrivatePtr portPriv) +{ + RegionRec WinRegion; + RegionRec ClipRegion; + BoxRec WinBox; + int ret = Success; + Bool clippedAway = FALSE; + + xf86XVUpdateCompositeClip(portPriv); + + /* translate the video region to the screen */ + WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x; + WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y; + WinBox.x2 = WinBox.x1 + portPriv->drw_w; + WinBox.y2 = WinBox.y1 + portPriv->drw_h; + + /* clip to the window composite clip */ + RegionInit(&WinRegion, &WinBox, 1); + RegionNull(&ClipRegion); + RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip); + + /* clip and translate to the viewport */ + if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { + RegionRec VPReg; + BoxRec VPBox; + + VPBox.x1 = portPriv->pScrn->frameX0; + VPBox.y1 = portPriv->pScrn->frameY0; + VPBox.x2 = portPriv->pScrn->frameX1 + 1; + VPBox.y2 = portPriv->pScrn->frameY1 + 1; + + RegionInit(&VPReg, &VPBox, 1); + RegionIntersect(&ClipRegion, &ClipRegion, &VPReg); + RegionUninit(&VPReg); + } + + /* that's all if it's totally obscured */ + if(!RegionNotEmpty(&ClipRegion)) { + clippedAway = TRUE; + goto CLIP_VIDEO_BAILOUT; + } + + /* bailout if we have to clip but the hardware doesn't support it */ + if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) { + BoxPtr clipBox = RegionRects(&ClipRegion); + if( (RegionNumRects(&ClipRegion) != 1) || + (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) || + (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) + { + clippedAway = TRUE; + goto CLIP_VIDEO_BAILOUT; + } + } + + if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { + RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion); + } + + ret = (*portPriv->AdaptorRec->PutVideo)(portPriv->pScrn, + portPriv->vid_x, portPriv->vid_y, + WinBox.x1, WinBox.y1, + portPriv->vid_w, portPriv->vid_h, + portPriv->drw_w, portPriv->drw_h, + &ClipRegion, portPriv->DevPriv.ptr, + portPriv->pDraw); + + if(ret == Success) portPriv->isOn = XV_ON; + +CLIP_VIDEO_BAILOUT: + + if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); + portPriv->isOn = XV_PENDING; + } + + /* This clip was copied and only good for one shot */ + if(!portPriv->FreeCompositeClip) + portPriv->pCompositeClip = NULL; + + RegionUninit(&WinRegion); + RegionUninit(&ClipRegion); + + return ret; +} + +/* Reput image/still */ +static int +xf86XVReputImage(XvPortRecPrivatePtr portPriv) +{ + RegionRec WinRegion; + RegionRec ClipRegion; + BoxRec WinBox; + int ret = Success; + Bool clippedAway = FALSE; + + xf86XVUpdateCompositeClip(portPriv); + + /* the clip can get smaller over time */ + RegionCopy(portPriv->clientClip, portPriv->pCompositeClip); + RegionTranslate(portPriv->clientClip, + -portPriv->pDraw->x, -portPriv->pDraw->y); + + /* translate the video region to the screen */ + WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x; + WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y; + WinBox.x2 = WinBox.x1 + portPriv->drw_w; + WinBox.y2 = WinBox.y1 + portPriv->drw_h; + + /* clip to the window composite clip */ + RegionInit(&WinRegion, &WinBox, 1); + RegionNull(&ClipRegion); + RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip); + + /* clip and translate to the viewport */ + if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { + RegionRec VPReg; + BoxRec VPBox; + + VPBox.x1 = portPriv->pScrn->frameX0; + VPBox.y1 = portPriv->pScrn->frameY0; + VPBox.x2 = portPriv->pScrn->frameX1 + 1; + VPBox.y2 = portPriv->pScrn->frameY1 + 1; + + RegionInit(&VPReg, &VPBox, 1); + RegionIntersect(&ClipRegion, &ClipRegion, &VPReg); + RegionUninit(&VPReg); + } + + /* that's all if it's totally obscured */ + if(!RegionNotEmpty(&ClipRegion)) { + clippedAway = TRUE; + goto CLIP_VIDEO_BAILOUT; + } + + /* bailout if we have to clip but the hardware doesn't support it */ + if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) { + BoxPtr clipBox = RegionRects(&ClipRegion); + if( (RegionNumRects(&ClipRegion) != 1) || + (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) || + (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) + { + clippedAway = TRUE; + goto CLIP_VIDEO_BAILOUT; + } + } + + if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { + RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion); + } + + ret = (*portPriv->AdaptorRec->ReputImage)(portPriv->pScrn, + portPriv->vid_x, portPriv->vid_y, + WinBox.x1, WinBox.y1, + portPriv->vid_w, portPriv->vid_h, + portPriv->drw_w, portPriv->drw_h, + &ClipRegion, portPriv->DevPriv.ptr, + portPriv->pDraw); + + portPriv->isOn = (ret == Success) ? XV_ON : XV_OFF; + +CLIP_VIDEO_BAILOUT: + + if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); + portPriv->isOn = XV_PENDING; + } + + /* This clip was copied and only good for one shot */ + if(!portPriv->FreeCompositeClip) + portPriv->pCompositeClip = NULL; + + RegionUninit(&WinRegion); + RegionUninit(&ClipRegion); + + return ret; +} + + +static int +xf86XVReputAllVideo(WindowPtr pWin, pointer data) +{ + XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin); + + while(WinPriv) { + if(WinPriv->PortRec->type == XvInputMask) + xf86XVReputVideo(WinPriv->PortRec); + else + xf86XVRegetVideo(WinPriv->PortRec); + WinPriv = WinPriv->next; + } + + return WT_WALKCHILDREN; +} + +static int +xf86XVEnlistPortInWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv) +{ + XF86XVWindowPtr winPriv, PrivRoot; + + winPriv = PrivRoot = GET_XF86XV_WINDOW(pWin); + + /* Enlist our port in the window private */ + while(winPriv) { + if(winPriv->PortRec == portPriv) /* we're already listed */ + break; + winPriv = winPriv->next; + } + + if(!winPriv) { + winPriv = calloc(1, sizeof(XF86XVWindowRec)); + if(!winPriv) return BadAlloc; + winPriv->PortRec = portPriv; + winPriv->next = PrivRoot; + dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, winPriv); + } + + portPriv->pDraw = (DrawablePtr)pWin; + + return Success; +} + + +static void +xf86XVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv) +{ + XF86XVWindowPtr winPriv, prevPriv = NULL; + winPriv = GET_XF86XV_WINDOW(pWin); + + while(winPriv) { + if(winPriv->PortRec == portPriv) { + if(prevPriv) + prevPriv->next = winPriv->next; + else + dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, + winPriv->next); + free(winPriv); + break; + } + prevPriv = winPriv; + winPriv = winPriv->next; + } + portPriv->pDraw = NULL; + if (portPriv->ckeyFilled) { + RegionDestroy(portPriv->ckeyFilled); + portPriv->ckeyFilled = NULL; + } + portPriv->clipChanged = FALSE; +} + +static void +xf86XVReputOrStopPort(XvPortRecPrivatePtr pPriv, + WindowPtr pWin, + Bool visible) +{ + if (!visible) { + if (pPriv->isOn == XV_ON) { + (*pPriv->AdaptorRec->StopVideo)(pPriv->pScrn, pPriv->DevPriv.ptr, FALSE); + pPriv->isOn = XV_PENDING; + } + + if (!pPriv->type) /* overlaid still/image*/ + xf86XVRemovePortFromWindow(pWin, pPriv); + + return; + } + + switch (pPriv->type) { + case XvInputMask: + xf86XVReputVideo(pPriv); + break; + case XvOutputMask: + xf86XVRegetVideo(pPriv); + break; + default: /* overlaid still/image*/ + if (pPriv->AdaptorRec->ReputImage) + xf86XVReputImage(pPriv); + break; + } +} + +static void +xf86XVReputOrStopAllPorts(ScrnInfoPtr pScrn, Bool onlyChanged) +{ + ScreenPtr pScreen = pScrn->pScreen; + XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); + XvAdaptorPtr pa; + int c, i; + + for (c = pxvs->nAdaptors, pa = pxvs->pAdaptors; c > 0; c--, pa++) { + XvPortPtr pPort = pa->pPorts; + + for (i = pa->nPorts; i > 0; i--, pPort++) { + XvPortRecPrivatePtr pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr; + WindowPtr pWin = (WindowPtr)pPriv->pDraw; + Bool visible; + + if (pPriv->isOn == XV_OFF || !pWin) + continue; + + if (onlyChanged && !pPriv->clipChanged) + continue; + + visible = pWin->visibility == VisibilityUnobscured || + pWin->visibility == VisibilityPartiallyObscured; + + /* + * Stop and remove still/images if + * ReputImage isn't supported. + */ + if (!pPriv->type && !pPriv->AdaptorRec->ReputImage) + visible = FALSE; + + xf86XVReputOrStopPort(pPriv, pWin, visible); + + pPriv->clipChanged = FALSE; + } + } +} + +/**** ScreenRec fields ****/ + +static Bool +xf86XVDestroyWindow(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); + XF86XVWindowPtr tmp, WinPriv = GET_XF86XV_WINDOW(pWin); + int ret; + + while(WinPriv) { + XvPortRecPrivatePtr pPriv = WinPriv->PortRec; + + if(pPriv->isOn > XV_OFF) { + (*pPriv->AdaptorRec->StopVideo)( + pPriv->pScrn, pPriv->DevPriv.ptr, TRUE); + pPriv->isOn = XV_OFF; + } + + pPriv->pDraw = NULL; + tmp = WinPriv; + WinPriv = WinPriv->next; + free(tmp); + } + + dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, NULL); + + pScreen->DestroyWindow = ScreenPriv->DestroyWindow; + ret = (*pScreen->DestroyWindow)(pWin); + pScreen->DestroyWindow = xf86XVDestroyWindow; + + return ret; +} + +static void +xf86XVPostValidateTree(WindowPtr pWin, WindowPtr pLayerWin, VTKind kind) +{ + ScreenPtr pScreen; + XF86XVScreenPtr ScreenPriv; + ScrnInfoPtr pScrn; + + if (pWin) + pScreen = pWin->drawable.pScreen; + else + pScreen = pLayerWin->drawable.pScreen; + + ScreenPriv = GET_XF86XV_SCREEN(pScreen); + pScrn = xf86Screens[pScreen->myNum]; + + xf86XVReputOrStopAllPorts(pScrn, TRUE); + + pScreen->PostValidateTree = ScreenPriv->PostValidateTree; + if (pScreen->PostValidateTree) { + (*pScreen->PostValidateTree)(pWin, pLayerWin, kind); + } + ScreenPriv->PostValidateTree = PostValidateTreeUndefined; +} + +static void +xf86XVWindowExposures(WindowPtr pWin, RegionPtr reg1, RegionPtr reg2) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); + XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin); + XvPortRecPrivatePtr pPriv; + Bool AreasExposed; + + AreasExposed = (WinPriv && reg1 && RegionNotEmpty(reg1)); + + pScreen->WindowExposures = ScreenPriv->WindowExposures; + (*pScreen->WindowExposures)(pWin, reg1, reg2); + pScreen->WindowExposures = xf86XVWindowExposures; + + /* filter out XClearWindow/Area */ + if (!pWin->valdata) return; + + while(WinPriv) { + Bool visible = TRUE; + + pPriv = WinPriv->PortRec; + + /* + * Stop and remove still/images if areas were exposed and + * ReputImage isn't supported. + */ + if (!pPriv->type && !pPriv->AdaptorRec->ReputImage) + visible = !AreasExposed; + + /* + * Subtract exposed areas from overlaid image to match textured video + * behavior. + */ + if (!pPriv->type && pPriv->clientClip) + RegionSubtract(pPriv->clientClip, pPriv->clientClip, reg1); + + if (visible && pPriv->ckeyFilled) { + RegionRec tmp; + RegionNull(&tmp); + RegionCopy(&tmp, reg1); + RegionTranslate(&tmp, pWin->drawable.x, pWin->drawable.y); + RegionSubtract(pPriv->ckeyFilled, pPriv->ckeyFilled, &tmp); + } + + WinPriv = WinPriv->next; + xf86XVReputOrStopPort(pPriv, pWin, visible); + + pPriv->clipChanged = FALSE; + } +} + +static void +xf86XVClipNotify(WindowPtr pWin, int dx, int dy) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); + XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin); + XvPortRecPrivatePtr pPriv; + + while(WinPriv) { + pPriv = WinPriv->PortRec; + + if(pPriv->pCompositeClip && pPriv->FreeCompositeClip) + RegionDestroy(pPriv->pCompositeClip); + + pPriv->pCompositeClip = NULL; + + if (pPriv->AdaptorRec->ClipNotify) + (*pPriv->AdaptorRec->ClipNotify)(pPriv->pScrn, pPriv->DevPriv.ptr, + pWin, dx, dy); + + pPriv->clipChanged = TRUE; + + if (ScreenPriv->PostValidateTree == PostValidateTreeUndefined) { + ScreenPriv->PostValidateTree = pScreen->PostValidateTree; + pScreen->PostValidateTree = xf86XVPostValidateTree; + } + + WinPriv = WinPriv->next; + } + + if(ScreenPriv->ClipNotify) { + pScreen->ClipNotify = ScreenPriv->ClipNotify; + (*pScreen->ClipNotify)(pWin, dx, dy); + pScreen->ClipNotify = xf86XVClipNotify; + } +} + + + +/**** Required XvScreenRec fields ****/ + +static Bool +xf86XVCloseScreen(int i, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); + XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); + XvAdaptorPtr pa; + int c; + + if(!ScreenPriv) return TRUE; + + pScreen->DestroyWindow = ScreenPriv->DestroyWindow; + pScreen->WindowExposures = ScreenPriv->WindowExposures; + pScreen->ClipNotify = ScreenPriv->ClipNotify; + + pScrn->EnterVT = ScreenPriv->EnterVT; + pScrn->LeaveVT = ScreenPriv->LeaveVT; + pScrn->AdjustFrame = ScreenPriv->AdjustFrame; + pScrn->ModeSet = ScreenPriv->ModeSet; + + for(c = 0, pa = pxvs->pAdaptors; c < pxvs->nAdaptors; c++, pa++) { + xf86XVFreeAdaptor(pa); + } + + free(pxvs->pAdaptors); + free(ScreenPriv); + return TRUE; +} + + +static int +xf86XVQueryAdaptors( + ScreenPtr pScreen, + XvAdaptorPtr *p_pAdaptors, + int *p_nAdaptors +){ + XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); + + *p_nAdaptors = pxvs->nAdaptors; + *p_pAdaptors = pxvs->pAdaptors; + + return Success; +} + + +/**** ScrnInfoRec fields ****/ + +static Bool +xf86XVEnterVT(int index, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[index]; + ScreenPtr pScreen = screenInfo.screens[index]; + XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); + Bool ret; + + pScrn->EnterVT = ScreenPriv->EnterVT; + ret = (*ScreenPriv->EnterVT)(index, flags); + ScreenPriv->EnterVT = pScrn->EnterVT; + pScrn->EnterVT = xf86XVEnterVT; + + if(ret) WalkTree(pScreen, xf86XVReputAllVideo, 0); + + return ret; +} + +static void +xf86XVLeaveVT(int index, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[index]; + ScreenPtr pScreen = screenInfo.screens[index]; + XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); + XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); + XvAdaptorPtr pAdaptor; + XvPortPtr pPort; + XvPortRecPrivatePtr pPriv; + int i, j; + + for(i = 0; i < pxvs->nAdaptors; i++) { + pAdaptor = &pxvs->pAdaptors[i]; + for(j = 0; j < pAdaptor->nPorts; j++) { + pPort = &pAdaptor->pPorts[j]; + pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr; + if(pPriv->isOn > XV_OFF) { + + (*pPriv->AdaptorRec->StopVideo)( + pPriv->pScrn, pPriv->DevPriv.ptr, TRUE); + pPriv->isOn = XV_OFF; + + if(pPriv->pCompositeClip && pPriv->FreeCompositeClip) + RegionDestroy(pPriv->pCompositeClip); + + pPriv->pCompositeClip = NULL; + + if(!pPriv->type && pPriv->pDraw) { /* still */ + xf86XVRemovePortFromWindow((WindowPtr)pPriv->pDraw, pPriv); + } + } + } + } + + pScrn->LeaveVT = ScreenPriv->LeaveVT; + (*ScreenPriv->LeaveVT)(index, flags); + ScreenPriv->LeaveVT = pScrn->LeaveVT; + pScrn->LeaveVT = xf86XVLeaveVT; +} + +static void +xf86XVAdjustFrame(int index, int x, int y, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[index]; + ScreenPtr pScreen = pScrn->pScreen; + XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); + + if(ScreenPriv->AdjustFrame) { + pScrn->AdjustFrame = ScreenPriv->AdjustFrame; + (*pScrn->AdjustFrame)(index, x, y, flags); + pScrn->AdjustFrame = xf86XVAdjustFrame; + } + + xf86XVReputOrStopAllPorts(pScrn, FALSE); +} + +static void +xf86XVModeSet(ScrnInfoPtr pScrn) +{ + ScreenPtr pScreen = pScrn->pScreen; + XF86XVScreenPtr ScreenPriv; + + /* Can be called before pScrn->pScreen is set */ + if (!pScreen) + return; + + ScreenPriv = GET_XF86XV_SCREEN(pScreen); + + if (ScreenPriv->ModeSet) { + pScrn->ModeSet = ScreenPriv->ModeSet; + (*pScrn->ModeSet)(pScrn); + pScrn->ModeSet = xf86XVModeSet; + } + + xf86XVReputOrStopAllPorts(pScrn, FALSE); +} + +/**** XvAdaptorRec fields ****/ + +static int +xf86XVAllocatePort( + unsigned long port, + XvPortPtr pPort, + XvPortPtr *ppPort +){ + *ppPort = pPort; + return Success; +} + + + +static int +xf86XVFreePort(XvPortPtr pPort) +{ + return Success; +} + + +static int +xf86XVPutVideo( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 vid_x, INT16 vid_y, + CARD16 vid_w, CARD16 vid_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + int result; + + /* No dumping video to pixmaps... For now anyhow */ + if(pDraw->type != DRAWABLE_WINDOW) { + pPort->pDraw = (DrawablePtr)NULL; + return BadAlloc; + } + + /* If we are changing windows, unregister our port in the old window */ + if(portPriv->pDraw && (portPriv->pDraw != pDraw)) + xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); + + /* Register our port with the new window */ + result = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv); + if(result != Success) return result; + + portPriv->type = XvInputMask; + + /* save a copy of these parameters */ + portPriv->vid_x = vid_x; portPriv->vid_y = vid_y; + portPriv->vid_w = vid_w; portPriv->vid_h = vid_h; + portPriv->drw_x = drw_x; portPriv->drw_y = drw_y; + portPriv->drw_w = drw_w; portPriv->drw_h = drw_h; + + /* make sure we have the most recent copy of the clientClip */ + xf86XVCopyClip(portPriv, pGC); + + /* To indicate to the DI layer that we were successful */ + pPort->pDraw = pDraw; + + if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ + + return(xf86XVReputVideo(portPriv)); +} + +static int +xf86XVPutStill( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 vid_x, INT16 vid_y, + CARD16 vid_w, CARD16 vid_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + RegionRec WinRegion; + RegionRec ClipRegion; + BoxRec WinBox; + int ret = Success; + Bool clippedAway = FALSE; + + if (pDraw->type != DRAWABLE_WINDOW) + return BadAlloc; + + if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ + + WinBox.x1 = pDraw->x + drw_x; + WinBox.y1 = pDraw->y + drw_y; + WinBox.x2 = WinBox.x1 + drw_w; + WinBox.y2 = WinBox.y1 + drw_h; + + xf86XVCopyCompositeClip(portPriv, pGC, pDraw); + + RegionInit(&WinRegion, &WinBox, 1); + RegionNull(&ClipRegion); + RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip); + + if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { + RegionRec VPReg; + BoxRec VPBox; + + VPBox.x1 = portPriv->pScrn->frameX0; + VPBox.y1 = portPriv->pScrn->frameY0; + VPBox.x2 = portPriv->pScrn->frameX1 + 1; + VPBox.y2 = portPriv->pScrn->frameY1 + 1; + + RegionInit(&VPReg, &VPBox, 1); + RegionIntersect(&ClipRegion, &ClipRegion, &VPReg); + RegionUninit(&VPReg); + } + + if(portPriv->pDraw) { + xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); + } + + if(!RegionNotEmpty(&ClipRegion)) { + clippedAway = TRUE; + goto PUT_STILL_BAILOUT; + } + + if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) { + BoxPtr clipBox = RegionRects(&ClipRegion); + if( (RegionNumRects(&ClipRegion) != 1) || + (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) || + (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) + { + clippedAway = TRUE; + goto PUT_STILL_BAILOUT; + } + } + + if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { + RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion); + } + + ret = (*portPriv->AdaptorRec->PutStill)(portPriv->pScrn, + vid_x, vid_y, WinBox.x1, WinBox.y1, + vid_w, vid_h, drw_w, drw_h, + &ClipRegion, portPriv->DevPriv.ptr, + pDraw); + + if((ret == Success) && + (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_STILLS)) { + + xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv); + portPriv->isOn = XV_ON; + portPriv->vid_x = vid_x; portPriv->vid_y = vid_y; + portPriv->vid_w = vid_w; portPriv->vid_h = vid_h; + portPriv->drw_x = drw_x; portPriv->drw_y = drw_y; + portPriv->drw_w = drw_w; portPriv->drw_h = drw_h; + portPriv->type = 0; /* no mask means it's transient and should + not be reput once it's removed */ + pPort->pDraw = pDraw; /* make sure we can get stop requests */ + } + +PUT_STILL_BAILOUT: + + if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); + portPriv->isOn = XV_PENDING; + } + + /* This clip was copied and only good for one shot */ + if(!portPriv->FreeCompositeClip) + portPriv->pCompositeClip = NULL; + + RegionUninit(&WinRegion); + RegionUninit(&ClipRegion); + + return ret; +} + +static int +xf86XVGetVideo( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 vid_x, INT16 vid_y, + CARD16 vid_w, CARD16 vid_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + int result; + + /* No pixmaps... For now anyhow */ + if(pDraw->type != DRAWABLE_WINDOW) { + pPort->pDraw = (DrawablePtr)NULL; + return BadAlloc; + } + + /* If we are changing windows, unregister our port in the old window */ + if(portPriv->pDraw && (portPriv->pDraw != pDraw)) + xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); + + /* Register our port with the new window */ + result = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv); + if(result != Success) return result; + + portPriv->type = XvOutputMask; + + /* save a copy of these parameters */ + portPriv->vid_x = vid_x; portPriv->vid_y = vid_y; + portPriv->vid_w = vid_w; portPriv->vid_h = vid_h; + portPriv->drw_x = drw_x; portPriv->drw_y = drw_y; + portPriv->drw_w = drw_w; portPriv->drw_h = drw_h; + + /* make sure we have the most recent copy of the clientClip */ + xf86XVCopyClip(portPriv, pGC); + + /* To indicate to the DI layer that we were successful */ + pPort->pDraw = pDraw; + + if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ + + return(xf86XVRegetVideo(portPriv)); +} + +static int +xf86XVGetStill( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 vid_x, INT16 vid_y, + CARD16 vid_w, CARD16 vid_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + RegionRec WinRegion; + RegionRec ClipRegion; + BoxRec WinBox; + int ret = Success; + Bool clippedAway = FALSE; + + if (pDraw->type != DRAWABLE_WINDOW) + return BadAlloc; + + if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ + + WinBox.x1 = pDraw->x + drw_x; + WinBox.y1 = pDraw->y + drw_y; + WinBox.x2 = WinBox.x1 + drw_w; + WinBox.y2 = WinBox.y1 + drw_h; + + RegionInit(&WinRegion, &WinBox, 1); + RegionNull(&ClipRegion); + RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip); + + if(portPriv->pDraw) { + xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); + } + + if(!RegionNotEmpty(&ClipRegion)) { + clippedAway = TRUE; + goto GET_STILL_BAILOUT; + } + + if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { + RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion); + } + + ret = (*portPriv->AdaptorRec->GetStill)(portPriv->pScrn, + vid_x, vid_y, WinBox.x1, WinBox.y1, + vid_w, vid_h, drw_w, drw_h, + &ClipRegion, portPriv->DevPriv.ptr, + pDraw); + +GET_STILL_BAILOUT: + + if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); + portPriv->isOn = XV_PENDING; + } + + RegionUninit(&WinRegion); + RegionUninit(&ClipRegion); + + return ret; +} + + + +static int +xf86XVStopVideo( + ClientPtr client, + XvPortPtr pPort, + DrawablePtr pDraw +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + + if(pDraw->type != DRAWABLE_WINDOW) + return BadAlloc; + + xf86XVRemovePortFromWindow((WindowPtr)pDraw, portPriv); + + if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ + + /* Must free resources. */ + + if(portPriv->isOn > XV_OFF) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->pScrn, portPriv->DevPriv.ptr, TRUE); + portPriv->isOn = XV_OFF; + } + + return Success; +} + +static int +xf86XVSetPortAttribute( + ClientPtr client, + XvPortPtr pPort, + Atom attribute, + INT32 value +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + + return((*portPriv->AdaptorRec->SetPortAttribute)(portPriv->pScrn, + attribute, value, portPriv->DevPriv.ptr)); +} + + +static int +xf86XVGetPortAttribute( + ClientPtr client, + XvPortPtr pPort, + Atom attribute, + INT32 *p_value +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + + return((*portPriv->AdaptorRec->GetPortAttribute)(portPriv->pScrn, + attribute, p_value, portPriv->DevPriv.ptr)); +} + + + +static int +xf86XVQueryBestSize( + ClientPtr client, + XvPortPtr pPort, + CARD8 motion, + CARD16 vid_w, CARD16 vid_h, + CARD16 drw_w, CARD16 drw_h, + unsigned int *p_w, unsigned int *p_h +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + + (*portPriv->AdaptorRec->QueryBestSize)(portPriv->pScrn, + (Bool)motion, vid_w, vid_h, drw_w, drw_h, + p_w, p_h, portPriv->DevPriv.ptr); + + return Success; +} + + +static int +xf86XVPutImage( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 src_x, INT16 src_y, + CARD16 src_w, CARD16 src_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h, + XvImagePtr format, + unsigned char* data, + Bool sync, + CARD16 width, CARD16 height +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + RegionRec WinRegion; + RegionRec ClipRegion; + BoxRec WinBox; + int ret = Success; + Bool clippedAway = FALSE; + + if (pDraw->type != DRAWABLE_WINDOW) + return BadAlloc; + + if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ + + xf86XVCopyCompositeClip(portPriv, pGC, pDraw); + + WinBox.x1 = pDraw->x + drw_x; + WinBox.y1 = pDraw->y + drw_y; + WinBox.x2 = WinBox.x1 + drw_w; + WinBox.y2 = WinBox.y1 + drw_h; + + RegionInit(&WinRegion, &WinBox, 1); + RegionNull(&ClipRegion); + RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip); + + if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { + RegionRec VPReg; + BoxRec VPBox; + + VPBox.x1 = portPriv->pScrn->frameX0; + VPBox.y1 = portPriv->pScrn->frameY0; + VPBox.x2 = portPriv->pScrn->frameX1 + 1; + VPBox.y2 = portPriv->pScrn->frameY1 + 1; + + RegionInit(&VPReg, &VPBox, 1); + RegionIntersect(&ClipRegion, &ClipRegion, &VPReg); + RegionUninit(&VPReg); + } + + /* If we are changing windows, unregister our port in the old window */ + if(portPriv->pDraw && (portPriv->pDraw != pDraw)) + xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); + + /* Register our port with the new window */ + ret = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv); + if(ret != Success) goto PUT_IMAGE_BAILOUT; + + if(!RegionNotEmpty(&ClipRegion)) { + clippedAway = TRUE; + goto PUT_IMAGE_BAILOUT; + } + + if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) { + BoxPtr clipBox = RegionRects(&ClipRegion); + if( (RegionNumRects(&ClipRegion) != 1) || + (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) || + (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) + { + clippedAway = TRUE; + goto PUT_IMAGE_BAILOUT; + } + } + + if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { + RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion); + } + + ret = (*portPriv->AdaptorRec->PutImage)(portPriv->pScrn, + src_x, src_y, WinBox.x1, WinBox.y1, + src_w, src_h, drw_w, drw_h, format->id, data, width, height, + sync, &ClipRegion, portPriv->DevPriv.ptr, + pDraw); + + if((ret == Success) && + (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_IMAGES)) { + + portPriv->isOn = XV_ON; + portPriv->vid_x = src_x; portPriv->vid_y = src_y; + portPriv->vid_w = src_w; portPriv->vid_h = src_h; + portPriv->drw_x = drw_x; portPriv->drw_y = drw_y; + portPriv->drw_w = drw_w; portPriv->drw_h = drw_h; + portPriv->type = 0; /* no mask means it's transient and should + not be reput once it's removed */ + pPort->pDraw = pDraw; /* make sure we can get stop requests */ + } + +PUT_IMAGE_BAILOUT: + + if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); + portPriv->isOn = XV_PENDING; + } + + /* This clip was copied and only good for one shot */ + if(!portPriv->FreeCompositeClip) + portPriv->pCompositeClip = NULL; + + RegionUninit(&WinRegion); + RegionUninit(&ClipRegion); + + return ret; +} + + +static int +xf86XVQueryImageAttributes( + ClientPtr client, + XvPortPtr pPort, + XvImagePtr format, + CARD16 *width, + CARD16 *height, + int *pitches, + int *offsets +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + + return (*portPriv->AdaptorRec->QueryImageAttributes)(portPriv->pScrn, + format->id, width, height, pitches, offsets); +} + +void +xf86XVFillKeyHelperDrawable (DrawablePtr pDraw, CARD32 key, RegionPtr fillboxes) +{ + ScreenPtr pScreen = pDraw->pScreen; + ChangeGCVal pval[2]; + BoxPtr pbox = RegionRects(fillboxes); + int i, nbox = RegionNumRects(fillboxes); + xRectangle *rects; + GCPtr gc; + + if(!xf86Screens[pScreen->myNum]->vtSema) return; + + gc = GetScratchGC(pDraw->depth, pScreen); + pval[0].val = key; + pval[1].val = IncludeInferiors; + (void) ChangeGC(NullClient, gc, GCForeground|GCSubwindowMode, pval); + ValidateGC(pDraw, gc); + + rects = malloc(nbox * sizeof(xRectangle)); + + for(i = 0; i < nbox; i++, pbox++) + { + rects[i].x = pbox->x1 - pDraw->x; + rects[i].y = pbox->y1 - pDraw->y; + rects[i].width = pbox->x2 - pbox->x1; + rects[i].height = pbox->y2 - pbox->y1; + } + + (*gc->ops->PolyFillRect)(pDraw, gc, nbox, rects); + + free(rects); + FreeScratchGC (gc); +} + +void +xf86XVFillKeyHelper (ScreenPtr pScreen, CARD32 key, RegionPtr fillboxes) +{ + xf86XVFillKeyHelperDrawable (&pScreen->root->drawable, key, fillboxes); +} + +void +xf86XVFillKeyHelperPort (DrawablePtr pDraw, pointer data, CARD32 key, RegionPtr clipboxes, Bool fillEverything) +{ + WindowPtr pWin = (WindowPtr)pDraw; + XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin); + XvPortRecPrivatePtr portPriv = NULL; + RegionRec reg; + RegionPtr fillboxes; + + while (WinPriv) { + XvPortRecPrivatePtr pPriv = WinPriv->PortRec; + + if (data == pPriv->DevPriv.ptr) { + portPriv = pPriv; + break; + } + + WinPriv = WinPriv->next; + } + + if (!portPriv) + return; + + if (!portPriv->ckeyFilled) + portPriv->ckeyFilled = RegionCreate(NULL, 0); + + if (!fillEverything) { + RegionNull(®); + fillboxes = ® + RegionSubtract(fillboxes, clipboxes, portPriv->ckeyFilled); + + if (!RegionNotEmpty(fillboxes)) + goto out; + } else + fillboxes = clipboxes; + + + RegionCopy(portPriv->ckeyFilled, clipboxes); + + xf86XVFillKeyHelperDrawable(pDraw, key, fillboxes); +out: + if (!fillEverything) + RegionUninit(®); +} + + +/* xf86XVClipVideoHelper - + + Takes the dst box in standard X BoxRec form (top and left + edges inclusive, bottom and right exclusive). The new dst + box is returned. The source boundaries are given (x1, y1 + inclusive, x2, y2 exclusive) and returned are the new source + boundaries in 16.16 fixed point. +*/ + +Bool +xf86XVClipVideoHelper( + BoxPtr dst, + INT32 *xa, + INT32 *xb, + INT32 *ya, + INT32 *yb, + RegionPtr reg, + INT32 width, + INT32 height +){ + double xsw, xdw, ysw, ydw; + INT32 delta; + BoxPtr extents = RegionExtents(reg); + int diff; + + xsw = (*xb - *xa) << 16; + xdw = dst->x2 - dst->x1; + ysw = (*yb - *ya) << 16; + ydw = dst->y2 - dst->y1; + + *xa <<= 16; *xb <<= 16; + *ya <<= 16; *yb <<= 16; + + diff = extents->x1 - dst->x1; + if (diff > 0) { + dst->x1 = extents->x1; + *xa += (diff * xsw) / xdw; + } + diff = dst->x2 - extents->x2; + if (diff > 0) { + dst->x2 = extents->x2; + *xb -= (diff * xsw) / xdw; + } + diff = extents->y1 - dst->y1; + if (diff > 0) { + dst->y1 = extents->y1; + *ya += (diff * ysw) / ydw; + } + diff = dst->y2 - extents->y2; + if (diff > 0) { + dst->y2 = extents->y2; + *yb -= (diff * ysw) / ydw; + } + + if (*xa < 0) { + diff = (((-*xa) * xdw) + xsw - 1) / xsw; + dst->x1 += diff; + *xa += (diff * xsw) / xdw; + } + delta = *xb - (width << 16); + if (delta > 0) { + diff = ((delta * xdw) + xsw - 1) / xsw; + dst->x2 -= diff; + *xb -= (diff * xsw) / xdw; + } + if (*xa >= *xb) return FALSE; + + if (*ya < 0) { + diff = (((-*ya) * ydw) + ysw - 1) / ysw; + dst->y1 += diff; + *ya += (diff * ysw) / ydw; + } + delta = *yb - (height << 16); + if (delta > 0) { + diff = ((delta * ydw) + ysw - 1) / ysw; + dst->y2 -= diff; + *yb -= (diff * ysw) / ydw; + } + if (*ya >= *yb) return FALSE; + + if ((dst->x1 > extents->x1) || (dst->x2 < extents->x2) || + (dst->y1 > extents->y1) || (dst->y2 < extents->y2)) + { + RegionRec clipReg; + RegionInit(&clipReg, dst, 1); + RegionIntersect(reg, reg, &clipReg); + RegionUninit(&clipReg); + } + return TRUE; +} + +void +xf86XVCopyYUV12ToPacked( + const void *srcy, + const void *srcv, + const void *srcu, + void *dst, + int srcPitchy, + int srcPitchuv, + int dstPitch, + int h, + int w +){ + CARD32 *Dst; + const CARD8 *Y, *U, *V; + int i, j; + + w >>= 1; + + for (j = 0; j < h; j++) { + Dst = dst; + Y = srcy; V = srcv; U = srcu; + i = w; + while (i >= 4) { +#if X_BYTE_ORDER == X_LITTLE_ENDIAN + Dst[0] = Y[0] | (Y[1] << 16) | (U[0] << 8) | (V[0] << 24); + Dst[1] = Y[2] | (Y[3] << 16) | (U[1] << 8) | (V[1] << 24); + Dst[2] = Y[4] | (Y[5] << 16) | (U[2] << 8) | (V[2] << 24); + Dst[3] = Y[6] | (Y[7] << 16) | (U[3] << 8) | (V[3] << 24); +#else + /* This assumes a little-endian framebuffer */ + Dst[0] = (Y[0] << 24) | (Y[1] << 8) | (U[0] << 16) | V[0]; + Dst[1] = (Y[2] << 24) | (Y[3] << 8) | (U[1] << 16) | V[1]; + Dst[2] = (Y[4] << 24) | (Y[5] << 8) | (U[2] << 16) | V[2]; + Dst[3] = (Y[6] << 24) | (Y[7] << 8) | (U[3] << 16) | V[3]; +#endif + Dst += 4; Y += 8; V += 4; U += 4; + i -= 4; + } + + while (i--) { +#if X_BYTE_ORDER == X_LITTLE_ENDIAN + Dst[0] = Y[0] | (Y[1] << 16) | (U[0] << 8) | (V[0] << 24); +#else + /* This assumes a little-endian framebuffer */ + Dst[0] = (Y[0] << 24) | (Y[1] << 8) | (U[0] << 16) | V[0]; +#endif + Dst++; Y += 2; V++; U++; + } + + dst = (CARD8 *)dst + dstPitch; + srcy = (const CARD8 *)srcy + srcPitchy; + if (j & 1) { + srcu = (const CARD8 *)srcu + srcPitchuv; + srcv = (const CARD8 *)srcv + srcPitchuv; + } + } +} + +void +xf86XVCopyPacked( + const void *src, + void *dst, + int srcPitch, + int dstPitch, + int h, + int w +){ + const CARD32 *Src; + CARD32 *Dst; + int i; + + w >>= 1; + while (--h >= 0) { + do { + Dst = dst; Src = src; + i = w; + while (i >= 4) { + Dst[0] = Src[0]; + Dst[1] = Src[1]; + Dst[2] = Src[2]; + Dst[3] = Src[3]; + Dst += 4; Src += 4; i -= 4; + } + if (!i) break; + Dst[0] = Src[0]; + if (i == 1) break; + Dst[1] = Src[1]; + if (i == 2) break; + Dst[2] = Src[2]; + } while (0); + + src = (const CARD8 *)src + srcPitch; + dst = (CARD8 *)dst + dstPitch; + } +} diff --git a/hw/xfree86/common/xf86xv.h b/hw/xfree86/common/xf86xv.h new file mode 100644 index 0000000..f0d8495 --- /dev/null +++ b/hw/xfree86/common/xf86xv.h @@ -0,0 +1,289 @@ + +/* + * Copyright (c) 1998-2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +#ifndef _XF86XV_H_ +#define _XF86XV_H_ + +#include "xvdix.h" +#include "xf86str.h" + +#define VIDEO_NO_CLIPPING 0x00000001 +#define VIDEO_INVERT_CLIPLIST 0x00000002 +#define VIDEO_OVERLAID_IMAGES 0x00000004 +#define VIDEO_OVERLAID_STILLS 0x00000008 +/* + * Usage of VIDEO_CLIP_TO_VIEWPORT is not recommended. + * It can make reput behaviour inconsistent. + */ +#define VIDEO_CLIP_TO_VIEWPORT 0x00000010 + +typedef struct { + int id; + int type; + int byte_order; + unsigned char guid[16]; + int bits_per_pixel; + int format; + int num_planes; + + /* for RGB formats only */ + int depth; + unsigned int red_mask; + unsigned int green_mask; + unsigned int blue_mask; + + /* for YUV formats only */ + unsigned int y_sample_bits; + unsigned int u_sample_bits; + unsigned int v_sample_bits; + unsigned int horz_y_period; + unsigned int horz_u_period; + unsigned int horz_v_period; + unsigned int vert_y_period; + unsigned int vert_u_period; + unsigned int vert_v_period; + char component_order[32]; + int scanline_order; +} XF86ImageRec, *XF86ImagePtr; + + +typedef struct { + ScrnInfoPtr pScrn; + int id; + unsigned short width, height; + int *pitches; /* bytes */ + int *offsets; /* in bytes from start of framebuffer */ + DevUnion devPrivate; +} XF86SurfaceRec, *XF86SurfacePtr; + + +typedef int (* PutVideoFuncPtr)( ScrnInfoPtr pScrn, + short vid_x, short vid_y, short drw_x, short drw_y, + short vid_w, short vid_h, short drw_w, short drw_h, + RegionPtr clipBoxes, pointer data, DrawablePtr pDraw ); +typedef int (* PutStillFuncPtr)( ScrnInfoPtr pScrn, + short vid_x, short vid_y, short drw_x, short drw_y, + short vid_w, short vid_h, short drw_w, short drw_h, + RegionPtr clipBoxes, pointer data, DrawablePtr pDraw ); +typedef int (* GetVideoFuncPtr)( ScrnInfoPtr pScrn, + short vid_x, short vid_y, short drw_x, short drw_y, + short vid_w, short vid_h, short drw_w, short drw_h, + RegionPtr clipBoxes, pointer data, DrawablePtr pDraw ); +typedef int (* GetStillFuncPtr)( ScrnInfoPtr pScrn, + short vid_x, short vid_y, short drw_x, short drw_y, + short vid_w, short vid_h, short drw_w, short drw_h, + RegionPtr clipBoxes, pointer data, DrawablePtr pDraw ); +typedef void (* StopVideoFuncPtr)(ScrnInfoPtr pScrn, pointer data, Bool Exit); +typedef int (* SetPortAttributeFuncPtr)(ScrnInfoPtr pScrn, Atom attribute, + INT32 value, pointer data); +typedef int (* GetPortAttributeFuncPtr)(ScrnInfoPtr pScrn, Atom attribute, + INT32 *value, pointer data); +typedef void (* QueryBestSizeFuncPtr)(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); +typedef int (* PutImageFuncPtr)( 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 image, unsigned char* buf, short width, short height, Bool Sync, + RegionPtr clipBoxes, pointer data, DrawablePtr pDraw ); +typedef int (* ReputImageFuncPtr)( 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, + RegionPtr clipBoxes, pointer data, DrawablePtr pDraw ); +typedef int (*QueryImageAttributesFuncPtr)(ScrnInfoPtr pScrn, + int image, unsigned short *width, unsigned short *height, + int *pitches, int *offsets); +typedef void (*ClipNotifyFuncPtr)(ScrnInfoPtr pScrn, pointer data, + WindowPtr window, int dx, int dy); + +typedef enum { + XV_OFF, + XV_PENDING, + XV_ON +} XvStatus; + +/*** this is what the driver needs to fill out ***/ + +typedef struct { + int id; + char *name; + unsigned short width, height; + XvRationalRec rate; +} XF86VideoEncodingRec, *XF86VideoEncodingPtr; + +typedef struct { + char depth; + short class; +} XF86VideoFormatRec, *XF86VideoFormatPtr; + +typedef struct { + int flags; + int min_value; + int max_value; + char *name; +} XF86AttributeRec, *XF86AttributePtr; + +typedef struct { + unsigned int type; + int flags; + char *name; + int nEncodings; + XF86VideoEncodingPtr pEncodings; + int nFormats; + XF86VideoFormatPtr pFormats; + int nPorts; + DevUnion *pPortPrivates; + int nAttributes; + XF86AttributePtr pAttributes; + int nImages; + XF86ImagePtr pImages; + PutVideoFuncPtr PutVideo; + PutStillFuncPtr PutStill; + GetVideoFuncPtr GetVideo; + GetStillFuncPtr GetStill; + StopVideoFuncPtr StopVideo; + SetPortAttributeFuncPtr SetPortAttribute; + GetPortAttributeFuncPtr GetPortAttribute; + QueryBestSizeFuncPtr QueryBestSize; + PutImageFuncPtr PutImage; + ReputImageFuncPtr ReputImage; /* image/still */ + QueryImageAttributesFuncPtr QueryImageAttributes; + ClipNotifyFuncPtr ClipNotify; +} XF86VideoAdaptorRec, *XF86VideoAdaptorPtr; + +typedef struct { + XF86ImagePtr image; + int flags; + int (*alloc_surface)(ScrnInfoPtr pScrn, + int id, + unsigned short width, + unsigned short height, + XF86SurfacePtr surface); + int (*free_surface)(XF86SurfacePtr surface); + int (*display) (XF86SurfacePtr surface, + short vid_x, short vid_y, + short drw_x, short drw_y, + short vid_w, short vid_h, + short drw_w, short drw_h, + RegionPtr clipBoxes); + int (*stop) (XF86SurfacePtr surface); + int (*getAttribute) (ScrnInfoPtr pScrn, Atom attr, INT32 *value); + int (*setAttribute) (ScrnInfoPtr pScrn, Atom attr, INT32 value); + int max_width; + int max_height; + int num_attributes; + XF86AttributePtr attributes; +} XF86OffscreenImageRec, *XF86OffscreenImagePtr; + +extern _X_EXPORT Bool +xf86XVScreenInit( + ScreenPtr pScreen, + XF86VideoAdaptorPtr *Adaptors, + int num +); + +typedef int (* xf86XVInitGenericAdaptorPtr)(ScrnInfoPtr pScrn, + XF86VideoAdaptorPtr **Adaptors); + +extern _X_EXPORT int +xf86XVRegisterGenericAdaptorDriver( + xf86XVInitGenericAdaptorPtr InitFunc +); + +extern _X_EXPORT int +xf86XVListGenericAdaptors( + ScrnInfoPtr pScrn, + XF86VideoAdaptorPtr **Adaptors +); + +extern _X_EXPORT Bool +xf86XVRegisterOffscreenImages( + ScreenPtr pScreen, + XF86OffscreenImagePtr images, + int num +); + +extern _X_EXPORT XF86OffscreenImagePtr +xf86XVQueryOffscreenImages( + ScreenPtr pScreen, + int *num +); + +extern _X_EXPORT XF86VideoAdaptorPtr xf86XVAllocateVideoAdaptorRec(ScrnInfoPtr pScrn); + +extern _X_EXPORT void xf86XVFreeVideoAdaptorRec(XF86VideoAdaptorPtr ptr); + +extern _X_EXPORT void +xf86XVFillKeyHelper (ScreenPtr pScreen, CARD32 key, RegionPtr clipboxes); + +extern _X_EXPORT void +xf86XVFillKeyHelperDrawable (DrawablePtr pDraw, CARD32 key, RegionPtr clipboxes); + +extern _X_EXPORT void +xf86XVFillKeyHelperPort (DrawablePtr pDraw, pointer data, CARD32 key, RegionPtr clipboxes, Bool fillEverything); + +extern _X_EXPORT Bool +xf86XVClipVideoHelper( + BoxPtr dst, + INT32 *xa, + INT32 *xb, + INT32 *ya, + INT32 *yb, + RegionPtr reg, + INT32 width, + INT32 height +); + +extern _X_EXPORT void +xf86XVCopyYUV12ToPacked( + const void *srcy, + const void *srcv, + const void *srcu, + void *dst, + int srcPitchy, + int srcPitchuv, + int dstPitch, + int h, + int w +); + +extern _X_EXPORT void +xf86XVCopyPacked( + const void *src, + void *dst, + int srcPitch, + int dstPitch, + int h, + int w +); + +extern _X_EXPORT DevPrivateKey (*XvGetScreenKeyProc)(void); +extern _X_EXPORT unsigned long (*XvGetRTPortProc)(void); +extern _X_EXPORT int (*XvScreenInitProc)(ScreenPtr); + +#endif /* _XF86XV_H_ */ diff --git a/hw/xfree86/common/xf86xvmc.c b/hw/xfree86/common/xf86xvmc.c new file mode 100644 index 0000000..e6464a5 --- /dev/null +++ b/hw/xfree86/common/xf86xvmc.c @@ -0,0 +1,232 @@ + +/* + * Copyright (c) 2001-2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "scrnintstr.h" +#include "resource.h" +#include "dixstruct.h" + +#include "xvmodproc.h" + +#include "xf86xvpriv.h" +#include "xf86xvmc.h" + +XvMCScreenInitProcPtr XvMCScreenInitProc = NULL; + + +typedef struct { + CloseScreenProcPtr CloseScreen; + int num_adaptors; + XF86MCAdaptorPtr *adaptors; + XvMCAdaptorPtr dixinfo; +} xf86XvMCScreenRec, *xf86XvMCScreenPtr; + +static DevPrivateKeyRec XF86XvMCScreenKeyRec; +#define XF86XvMCScreenKey (&XF86XvMCScreenKeyRec) + +#define XF86XVMC_GET_PRIVATE(pScreen) (xf86XvMCScreenPtr) \ + dixLookupPrivate(&(pScreen)->devPrivates, XF86XvMCScreenKey) + + +static int +xf86XvMCCreateContext ( + XvPortPtr pPort, + XvMCContextPtr pContext, + int *num_priv, + CARD32 **priv +) +{ + xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pContext->pScreen); + ScrnInfoPtr pScrn = xf86Screens[pContext->pScreen->myNum]; + + pContext->port_priv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + + return (*pScreenPriv->adaptors[pContext->adapt_num]->CreateContext)( + pScrn, pContext, num_priv, priv); +} + +static void +xf86XvMCDestroyContext ( XvMCContextPtr pContext) +{ + xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pContext->pScreen); + ScrnInfoPtr pScrn = xf86Screens[pContext->pScreen->myNum]; + + (*pScreenPriv->adaptors[pContext->adapt_num]->DestroyContext)( + pScrn, pContext); +} + +static int +xf86XvMCCreateSurface ( + XvMCSurfacePtr pSurface, + int *num_priv, + CARD32 **priv +) +{ + XvMCContextPtr pContext = pSurface->context; + xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pContext->pScreen); + ScrnInfoPtr pScrn = xf86Screens[pContext->pScreen->myNum]; + + return (*pScreenPriv->adaptors[pContext->adapt_num]->CreateSurface)( + pScrn, pSurface, num_priv, priv); +} + +static void +xf86XvMCDestroySurface (XvMCSurfacePtr pSurface) +{ + XvMCContextPtr pContext = pSurface->context; + xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pContext->pScreen); + ScrnInfoPtr pScrn = xf86Screens[pContext->pScreen->myNum]; + + (*pScreenPriv->adaptors[pContext->adapt_num]->DestroySurface)( + pScrn, pSurface); +} + +static int +xf86XvMCCreateSubpicture ( + XvMCSubpicturePtr pSubpicture, + int *num_priv, + CARD32 **priv +) +{ + XvMCContextPtr pContext = pSubpicture->context; + xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pContext->pScreen); + ScrnInfoPtr pScrn = xf86Screens[pContext->pScreen->myNum]; + + return (*pScreenPriv->adaptors[pContext->adapt_num]->CreateSubpicture)( + pScrn, pSubpicture, num_priv, priv); +} + +static void +xf86XvMCDestroySubpicture (XvMCSubpicturePtr pSubpicture) +{ + XvMCContextPtr pContext = pSubpicture->context; + xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pContext->pScreen); + ScrnInfoPtr pScrn = xf86Screens[pContext->pScreen->myNum]; + + (*pScreenPriv->adaptors[pContext->adapt_num]->DestroySubpicture)( + pScrn, pSubpicture); +} + + +static Bool +xf86XvMCCloseScreen (int i, ScreenPtr pScreen) +{ + xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pScreen); + + pScreen->CloseScreen = pScreenPriv->CloseScreen; + + free(pScreenPriv->dixinfo); + free(pScreenPriv); + + return (*pScreen->CloseScreen)(i, pScreen); +} + +Bool xf86XvMCScreenInit( + ScreenPtr pScreen, + int num_adaptors, + XF86MCAdaptorPtr *adaptors +) +{ + XvMCAdaptorPtr pAdapt; + xf86XvMCScreenPtr pScreenPriv; + XvScreenPtr pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, + XF86XvScreenKey); + int i, j; + + if(!XvMCScreenInitProc) return FALSE; + + if(!(pAdapt = malloc(sizeof(XvMCAdaptorRec) * num_adaptors))) + return FALSE; + + if (!dixRegisterPrivateKey(&XF86XvMCScreenKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + if(!(pScreenPriv = malloc(sizeof(xf86XvMCScreenRec)))) { + free(pAdapt); + return FALSE; + } + + dixSetPrivate(&pScreen->devPrivates, XF86XvMCScreenKey, pScreenPriv); + + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = xf86XvMCCloseScreen; + + pScreenPriv->num_adaptors = num_adaptors; + pScreenPriv->adaptors = adaptors; + pScreenPriv->dixinfo = pAdapt; + + for(i = 0; i < num_adaptors; i++) { + pAdapt[i].xv_adaptor = NULL; + for(j = 0; j < pxvs->nAdaptors; j++) { + if(!strcmp((*adaptors)->name, pxvs->pAdaptors[j].name)) { + pAdapt[i].xv_adaptor = &(pxvs->pAdaptors[j]); + break; + } + } + if(!pAdapt[i].xv_adaptor) { + /* no adaptor by that name */ + free(pAdapt); + return FALSE; + } + pAdapt[i].num_surfaces = (*adaptors)->num_surfaces; + pAdapt[i].surfaces = (XvMCSurfaceInfoPtr*)((*adaptors)->surfaces); + pAdapt[i].num_subpictures = (*adaptors)->num_subpictures; + pAdapt[i].subpictures = (XvImagePtr*)((*adaptors)->subpictures); + pAdapt[i].CreateContext = xf86XvMCCreateContext; + pAdapt[i].DestroyContext = xf86XvMCDestroyContext; + pAdapt[i].CreateSurface = xf86XvMCCreateSurface; + pAdapt[i].DestroySurface = xf86XvMCDestroySurface; + pAdapt[i].CreateSubpicture = xf86XvMCCreateSubpicture; + pAdapt[i].DestroySubpicture = xf86XvMCDestroySubpicture; + adaptors++; + } + + if(Success != (*XvMCScreenInitProc)(pScreen, num_adaptors, pAdapt)) + return FALSE; + + return TRUE; +} + +XF86MCAdaptorPtr xf86XvMCCreateAdaptorRec (void) +{ + return calloc(1, sizeof(XF86MCAdaptorRec)); +} + +void xf86XvMCDestroyAdaptorRec(XF86MCAdaptorPtr adaptor) +{ + free(adaptor); +} diff --git a/hw/xfree86/common/xf86xvmc.h b/hw/xfree86/common/xf86xvmc.h new file mode 100644 index 0000000..902b4f8 --- /dev/null +++ b/hw/xfree86/common/xf86xvmc.h @@ -0,0 +1,166 @@ + +/* + * Copyright (c) 2001 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +#ifndef _XF86XVMC_H +#define _XF86XVMC_H + +#include "xvmcext.h" +#include "xf86xv.h" + +typedef struct { + int num_xvimages; + int *xvimage_ids; /* reference the subpictures in the XF86MCAdaptorRec */ +} XF86MCImageIDList; + +typedef struct { + int surface_type_id; /* Driver generated. Must be unique on the port */ + int chroma_format; + int color_description; /* no longer used */ + unsigned short max_width; + unsigned short max_height; + unsigned short subpicture_max_width; + unsigned short subpicture_max_height; + int mc_type; + int flags; + XF86MCImageIDList *compatible_subpictures; /* can be null, if none */ +} XF86MCSurfaceInfoRec, *XF86MCSurfaceInfoPtr; + + +/* + xf86XvMCCreateContextProc + + DIX will fill everything out in the context except the driver_priv. + The port_priv holds the private data specified for the port when + Xv was initialized by the driver. + The driver may store whatever it wants in driver_priv and edit + the width, height and flags. If the driver wants to return something + to the client it can allocate space in priv and specify the number + of 32 bit words in num_priv. This must be dynamically allocated + space because DIX will free it after it passes it to the client. +*/ + + +typedef int (*xf86XvMCCreateContextProcPtr) ( + ScrnInfoPtr pScrn, + XvMCContextPtr context, + int *num_priv, + CARD32 **priv +); + +typedef void (*xf86XvMCDestroyContextProcPtr) ( + ScrnInfoPtr pScrn, + XvMCContextPtr context +); + +/* + xf86XvMCCreateSurfaceProc + + DIX will fill everything out in the surface except the driver_priv. + The driver may store whatever it wants in driver_priv. The driver + may pass data back to the client in the same manner as the + xf86XvMCCreateContextProc. +*/ + + +typedef int (*xf86XvMCCreateSurfaceProcPtr) ( + ScrnInfoPtr pScrn, + XvMCSurfacePtr surface, + int *num_priv, + CARD32 **priv +); + +typedef void (*xf86XvMCDestroySurfaceProcPtr) ( + ScrnInfoPtr pScrn, + XvMCSurfacePtr surface +); + +/* + xf86XvMCCreateSubpictureProc + + DIX will fill everything out in the subpicture except the driver_priv, + num_palette_entries, entry_bytes and component_order. The driver may + store whatever it wants in driver_priv and edit the width and height. + If it is a paletted subpicture the driver needs to fill out the + num_palette_entries, entry_bytes and component_order. These are + not communicated to the client until the time the surface is + created. + + The driver may pass data back to the client in the same manner as the + xf86XvMCCreateContextProc. +*/ + + +typedef int (*xf86XvMCCreateSubpictureProcPtr) ( + ScrnInfoPtr pScrn, + XvMCSubpicturePtr subpicture, + int *num_priv, + CARD32 **priv +); + +typedef void (*xf86XvMCDestroySubpictureProcPtr) ( + ScrnInfoPtr pScrn, + XvMCSubpicturePtr subpicture +); + + +typedef struct { + char *name; + int num_surfaces; + XF86MCSurfaceInfoPtr *surfaces; + int num_subpictures; + XF86ImagePtr *subpictures; + xf86XvMCCreateContextProcPtr CreateContext; + xf86XvMCDestroyContextProcPtr DestroyContext; + xf86XvMCCreateSurfaceProcPtr CreateSurface; + xf86XvMCDestroySurfaceProcPtr DestroySurface; + xf86XvMCCreateSubpictureProcPtr CreateSubpicture; + xf86XvMCDestroySubpictureProcPtr DestroySubpicture; +} XF86MCAdaptorRec, *XF86MCAdaptorPtr; + +/* + xf86XvMCScreenInit + + Unlike Xv, the adaptor data is not copied from this structure. + This structure's data is used so it must stick around for the + life of the server. Note that it's an array of pointers not + an array of structures. +*/ + +extern _X_EXPORT Bool xf86XvMCScreenInit( + ScreenPtr pScreen, + int num_adaptors, + XF86MCAdaptorPtr *adaptors +); + +extern _X_EXPORT XF86MCAdaptorPtr xf86XvMCCreateAdaptorRec (void); +extern _X_EXPORT void xf86XvMCDestroyAdaptorRec(XF86MCAdaptorPtr adaptor); + +typedef int (*XvMCScreenInitProcPtr)(ScreenPtr, int, XvMCAdaptorPtr); +extern _X_EXPORT XvMCScreenInitProcPtr XvMCScreenInitProc; + +#endif /* _XF86XVMC_H */ diff --git a/hw/xfree86/common/xf86xvpriv.h b/hw/xfree86/common/xf86xvpriv.h new file mode 100644 index 0000000..2a459f1 --- /dev/null +++ b/hw/xfree86/common/xf86xvpriv.h @@ -0,0 +1,88 @@ + +/* + * Copyright (c) 2003 by The XFree86 Project, Inc. + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +#ifndef _XF86XVPRIV_H_ +#define _XF86XVPRIV_H_ + +#include "xf86xv.h" +#include "privates.h" + +/*** These are DDX layer privates ***/ + +extern _X_EXPORT DevPrivateKey XF86XvScreenKey; + +typedef struct { + DestroyWindowProcPtr DestroyWindow; + ClipNotifyProcPtr ClipNotify; + WindowExposuresProcPtr WindowExposures; + PostValidateTreeProcPtr PostValidateTree; + void (*AdjustFrame)(int, int, int, int); + Bool (*EnterVT)(int, int); + void (*LeaveVT)(int, int); + xf86ModeSetProc *ModeSet; +} XF86XVScreenRec, *XF86XVScreenPtr; + +typedef struct { + int flags; + PutVideoFuncPtr PutVideo; + PutStillFuncPtr PutStill; + GetVideoFuncPtr GetVideo; + GetStillFuncPtr GetStill; + StopVideoFuncPtr StopVideo; + SetPortAttributeFuncPtr SetPortAttribute; + GetPortAttributeFuncPtr GetPortAttribute; + QueryBestSizeFuncPtr QueryBestSize; + PutImageFuncPtr PutImage; + ReputImageFuncPtr ReputImage; + QueryImageAttributesFuncPtr QueryImageAttributes; + ClipNotifyFuncPtr ClipNotify; +} XvAdaptorRecPrivate, *XvAdaptorRecPrivatePtr; + +typedef struct { + ScrnInfoPtr pScrn; + DrawablePtr pDraw; + unsigned char type; + unsigned int subWindowMode; + RegionPtr clientClip; + RegionPtr ckeyFilled; + RegionPtr pCompositeClip; + Bool FreeCompositeClip; + XvAdaptorRecPrivatePtr AdaptorRec; + XvStatus isOn; + Bool clipChanged; + int vid_x, vid_y, vid_w, vid_h; + int drw_x, drw_y, drw_w, drw_h; + DevUnion DevPriv; +} XvPortRecPrivate, *XvPortRecPrivatePtr; + +typedef struct _XF86XVWindowRec{ + XvPortRecPrivatePtr PortRec; + struct _XF86XVWindowRec *next; +} XF86XVWindowRec, *XF86XVWindowPtr; + +#endif /* _XF86XVPRIV_H_ */ diff --git a/hw/xfree86/common/xisb.c b/hw/xfree86/common/xisb.c new file mode 100644 index 0000000..e4c8bf2 --- /dev/null +++ b/hw/xfree86/common/xisb.c @@ -0,0 +1,174 @@ +/* + * Copyright (c) 1997 Metro Link Incorporated + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE X CONSORTIUM 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 Metro Link shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from Metro Link. + * + */ + +/* + X Input Serial Buffer routines for use in any XInput driver that accesses + a serial device. +*/ + + +/***************************************************************************** + * Standard Headers + ****************************************************************************/ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <misc.h> +#include <xf86.h> +#include <xf86_OSproc.h> +#include <xf86_OSlib.h> +#include <xf86Xinput.h> +#include "xisb.h" + +/***************************************************************************** + * Local Headers + ****************************************************************************/ + +/***************************************************************************** + * Variables without includable headers + ****************************************************************************/ + +/***************************************************************************** + * Local Variables + ****************************************************************************/ + +/***************************************************************************** + * Function Definitions + ****************************************************************************/ + +XISBuffer * +XisbNew (int fd, ssize_t size) +{ + XISBuffer *b; + + b = malloc(sizeof (XISBuffer)); + if (!b) + return NULL; + b->buf = malloc((sizeof (unsigned char) * size)); + if (!b->buf) + { + free(b); + return NULL; + } + + b->fd = fd; + b->trace = 0; + b->block_duration = 0; + b->current = 1; /* force it to be past the end to trigger initial read */ + b->end = 0; + b->buffer_size = size; + return b; +} + +void +XisbFree (XISBuffer *b) +{ + free(b->buf); + free(b); +} + +int +XisbRead (XISBuffer *b) +{ + int ret; + + if (b->current >= b->end) + { + if (b->block_duration >= 0) + { + if (xf86WaitForInput (b->fd, b->block_duration) < 1) + return -1; + } + else + { + /* + * automatically clear it so if XisbRead is called in a loop + * the next call will make sure there is data with select and + * thus prevent a blocking read + */ + b->block_duration = 0; + } + + ret = xf86ReadSerial (b->fd, b->buf, b->buffer_size); + switch (ret) + { + case 0: + return -1; /* timeout */ + case -1: + return -2; /* error */ + default: + b->end = ret; + b->current = 0; + break; + } + } + if (b->trace) + ErrorF ("read 0x%02x (%c)\n", b->buf[b->current], + isprint(b->buf[b->current])?b->buf[b->current]:'.'); + + return b->buf[b->current++]; +} + +/* the only purpose of this function is to provide output tracing */ +ssize_t +XisbWrite (XISBuffer *b, unsigned char *msg, ssize_t len) +{ + if (b->trace) + { + int i = 0; + for (i = 0; i < len; i++) + ErrorF ("\t\twrote 0x%02x (%c)\n", msg[i], msg[i]); + } + return (xf86WriteSerial (b->fd, msg, len)); +} + +/* turn tracing of this buffer on (1) or off (0) */ +void +XisbTrace (XISBuffer *b, int trace) +{ + b->trace = trace; +} + +/* + * specify a block_duration of -1 when you know the buffer's fd is ready to + * read. After a read, it is automatically set to 0 so that the next read + * will use check to select for data and prevent a block. + * It is the caller's responsibility to set the block_duration to -1 if it + * knows that there is data to read (because the main select loop triggered + * the read) and want's to avoid the unnecessary overhead of the select call + * + * a zero or positive block duration will cause the select to block for the + * give duration in usecs. + */ + +void +XisbBlockDuration (XISBuffer *b, int block_duration) +{ + b->block_duration = block_duration; +} diff --git a/hw/xfree86/common/xisb.h b/hw/xfree86/common/xisb.h new file mode 100644 index 0000000..bacfde1 --- /dev/null +++ b/hw/xfree86/common/xisb.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 1997 Metro Link Incorporated + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE X CONSORTIUM 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 Metro Link shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from Metro Link. + * + */ + +#ifndef _xisb_H_ +#define _xisb_H_ + +#include <unistd.h> + +/****************************************************************************** + * Definitions + * structs, typedefs, #defines, enums + *****************************************************************************/ + +typedef struct _XISBuffer +{ + int fd; + int trace; + int block_duration; + ssize_t current; /* bytes read */ + ssize_t end; + ssize_t buffer_size; + unsigned char *buf; +} XISBuffer; + +/****************************************************************************** + * Declarations + * variables: use xisb_LOC in front + * of globals. + * put locals in the .c file. + *****************************************************************************/ +extern _X_EXPORT XISBuffer * XisbNew (int fd, ssize_t size); +extern _X_EXPORT void XisbFree (XISBuffer *b); +extern _X_EXPORT int XisbRead (XISBuffer *b); +extern _X_EXPORT ssize_t XisbWrite (XISBuffer *b, unsigned char *msg, ssize_t len); +extern _X_EXPORT void XisbTrace (XISBuffer *b, int trace); +extern _X_EXPORT void XisbBlockDuration (XISBuffer *b, int block_duration); + +/* + * DO NOT PUT ANYTHING AFTER THIS ENDIF + */ +#endif diff --git a/hw/xfree86/common/xorgHelper.c b/hw/xfree86/common/xorgHelper.c new file mode 100644 index 0000000..7a8e516 --- /dev/null +++ b/hw/xfree86/common/xorgHelper.c @@ -0,0 +1,23 @@ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <X11/X.h> +#include "os.h" +#include "servermd.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "propertyst.h" +#include "gcstruct.h" +#include "loaderProcs.h" +#include "xf86.h" +#include "xf86Priv.h" +#include "xorgVersion.h" + + +CARD32 +xorgGetVersion(void) +{ + return XORG_VERSION_CURRENT; +} diff --git a/hw/xfree86/common/xorgVersion.h b/hw/xfree86/common/xorgVersion.h new file mode 100644 index 0000000..f627e87 --- /dev/null +++ b/hw/xfree86/common/xorgVersion.h @@ -0,0 +1,49 @@ + +/* + * Copyright (c) 2004, X.Org Foundation + * + * 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, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +#ifndef XORG_VERSION_H +# define XORG_VERSION_H + +# ifndef XORG_VERSION_CURRENT +# error +# endif + +# define XORG_VERSION_NUMERIC(major,minor,patch,snap,dummy) \ + (((major) * 10000000) + ((minor) * 100000) + ((patch) * 1000) + snap) + +# define XORG_GET_MAJOR_VERSION(vers) ((vers) / 10000000) +# define XORG_GET_MINOR_VERSION(vers) (((vers) % 10000000) / 100000) +# define XORG_GET_PATCH_VERSION(vers) (((vers) % 100000) / 1000) +# define XORG_GET_SNAP_VERSION(vers) ((vers) % 1000) + +# define XORG_VERSION_MAJOR XORG_GET_MAJOR_VERSION(XORG_VERSION_CURRENT) +# define XORG_VERSION_MINOR XORG_GET_MINOR_VERSION(XORG_VERSION_CURRENT) +# define XORG_VERSION_PATCH XORG_GET_PATCH_VERSION(XORG_VERSION_CURRENT) +# define XORG_VERSION_SNAP XORG_GET_SNAP_VERSION(XORG_VERSION_CURRENT) + +#endif |