diff options
Diffstat (limited to 'xorg-server/hw/xfree86')
-rw-r--r-- | xorg-server/hw/xfree86/common/xf86Init.c | 2994 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/common/xf86VidMode.c | 2 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/common/xf86xv.c | 210 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/common/xf86xv.h | 3 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/common/xf86xvpriv.h | 6 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/dri2/dri2.c | 2 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/fbdevhw/fbdevhw.c | 56 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/int10/helper_exec.c | 1466 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/modes/xf86Crtc.c | 6563 |
9 files changed, 5646 insertions, 5656 deletions
diff --git a/xorg-server/hw/xfree86/common/xf86Init.c b/xorg-server/hw/xfree86/common/xf86Init.c index a1fda54cd..e017d9dce 100644 --- a/xorg-server/hw/xfree86/common/xf86Init.c +++ b/xorg-server/hw/xfree86/common/xf86Init.c @@ -1,1497 +1,1497 @@ -/* - * 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); - - /* Call the PreInit function for each input device instance. */ - 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') - 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; -} +/*
+ * 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')
+ 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/xorg-server/hw/xfree86/common/xf86VidMode.c b/xorg-server/hw/xfree86/common/xf86VidMode.c index 591c338b1..eb29fd09e 100644 --- a/xorg-server/hw/xfree86/common/xf86VidMode.c +++ b/xorg-server/hw/xfree86/common/xf86VidMode.c @@ -634,7 +634,7 @@ VidModeSetModeValue(pointer mode, int valtyp, int val) vidMonitorValue
VidModeGetMonitorValue(pointer monitor, int valtyp, int indx)
{
- vidMonitorValue ret;
+ vidMonitorValue ret = { NULL, };
switch (valtyp) {
case VIDMODE_MON_VENDOR:
diff --git a/xorg-server/hw/xfree86/common/xf86xv.c b/xorg-server/hw/xfree86/common/xf86xv.c index 9f62a8397..8115075b3 100644 --- a/xorg-server/hw/xfree86/common/xf86xv.c +++ b/xorg-server/hw/xfree86/common/xf86xv.c @@ -97,8 +97,11 @@ static int xf86XVQueryImageAttributes(ClientPtr, XvPortPtr, XvImagePtr, 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);
@@ -280,10 +283,9 @@ xf86XVScreenInit( pScrn = xf86Screens[pScreen->myNum];
- ScreenPriv->videoGC = NULL; /* for the helper */
-
ScreenPriv->DestroyWindow = pScreen->DestroyWindow;
ScreenPriv->WindowExposures = pScreen->WindowExposures;
+ ScreenPriv->PostValidateTree = PostValidateTreeUndefined;
ScreenPriv->ClipNotify = pScreen->ClipNotify;
ScreenPriv->EnterVT = pScrn->EnterVT;
ScreenPriv->LeaveVT = pScrn->LeaveVT;
@@ -333,6 +335,8 @@ xf86XVFreeAdaptor(XvAdaptorPtr pAdaptor) RegionDestroy(pPriv->clientClip);
if(pPriv->pCompositeClip && pPriv->FreeCompositeClip)
RegionDestroy(pPriv->pCompositeClip);
+ if (pPriv->ckeyFilled)
+ RegionDestroy(pPriv->ckeyFilled);
free(pPriv);
}
}
@@ -1018,7 +1022,6 @@ static void xf86XVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
{
XF86XVWindowPtr winPriv, prevPriv = NULL;
-
winPriv = GET_XF86XV_WINDOW(pWin);
while(winPriv) {
@@ -1035,6 +1038,11 @@ xf86XVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv) winPriv = winPriv->next;
}
portPriv->pDraw = NULL;
+ if (portPriv->ckeyFilled) {
+ RegionDestroy(portPriv->ckeyFilled);
+ portPriv->ckeyFilled = NULL;
+ }
+ portPriv->clipChanged = FALSE;
}
static void
@@ -1069,7 +1077,7 @@ xf86XVReputOrStopPort(XvPortRecPrivatePtr pPriv, }
static void
-xf86XVReputOrStopAllPorts(ScrnInfoPtr pScrn)
+xf86XVReputOrStopAllPorts(ScrnInfoPtr pScrn, Bool onlyChanged)
{
ScreenPtr pScreen = pScrn->pScreen;
XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
@@ -1087,6 +1095,9 @@ xf86XVReputOrStopAllPorts(ScrnInfoPtr pScrn) if (pPriv->isOn == XV_OFF || !pWin)
continue;
+ if (onlyChanged && !pPriv->clipChanged)
+ continue;
+
visible = pWin->visibility == VisibilityUnobscured ||
pWin->visibility == VisibilityPartiallyObscured;
@@ -1098,6 +1109,8 @@ xf86XVReputOrStopAllPorts(ScrnInfoPtr pScrn) visible = FALSE;
xf86XVReputOrStopPort(pPriv, pWin, visible);
+
+ pPriv->clipChanged = FALSE;
}
}
}
@@ -1123,9 +1136,6 @@ xf86XVDestroyWindow(WindowPtr pWin) pPriv->pDraw = NULL;
tmp = WinPriv;
- if(WinPriv->pGC) {
- FreeGC(WinPriv->pGC, 0);
- }
WinPriv = WinPriv->next;
free(tmp);
}
@@ -1139,6 +1149,29 @@ xf86XVDestroyWindow(WindowPtr pWin) 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)
@@ -1170,12 +1203,28 @@ xf86XVWindowExposures(WindowPtr pWin, RegionPtr reg1, RegionPtr reg2) 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)
{
@@ -1185,9 +1234,6 @@ xf86XVClipNotify(WindowPtr pWin, int dx, int dy) XvPortRecPrivatePtr pPriv;
while(WinPriv) {
- Bool visible = pWin->visibility == VisibilityUnobscured ||
- pWin->visibility == VisibilityPartiallyObscured;
-
pPriv = WinPriv->PortRec;
if(pPriv->pCompositeClip && pPriv->FreeCompositeClip)
@@ -1199,15 +1245,14 @@ xf86XVClipNotify(WindowPtr pWin, int dx, int dy) (*pPriv->AdaptorRec->ClipNotify)(pPriv->pScrn, pPriv->DevPriv.ptr,
pWin, dx, dy);
- /*
- * Stop and remove still/images if
- * ReputImage isn't supported.
- */
- if (!pPriv->type && !pPriv->AdaptorRec->ReputImage)
- visible = FALSE;
+ pPriv->clipChanged = TRUE;
+
+ if (ScreenPriv->PostValidateTree == PostValidateTreeUndefined) {
+ ScreenPriv->PostValidateTree = pScreen->PostValidateTree;
+ pScreen->PostValidateTree = xf86XVPostValidateTree;
+ }
WinPriv = WinPriv->next;
- xf86XVReputOrStopPort(pPriv, pWin, visible);
}
if(ScreenPriv->ClipNotify) {
@@ -1232,11 +1277,6 @@ xf86XVCloseScreen(int i, ScreenPtr pScreen) if(!ScreenPriv) return TRUE;
- if(ScreenPriv->videoGC) {
- FreeGC(ScreenPriv->videoGC, 0);
- ScreenPriv->videoGC = NULL;
- }
-
pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
pScreen->WindowExposures = ScreenPriv->WindowExposures;
pScreen->ClipNotify = ScreenPriv->ClipNotify;
@@ -1345,7 +1385,7 @@ xf86XVAdjustFrame(int index, int x, int y, int flags) pScrn->AdjustFrame = xf86XVAdjustFrame;
}
- xf86XVReputOrStopAllPorts(pScrn);
+ xf86XVReputOrStopAllPorts(pScrn, FALSE);
}
static void
@@ -1366,7 +1406,7 @@ xf86XVModeSet(ScrnInfoPtr pScrn) pScrn->ModeSet = xf86XVModeSet;
}
- xf86XVReputOrStopAllPorts(pScrn);
+ xf86XVReputOrStopAllPorts(pScrn, FALSE);
}
/**** XvAdaptorRec fields ****/
@@ -1869,92 +1909,92 @@ xf86XVQueryImageAttributes( format->id, width, height, pitches, offsets);
}
-
void
-xf86XVFillKeyHelperDrawable (DrawablePtr pDraw, CARD32 key, RegionPtr clipboxes)
+xf86XVFillKeyHelperDrawable (DrawablePtr pDraw, CARD32 key, RegionPtr fillboxes)
{
ScreenPtr pScreen = pDraw->pScreen;
- WindowPtr pWin = (WindowPtr)pDraw;
- XF86XVWindowPtr pPriv = GET_XF86XV_WINDOW(pWin);
- GCPtr pGC = NULL;
- BoxPtr pbox = RegionRects(clipboxes);
- int i, nbox = RegionNumRects(clipboxes);
- xRectangle *rects;
-
- if(!xf86Screens[pScreen->myNum]->vtSema) return;
-
- if(pPriv)
- pGC = pPriv->pGC;
-
- if(!pGC) {
- int status;
- XID pval[2];
- pval[0] = key;
- pval[1] = IncludeInferiors;
- pGC = CreateGC(pDraw, GCForeground | GCSubwindowMode, pval, &status,
- (XID)0, serverClient);
- if(!pGC) return;
- ValidateGC(pDraw, pGC);
- if (pPriv) pPriv->pGC = pGC;
- } else if (key != pGC->fgPixel){
- ChangeGCVal val;
- val.val = key;
- ChangeGC(NullClient, pGC, GCForeground, &val);
- ValidateGC(pDraw, pGC);
- }
-
- RegionTranslate(clipboxes, -pDraw->x, -pDraw->y);
-
- rects = malloc(nbox * sizeof(xRectangle));
-
- for(i = 0; i < nbox; i++, pbox++) {
- rects[i].x = pbox->x1;
- rects[i].y = pbox->y1;
- rects[i].width = pbox->x2 - pbox->x1;
- rects[i].height = pbox->y2 - pbox->y1;
- }
-
- (*pGC->ops->PolyFillRect)(pDraw, pGC, nbox, rects);
-
- if (!pPriv) FreeGC(pGC, 0);
-
- free(rects);
-}
-
-void
-xf86XVFillKeyHelper (ScreenPtr pScreen, CARD32 key, RegionPtr clipboxes)
-{
- DrawablePtr root = &pScreen->root->drawable;
ChangeGCVal pval[2];
- BoxPtr pbox = RegionRects(clipboxes);
- int i, nbox = RegionNumRects(clipboxes);
+ BoxPtr pbox = RegionRects(fillboxes);
+ int i, nbox = RegionNumRects(fillboxes);
xRectangle *rects;
GCPtr gc;
if(!xf86Screens[pScreen->myNum]->vtSema) return;
- gc = GetScratchGC(root->depth, pScreen);
+ gc = GetScratchGC(pDraw->depth, pScreen);
pval[0].val = key;
pval[1].val = IncludeInferiors;
(void) ChangeGC(NullClient, gc, GCForeground|GCSubwindowMode, pval);
- ValidateGC(root, gc);
+ ValidateGC(pDraw, gc);
rects = malloc(nbox * sizeof(xRectangle));
for(i = 0; i < nbox; i++, pbox++)
{
- rects[i].x = pbox->x1;
- rects[i].y = pbox->y1;
+ 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)(root, gc, nbox, rects);
+ (*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
diff --git a/xorg-server/hw/xfree86/common/xf86xv.h b/xorg-server/hw/xfree86/common/xf86xv.h index 25f3e4ad3..08e5c790d 100644 --- a/xorg-server/hw/xfree86/common/xf86xv.h +++ b/xorg-server/hw/xfree86/common/xf86xv.h @@ -244,6 +244,9 @@ 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,
diff --git a/xorg-server/hw/xfree86/common/xf86xvpriv.h b/xorg-server/hw/xfree86/common/xf86xvpriv.h index 35d72ca9c..7eb46e51f 100644 --- a/xorg-server/hw/xfree86/common/xf86xvpriv.h +++ b/xorg-server/hw/xfree86/common/xf86xvpriv.h @@ -40,10 +40,10 @@ typedef struct { DestroyWindowProcPtr DestroyWindow;
ClipNotifyProcPtr ClipNotify;
WindowExposuresProcPtr WindowExposures;
+ PostValidateTreeProcPtr PostValidateTree;
void (*AdjustFrame)(int, int, int, int);
Bool (*EnterVT)(int, int);
void (*LeaveVT)(int, int);
- GCPtr videoGC;
xf86ModeSetProc *ModeSet;
} XF86XVScreenRec, *XF86XVScreenPtr;
@@ -69,11 +69,12 @@ typedef struct { unsigned char type;
unsigned int subWindowMode;
RegionPtr clientClip;
+ RegionPtr ckeyFilled;
RegionPtr pCompositeClip;
Bool FreeCompositeClip;
XvAdaptorRecPrivatePtr AdaptorRec;
XvStatus isOn;
- Bool moved;
+ Bool clipChanged;
int vid_x, vid_y, vid_w, vid_h;
int drw_x, drw_y, drw_w, drw_h;
DevUnion DevPriv;
@@ -82,7 +83,6 @@ typedef struct { typedef struct _XF86XVWindowRec{
XvPortRecPrivatePtr PortRec;
struct _XF86XVWindowRec *next;
- GCPtr pGC;
} XF86XVWindowRec, *XF86XVWindowPtr;
#endif /* _XF86XVPRIV_H_ */
diff --git a/xorg-server/hw/xfree86/dri2/dri2.c b/xorg-server/hw/xfree86/dri2/dri2.c index aba2202d6..7d6f772d7 100644 --- a/xorg-server/hw/xfree86/dri2/dri2.c +++ b/xorg-server/hw/xfree86/dri2/dri2.c @@ -403,7 +403,7 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height, && (pDraw->height == pPriv->height)
&& (pPriv->serialNumber == DRI2DrawableSerial(pDraw));
- buffers = malloc((count + 1) * sizeof(buffers[0]));
+ buffers = calloc((count + 1), sizeof(buffers[0]));
for (i = 0; i < count; i++) {
const unsigned attachment = *(attachments++);
diff --git a/xorg-server/hw/xfree86/fbdevhw/fbdevhw.c b/xorg-server/hw/xfree86/fbdevhw/fbdevhw.c index 49d0bd044..ef69d58bc 100644 --- a/xorg-server/hw/xfree86/fbdevhw/fbdevhw.c +++ b/xorg-server/hw/xfree86/fbdevhw/fbdevhw.c @@ -264,14 +264,7 @@ fbdev_open_pci(struct pci_device * pPci, char **namep) {
struct fb_fix_screeninfo fix;
char filename[256];
- int fd,i,j;
-
-
- /* There are two ways to that we can determine which fb device is
- * associated with this PCI device. The more modern way is to look in
- * the sysfs directory for the PCI device for a file named
- * "graphics/fb*"
- */
+ int fd, i;
for (i = 0; i < 8; i++) {
sprintf(filename,
@@ -304,55 +297,10 @@ fbdev_open_pci(struct pci_device * pPci, char **namep) }
}
-
- /* The other way is to examine the resources associated with each fb
- * device and see if there is a match with the PCI device. This technique
- * has some problems on certain mixed 64-bit / 32-bit architectures.
- * There is a flaw in the fb_fix_screeninfo structure in that it only
- * returns the low 32-bits of the address of the resources associated with
- * a device. However, on a mixed architecture the base addresses of PCI
- * devices, even for 32-bit applications, may be higher than 0x0f0000000.
- */
-
- for (i = 0; i < 8; i++) {
- sprintf(filename,"/dev/fb%d",i);
- if (-1 == (fd = open(filename,O_RDWR,0))) {
- xf86DrvMsg(-1, X_WARNING,
- "open %s: %s\n", filename, strerror(errno));
- continue;
- }
- if (-1 == ioctl(fd,FBIOGET_FSCREENINFO,(void*)&fix)) {
- close(fd);
- continue;
- }
- for (j = 0; j < 6; j++) {
- const pciaddr_t res_start = pPci->regions[j].base_addr;
- const pciaddr_t res_end = res_start + pPci->regions[j].size;
-
- if ((0 != fix.smem_len &&
- (pciaddr_t) fix.smem_start >= res_start &&
- (pciaddr_t) fix.smem_start < res_end) ||
- (0 != fix.mmio_len &&
- (pciaddr_t) fix.mmio_start >= res_start &&
- (pciaddr_t) fix.mmio_start < res_end))
- break;
- }
- if (j == 6) {
- close(fd);
- continue;
- }
- if (namep) {
- *namep = xnfalloc(16);
- strncpy(*namep,fix.id,16);
- }
- return fd;
- }
-
if (namep)
*namep = NULL;
- xf86DrvMsg(-1, X_ERROR,
- "Unable to find a valid framebuffer device\n");
+ xf86DrvMsg(-1, X_ERROR, "Unable to find a valid framebuffer device\n");
return -1;
}
diff --git a/xorg-server/hw/xfree86/int10/helper_exec.c b/xorg-server/hw/xfree86/int10/helper_exec.c index b9af473b1..1043fcde7 100644 --- a/xorg-server/hw/xfree86/int10/helper_exec.c +++ b/xorg-server/hw/xfree86/int10/helper_exec.c @@ -1,733 +1,733 @@ -/* - * XFree86 int10 module - * execute BIOS int 10h calls in x86 real mode environment - * Copyright 1999 Egbert Eich - * - * Part of this code was inspired by the VBIOS POSTing code in DOSEMU - * developed by the "DOSEMU-Development-Team" - */ - -/* - * To debug port accesses define PRINT_PORT to 1. - * Note! You also have to comment out ioperm() - * in xf86EnableIO(). Otherwise we won't trap - * on PIO. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include <xorg-config.h> -#endif - -#define PRINT_PORT 0 - -#include <unistd.h> - -#include <X11/Xos.h> -#include "xf86.h" -#include "xf86_OSproc.h" -#include "compiler.h" -#define _INT10_PRIVATE -#include "int10Defines.h" -#include "xf86int10.h" -#include "Pci.h" -#ifdef _X86EMU -#include "x86emu/x86emui.h" -#else -#define DEBUG_IO_TRACE() 0 -#endif -#include <pciaccess.h> - -static int pciCfg1in(CARD16 addr, CARD32 *val); -static int pciCfg1out(CARD16 addr, CARD32 val); -static int pciCfg1inw(CARD16 addr, CARD16 *val); -static int pciCfg1outw(CARD16 addr, CARD16 val); -static int pciCfg1inb(CARD16 addr, CARD8 *val); -static int pciCfg1outb(CARD16 addr, CARD8 val); -#if defined (_PC) -static void SetResetBIOSVars(xf86Int10InfoPtr pInt, Bool set); -#endif - -#define REG pInt - -int -setup_int(xf86Int10InfoPtr pInt) -{ - if (pInt != Int10Current) { - if (!MapCurrentInt10(pInt)) - return -1; - Int10Current = pInt; - } - X86_EAX = (CARD32) pInt->ax; - X86_EBX = (CARD32) pInt->bx; - X86_ECX = (CARD32) pInt->cx; - X86_EDX = (CARD32) pInt->dx; - X86_ESI = (CARD32) pInt->si; - X86_EDI = (CARD32) pInt->di; - X86_EBP = (CARD32) pInt->bp; - X86_ESP = 0x1000; X86_SS = pInt->stackseg >> 4; - X86_EIP = 0x0600; X86_CS = 0x0; /* address of 'hlt' */ - X86_DS = 0x40; /* standard pc ds */ - X86_ES = pInt->es; - X86_FS = 0; - X86_GS = 0; - X86_EFLAGS = X86_IF_MASK | X86_IOPL_MASK; -#if defined (_PC) - if (pInt->Flags & SET_BIOS_SCRATCH) - SetResetBIOSVars(pInt, TRUE); -#endif - OsBlockSignals(); - return 0; -} - -void -finish_int(xf86Int10InfoPtr pInt, int sig) -{ - OsReleaseSignals(); - pInt->ax = (CARD32) X86_EAX; - pInt->bx = (CARD32) X86_EBX; - pInt->cx = (CARD32) X86_ECX; - pInt->dx = (CARD32) X86_EDX; - pInt->si = (CARD32) X86_ESI; - pInt->di = (CARD32) X86_EDI; - pInt->es = (CARD16) X86_ES; - pInt->bp = (CARD32) X86_EBP; - pInt->flags = (CARD32) X86_FLAGS; -#if defined (_PC) - if (pInt->Flags & RESTORE_BIOS_SCRATCH) - SetResetBIOSVars(pInt, FALSE); -#endif -} - -/* general software interrupt handler */ -CARD32 -getIntVect(xf86Int10InfoPtr pInt,int num) -{ - return MEM_RW(pInt, num << 2) + (MEM_RW(pInt, (num << 2) + 2) << 4); -} - -void -pushw(xf86Int10InfoPtr pInt, CARD16 val) -{ - X86_ESP -= 2; - MEM_WW(pInt, ((CARD32) X86_SS << 4) + X86_SP, val); -} - -int -run_bios_int(int num, xf86Int10InfoPtr pInt) -{ - CARD32 eflags; -#ifndef _PC - /* check if bios vector is initialized */ - if (MEM_RW(pInt, (num << 2) + 2) == (SYS_BIOS >> 4)) { /* SYS_BIOS_SEG ?*/ - - if (num == 21 && X86_AH == 0x4e) { - xf86DrvMsg(pInt->scrnIndex, X_NOTICE, - "Failing Find-Matching-File on non-PC" - " (int 21, func 4e)\n"); - X86_AX = 2; - SET_FLAG(F_CF); - return 1; - } else { - xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, - "Ignoring int 0x%02x call\n", num); - if (xf86GetVerbosity() > 3) { - dump_registers(pInt); - stack_trace(pInt); - } - return 1; - } - } -#endif -#ifdef PRINT_INT - ErrorF("calling card BIOS at: "); -#endif - eflags = X86_EFLAGS; -#if 0 - eflags = eflags | IF_MASK; - X86_EFLAGS = X86_EFLAGS & ~(VIF_MASK | TF_MASK | IF_MASK | NT_MASK); -#endif - pushw(pInt, eflags); - pushw(pInt, X86_CS); - pushw(pInt, X86_IP); - X86_CS = MEM_RW(pInt, (num << 2) + 2); - X86_IP = MEM_RW(pInt, num << 2); -#ifdef PRINT_INT - ErrorF("0x%x:%lx\n", X86_CS, X86_EIP); -#endif - return 1; -} - -/* Debugging stuff */ -void -dump_code(xf86Int10InfoPtr pInt) -{ - int i; - unsigned long lina = SEG_ADR((CARD32), X86_CS, IP); - - xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3, "code at 0x%8.8lx:\n", lina); - for (i=0; i<0x10; i++) - xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, lina + i)); - xf86ErrorFVerb(3, "\n"); - for (; i<0x20; i++) - xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, lina + i)); - xf86ErrorFVerb(3, "\n"); -} - -void -dump_registers(xf86Int10InfoPtr pInt) -{ - xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3, - "EAX=0x%8.8lx, EBX=0x%8.8lx, ECX=0x%8.8lx, EDX=0x%8.8lx\n", - (unsigned long)X86_EAX, (unsigned long)X86_EBX, - (unsigned long)X86_ECX, (unsigned long)X86_EDX); - xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3, - "ESP=0x%8.8lx, EBP=0x%8.8lx, ESI=0x%8.8lx, EDI=0x%8.8lx\n", - (unsigned long)X86_ESP, (unsigned long)X86_EBP, - (unsigned long)X86_ESI, (unsigned long)X86_EDI); - xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3, - "CS=0x%4.4x, SS=0x%4.4x," - " DS=0x%4.4x, ES=0x%4.4x, FS=0x%4.4x, GS=0x%4.4x\n", - X86_CS, X86_SS, X86_DS, X86_ES, X86_FS, X86_GS); - xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3, - "EIP=0x%8.8lx, EFLAGS=0x%8.8lx\n", - (unsigned long)X86_EIP, (unsigned long)X86_EFLAGS); -} - -void -stack_trace(xf86Int10InfoPtr pInt) -{ - int i = 0; - unsigned long stack = SEG_ADR((CARD32), X86_SS, SP); - unsigned long tail = (CARD32)((X86_SS << 4) + 0x1000); - - if (stack >= tail) return; - - xf86MsgVerb(X_INFO, 3, "stack at 0x%8.8lx:\n", stack); - for (; stack < tail; stack++) { - xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, stack)); - i = (i + 1) % 0x10; - if (!i) - xf86ErrorFVerb(3, "\n"); - } - if (i) - xf86ErrorFVerb(3, "\n"); -} - -int -port_rep_inb(xf86Int10InfoPtr pInt, - CARD16 port, CARD32 base, int d_f, CARD32 count) -{ - register int inc = d_f ? -1 : 1; - CARD32 dst = base; - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" rep_insb(%#x) %ld bytes at %8.8lx %s\n", - port, count, base, d_f ? "up" : "down"); - while (count--) { - MEM_WB(pInt, dst, x_inb(port)); - dst += inc; - } - return dst - base; -} - -int -port_rep_inw(xf86Int10InfoPtr pInt, - CARD16 port, CARD32 base, int d_f, CARD32 count) -{ - register int inc = d_f ? -2 : 2; - CARD32 dst = base; - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" rep_insw(%#x) %ld bytes at %8.8lx %s\n", - port, count, base, d_f ? "up" : "down"); - while (count--) { - MEM_WW(pInt, dst, x_inw(port)); - dst += inc; - } - return dst - base; -} - -int -port_rep_inl(xf86Int10InfoPtr pInt, - CARD16 port, CARD32 base, int d_f, CARD32 count) -{ - register int inc = d_f ? -4 : 4; - CARD32 dst = base; - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" rep_insl(%#x) %ld bytes at %8.8lx %s\n", - port, count, base, d_f ? "up" : "down"); - while (count--) { - MEM_WL(pInt, dst, x_inl(port)); - dst += inc; - } - return dst - base; -} - -int -port_rep_outb(xf86Int10InfoPtr pInt, - CARD16 port, CARD32 base, int d_f, CARD32 count) -{ - register int inc = d_f ? -1 : 1; - CARD32 dst = base; - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" rep_outb(%#x) %ld bytes at %8.8lx %s\n", - port, count, base, d_f ? "up" : "down"); - while (count--) { - x_outb(port, MEM_RB(pInt, dst)); - dst += inc; - } - return dst - base; -} - -int -port_rep_outw(xf86Int10InfoPtr pInt, - CARD16 port, CARD32 base, int d_f, CARD32 count) -{ - register int inc = d_f ? -2 : 2; - CARD32 dst = base; - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" rep_outw(%#x) %ld bytes at %8.8lx %s\n", - port, count, base, d_f ? "up" : "down"); - while (count--) { - x_outw(port, MEM_RW(pInt, dst)); - dst += inc; - } - return dst - base; -} - -int -port_rep_outl(xf86Int10InfoPtr pInt, - CARD16 port, CARD32 base, int d_f, CARD32 count) -{ - register int inc = d_f ? -4 : 4; - CARD32 dst = base; - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" rep_outl(%#x) %ld bytes at %8.8lx %s\n", - port, count, base, d_f ? "up" : "down"); - while (count--) { - x_outl(port, MEM_RL(pInt, dst)); - dst += inc; - } - return dst - base; -} - -CARD8 -x_inb(CARD16 port) -{ - CARD8 val; - - if (port == 0x40) { - Int10Current->inb40time++; - val = (CARD8)(Int10Current->inb40time >> - ((Int10Current->inb40time & 1) << 3)); - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" inb(%#x) = %2.2x\n", port, val); -#ifdef __NOT_YET__ - } else if (port < 0x0100) { /* Don't interfere with mainboard */ - val = 0; - xf86DrvMsgVerb(Int10Current->scrnIndex, X_NOT_IMPLEMENTED, 2, - "inb 0x%4.4x\n", port); - if (xf86GetVerbosity() > 3) { - dump_registers(Int10Current); - stack_trace(Int10Current); - } -#endif /* __NOT_YET__ */ - } else if (!pciCfg1inb(port, &val)) { - val = inb(Int10Current->ioBase + port); - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" inb(%#x) = %2.2x\n", port, val); - } - return val; -} - -CARD16 -x_inw(CARD16 port) -{ - CARD16 val; - - if (port == 0x5c) { - struct timeval tv; - - /* - * Emulate a PC98's timer. Typical resolution is 3.26 usec. - * Approximate this by dividing by 3. - */ - X_GETTIMEOFDAY(&tv); - val = (CARD16)(tv.tv_usec / 3); - } else if (!pciCfg1inw(port, &val)) { - val = inw(Int10Current->ioBase + port); - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" inw(%#x) = %4.4x\n", port, val); - } - return val; -} - -void -x_outb(CARD16 port, CARD8 val) -{ - if ((port == 0x43) && (val == 0)) { - struct timeval tv; - /* - * Emulate a PC's timer 0. Such timers typically have a resolution of - * some .838 usec per tick, but this can only provide 1 usec per tick. - * (Not that this matters much, given inherent emulation delays.) Use - * the bottom bit as a byte select. See inb(0x40) above. - */ - X_GETTIMEOFDAY(&tv); - Int10Current->inb40time = (CARD16)(tv.tv_usec | 1); - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" outb(%#x, %2.2x)\n", port, val); -#ifdef __NOT_YET__ - } else if (port < 0x0100) { /* Don't interfere with mainboard */ - xf86DrvMsgVerb(Int10Current->scrnIndex, X_NOT_IMPLEMENTED, 2, - "outb 0x%4.4x,0x%2.2x\n", port, val); - if (xf86GetVerbosity() > 3) { - dump_registers(Int10Current); - stack_trace(Int10Current); - } -#endif /* __NOT_YET__ */ - } else if (!pciCfg1outb(port, val)) { - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" outb(%#x, %2.2x)\n", port, val); - outb(Int10Current->ioBase + port, val); - } -} - -void -x_outw(CARD16 port, CARD16 val) -{ - - if (!pciCfg1outw(port, val)) { - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" outw(%#x, %4.4x)\n", port, val); - outw(Int10Current->ioBase + port, val); - } -} - -CARD32 -x_inl(CARD16 port) -{ - CARD32 val; - - if (!pciCfg1in(port, &val)) { - val = inl(Int10Current->ioBase + port); - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" inl(%#x) = %8.8lx\n", port, val); - } - return val; -} - -void -x_outl(CARD16 port, CARD32 val) -{ - if (!pciCfg1out(port, val)) { - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" outl(%#x, %8.8lx)\n", port, val); - outl(Int10Current->ioBase + port, val); - } -} - -CARD8 -Mem_rb(CARD32 addr) -{ - return (*Int10Current->mem->rb)(Int10Current, addr); -} - -CARD16 -Mem_rw(CARD32 addr) -{ - return (*Int10Current->mem->rw)(Int10Current, addr); -} - -CARD32 -Mem_rl(CARD32 addr) -{ - return (*Int10Current->mem->rl)(Int10Current, addr); -} - -void -Mem_wb(CARD32 addr, CARD8 val) -{ - (*Int10Current->mem->wb)(Int10Current, addr, val); -} - -void -Mem_ww(CARD32 addr, CARD16 val) -{ - (*Int10Current->mem->ww)(Int10Current, addr, val); -} - -void -Mem_wl(CARD32 addr, CARD32 val) -{ - (*Int10Current->mem->wl)(Int10Current, addr, val); -} - -static CARD32 PciCfg1Addr = 0; - -#define PCI_DOM_FROM_TAG(tag) (((tag) >> 24) & (PCI_DOM_MASK)) -#define PCI_BUS_FROM_TAG(tag) (((tag) >> 16) & (PCI_DOMBUS_MASK)) -#define PCI_DEV_FROM_TAG(tag) (((tag) & 0x0000f800u) >> 11) -#define PCI_FUNC_FROM_TAG(tag) (((tag) & 0x00000700u) >> 8) - -#define PCI_OFFSET(x) ((x) & 0x000000ff) -#define PCI_TAG(x) ((x) & 0x7fffff00) - -static struct pci_device* -pci_device_for_cfg_address (CARD32 addr) -{ - struct pci_device *dev = NULL; - PCITAG tag = PCI_TAG(addr); - struct pci_slot_match slot_match = { - .domain = PCI_DOM_FROM_TAG(tag), - .bus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(tag)), - .dev = PCI_DEV_FROM_TAG(tag), - .func = PCI_FUNC_FROM_TAG(tag), - .match_data = 0 - }; - - struct pci_device_iterator *iter = - pci_slot_match_iterator_create (&slot_match); - - if (iter) - dev = pci_device_next(iter); - - pci_iterator_destroy(iter); - - return dev; -} - -static int -pciCfg1in(CARD16 addr, CARD32 *val) -{ - if (addr == 0xCF8) { - *val = PciCfg1Addr; - return 1; - } - if (addr == 0xCFC) { - pci_device_cfg_read_u32(pci_device_for_cfg_address(PciCfg1Addr), - val, PCI_OFFSET(PciCfg1Addr)); - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" cfg_inl(%#lx) = %8.8lx\n", PciCfg1Addr, *val); - return 1; - } - return 0; -} - -static int -pciCfg1out(CARD16 addr, CARD32 val) -{ - if (addr == 0xCF8) { - PciCfg1Addr = val; - return 1; - } - if (addr == 0xCFC) { - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" cfg_outl(%#lx, %8.8lx)\n", PciCfg1Addr, val); - pci_device_cfg_write_u32(pci_device_for_cfg_address(PciCfg1Addr), - val, PCI_OFFSET(PciCfg1Addr)); - return 1; - } - return 0; -} - -static int -pciCfg1inw(CARD16 addr, CARD16 *val) -{ - int shift; - - if ((addr >= 0xCF8) && (addr <= 0xCFB)) { - shift = (addr - 0xCF8) * 8; - *val = (PciCfg1Addr >> shift) & 0xffff; - return 1; - } - if ((addr >= 0xCFC) && (addr <= 0xCFF)) { - const unsigned offset = addr - 0xCFC; - - pci_device_cfg_read_u16(pci_device_for_cfg_address(PciCfg1Addr), - val, PCI_OFFSET(PciCfg1Addr) + offset); - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" cfg_inw(%#lx) = %4.4x\n", PciCfg1Addr + offset, *val); - return 1; - } - return 0; -} - -static int -pciCfg1outw(CARD16 addr, CARD16 val) -{ - int shift; - - if ((addr >= 0xCF8) && (addr <= 0xCFB)) { - shift = (addr - 0xCF8) * 8; - PciCfg1Addr &= ~(0xffff << shift); - PciCfg1Addr |= ((CARD32) val) << shift; - return 1; - } - if ((addr >= 0xCFC) && (addr <= 0xCFF)) { - const unsigned offset = addr - 0xCFC; - - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" cfg_outw(%#lx, %4.4x)\n", PciCfg1Addr + offset, val); - pci_device_cfg_write_u16(pci_device_for_cfg_address(PciCfg1Addr), - val, PCI_OFFSET(PciCfg1Addr) + offset); - return 1; - } - return 0; -} - -static int -pciCfg1inb(CARD16 addr, CARD8 *val) -{ - int shift; - - if ((addr >= 0xCF8) && (addr <= 0xCFB)) { - shift = (addr - 0xCF8) * 8; - *val = (PciCfg1Addr >> shift) & 0xff; - return 1; - } - if ((addr >= 0xCFC) && (addr <= 0xCFF)) { - const unsigned offset = addr - 0xCFC; - - pci_device_cfg_read_u8(pci_device_for_cfg_address(PciCfg1Addr), - val, PCI_OFFSET(PciCfg1Addr) + offset); - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" cfg_inb(%#lx) = %2.2x\n", PciCfg1Addr + offset, *val); - return 1; - } - return 0; -} - -static int -pciCfg1outb(CARD16 addr, CARD8 val) -{ - int shift; - - if ((addr >= 0xCF8) && (addr <= 0xCFB)) { - shift = (addr - 0xCF8) * 8; - PciCfg1Addr &= ~(0xff << shift); - PciCfg1Addr |= ((CARD32) val) << shift; - return 1; - } - if ((addr >= 0xCFC) && (addr <= 0xCFF)) { - const unsigned offset = addr - 0xCFC; - - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" cfg_outb(%#lx, %2.2x)\n", PciCfg1Addr + offset, val); - pci_device_cfg_write_u8(pci_device_for_cfg_address(PciCfg1Addr), - val, PCI_OFFSET(PciCfg1Addr) + offset); - return 1; - } - return 0; -} - -CARD8 -bios_checksum(const CARD8 *start, int size) -{ - CARD8 sum = 0; - - while (size-- > 0) - sum += *start++; - return sum; -} - -/* - * Lock/Unlock legacy VGA. Some Bioses try to be very clever and make - * an attempt to detect a legacy ISA card. If they find one they might - * act very strange: for example they might configure the card as a - * monochrome card. This might cause some drivers to choke. - * To avoid this we attempt legacy VGA by writing to all know VGA - * disable registers before we call the BIOS initialization and - * restore the original values afterwards. In beween we hold our - * breath. To get to a (possibly exising) ISA card need to disable - * our current PCI card. - */ -/* - * This is just for booting: we just want to catch pure - * legacy vga therefore we don't worry about mmio etc. - * This stuff should really go into vgaHW.c. However then - * the driver would have to load the vga-module prior to - * doing int10. - */ -void -LockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga) -{ - vga->save_msr = inb(pInt->ioBase + 0x03CC); - vga->save_vse = inb(pInt->ioBase + 0x03C3); -#ifndef __ia64__ - vga->save_46e8 = inb(pInt->ioBase + 0x46E8); -#endif - vga->save_pos102 = inb(pInt->ioBase + 0x0102); - outb(pInt->ioBase + 0x03C2, ~(CARD8)0x03 & vga->save_msr); - outb(pInt->ioBase + 0x03C3, ~(CARD8)0x01 & vga->save_vse); -#ifndef __ia64__ - outb(pInt->ioBase + 0x46E8, ~(CARD8)0x08 & vga->save_46e8); -#endif - outb(pInt->ioBase + 0x0102, ~(CARD8)0x01 & vga->save_pos102); -} - -void -UnlockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga) -{ - outb(pInt->ioBase + 0x0102, vga->save_pos102); -#ifndef __ia64__ - outb(pInt->ioBase + 0x46E8, vga->save_46e8); -#endif - outb(pInt->ioBase + 0x03C3, vga->save_vse); - outb(pInt->ioBase + 0x03C2, vga->save_msr); -} - -#if defined (_PC) -static void -SetResetBIOSVars(xf86Int10InfoPtr pInt, Bool set) -{ - int pagesize = getpagesize(); - unsigned char* base = xf86MapVidMem(pInt->scrnIndex, - VIDMEM_MMIO, 0, pagesize); - int i; - - if (set) { - for (i = BIOS_SCRATCH_OFF; i < BIOS_SCRATCH_END; i++) - MEM_WW(pInt, i, *(base + i)); - } else { - for (i = BIOS_SCRATCH_OFF; i < BIOS_SCRATCH_END; i++) - *(base + i) = MEM_RW(pInt, i); - } - - xf86UnMapVidMem(pInt->scrnIndex,base,pagesize); -} - -void -xf86Int10SaveRestoreBIOSVars(xf86Int10InfoPtr pInt, Bool save) -{ - int pagesize = getpagesize(); - unsigned char* base; - int i; - - if (!xf86IsEntityPrimary(pInt->entityIndex) - || (!save && !pInt->BIOSScratch)) - return; - - base = xf86MapVidMem(pInt->scrnIndex, VIDMEM_MMIO, 0, pagesize); - base += BIOS_SCRATCH_OFF; - if (save) { - if ((pInt->BIOSScratch - = xnfalloc(BIOS_SCRATCH_LEN))) - for (i = 0; i < BIOS_SCRATCH_LEN; i++) - *(((char*)pInt->BIOSScratch + i)) = *(base + i); - } else { - if (pInt->BIOSScratch) { - for (i = 0; i < BIOS_SCRATCH_LEN; i++) - *(base + i) = *(pInt->BIOSScratch + i); - free(pInt->BIOSScratch); - pInt->BIOSScratch = NULL; - } - } - - xf86UnMapVidMem(pInt->scrnIndex,base - BIOS_SCRATCH_OFF ,pagesize); -} -#endif - -xf86Int10InfoPtr -xf86InitInt10(int entityIndex) -{ - return xf86ExtendedInitInt10(entityIndex, 0); -} +/*
+ * XFree86 int10 module
+ * execute BIOS int 10h calls in x86 real mode environment
+ * Copyright 1999 Egbert Eich
+ *
+ * Part of this code was inspired by the VBIOS POSTing code in DOSEMU
+ * developed by the "DOSEMU-Development-Team"
+ */
+
+/*
+ * To debug port accesses define PRINT_PORT to 1.
+ * Note! You also have to comment out ioperm()
+ * in xf86EnableIO(). Otherwise we won't trap
+ * on PIO.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#define PRINT_PORT 0
+
+#include <unistd.h>
+
+#include <X11/Xos.h>
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "compiler.h"
+#define _INT10_PRIVATE
+#include "int10Defines.h"
+#include "xf86int10.h"
+#include "Pci.h"
+#ifdef _X86EMU
+#include "x86emu/x86emui.h"
+#else
+#define DEBUG_IO_TRACE() 0
+#endif
+#include <pciaccess.h>
+
+static int pciCfg1in(CARD16 addr, CARD32 *val);
+static int pciCfg1out(CARD16 addr, CARD32 val);
+static int pciCfg1inw(CARD16 addr, CARD16 *val);
+static int pciCfg1outw(CARD16 addr, CARD16 val);
+static int pciCfg1inb(CARD16 addr, CARD8 *val);
+static int pciCfg1outb(CARD16 addr, CARD8 val);
+#if defined (_PC)
+static void SetResetBIOSVars(xf86Int10InfoPtr pInt, Bool set);
+#endif
+
+#define REG pInt
+
+int
+setup_int(xf86Int10InfoPtr pInt)
+{
+ if (pInt != Int10Current) {
+ if (!MapCurrentInt10(pInt))
+ return -1;
+ Int10Current = pInt;
+ }
+ X86_EAX = (CARD32) pInt->ax;
+ X86_EBX = (CARD32) pInt->bx;
+ X86_ECX = (CARD32) pInt->cx;
+ X86_EDX = (CARD32) pInt->dx;
+ X86_ESI = (CARD32) pInt->si;
+ X86_EDI = (CARD32) pInt->di;
+ X86_EBP = (CARD32) pInt->bp;
+ X86_ESP = 0x1000; X86_SS = pInt->stackseg >> 4;
+ X86_EIP = 0x0600; X86_CS = 0x0; /* address of 'hlt' */
+ X86_DS = 0x40; /* standard pc ds */
+ X86_ES = pInt->es;
+ X86_FS = 0;
+ X86_GS = 0;
+ X86_EFLAGS = X86_IF_MASK | X86_IOPL_MASK;
+#if defined (_PC)
+ if (pInt->Flags & SET_BIOS_SCRATCH)
+ SetResetBIOSVars(pInt, TRUE);
+#endif
+ OsBlockSignals();
+ return 0;
+}
+
+void
+finish_int(xf86Int10InfoPtr pInt, int sig)
+{
+ OsReleaseSignals();
+ pInt->ax = (CARD32) X86_EAX;
+ pInt->bx = (CARD32) X86_EBX;
+ pInt->cx = (CARD32) X86_ECX;
+ pInt->dx = (CARD32) X86_EDX;
+ pInt->si = (CARD32) X86_ESI;
+ pInt->di = (CARD32) X86_EDI;
+ pInt->es = (CARD16) X86_ES;
+ pInt->bp = (CARD32) X86_EBP;
+ pInt->flags = (CARD32) X86_FLAGS;
+#if defined (_PC)
+ if (pInt->Flags & RESTORE_BIOS_SCRATCH)
+ SetResetBIOSVars(pInt, FALSE);
+#endif
+}
+
+/* general software interrupt handler */
+CARD32
+getIntVect(xf86Int10InfoPtr pInt,int num)
+{
+ return MEM_RW(pInt, num << 2) + (MEM_RW(pInt, (num << 2) + 2) << 4);
+}
+
+void
+pushw(xf86Int10InfoPtr pInt, CARD16 val)
+{
+ X86_ESP -= 2;
+ MEM_WW(pInt, ((CARD32) X86_SS << 4) + X86_SP, val);
+}
+
+int
+run_bios_int(int num, xf86Int10InfoPtr pInt)
+{
+ CARD32 eflags;
+#ifndef _PC
+ /* check if bios vector is initialized */
+ if (MEM_RW(pInt, (num << 2) + 2) == (SYS_BIOS >> 4)) { /* SYS_BIOS_SEG ?*/
+
+ if (num == 21 && X86_AH == 0x4e) {
+ xf86DrvMsg(pInt->scrnIndex, X_NOTICE,
+ "Failing Find-Matching-File on non-PC"
+ " (int 21, func 4e)\n");
+ X86_AX = 2;
+ SET_FLAG(F_CF);
+ return 1;
+ } else {
+ xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2,
+ "Ignoring int 0x%02x call\n", num);
+ if (xf86GetVerbosity() > 3) {
+ dump_registers(pInt);
+ stack_trace(pInt);
+ }
+ return 1;
+ }
+ }
+#endif
+#ifdef PRINT_INT
+ ErrorF("calling card BIOS at: ");
+#endif
+ eflags = X86_EFLAGS;
+#if 0
+ eflags = eflags | IF_MASK;
+ X86_EFLAGS = X86_EFLAGS & ~(VIF_MASK | TF_MASK | IF_MASK | NT_MASK);
+#endif
+ pushw(pInt, eflags);
+ pushw(pInt, X86_CS);
+ pushw(pInt, X86_IP);
+ X86_CS = MEM_RW(pInt, (num << 2) + 2);
+ X86_IP = MEM_RW(pInt, num << 2);
+#ifdef PRINT_INT
+ ErrorF("0x%x:%lx\n", X86_CS, X86_EIP);
+#endif
+ return 1;
+}
+
+/* Debugging stuff */
+void
+dump_code(xf86Int10InfoPtr pInt)
+{
+ int i;
+ unsigned long lina = SEG_ADR((CARD32), X86_CS, IP);
+
+ xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3, "code at 0x%8.8lx:\n", lina);
+ for (i=0; i<0x10; i++)
+ xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, lina + i));
+ xf86ErrorFVerb(3, "\n");
+ for (; i<0x20; i++)
+ xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, lina + i));
+ xf86ErrorFVerb(3, "\n");
+}
+
+void
+dump_registers(xf86Int10InfoPtr pInt)
+{
+ xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3,
+ "EAX=0x%8.8lx, EBX=0x%8.8lx, ECX=0x%8.8lx, EDX=0x%8.8lx\n",
+ (unsigned long)X86_EAX, (unsigned long)X86_EBX,
+ (unsigned long)X86_ECX, (unsigned long)X86_EDX);
+ xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3,
+ "ESP=0x%8.8lx, EBP=0x%8.8lx, ESI=0x%8.8lx, EDI=0x%8.8lx\n",
+ (unsigned long)X86_ESP, (unsigned long)X86_EBP,
+ (unsigned long)X86_ESI, (unsigned long)X86_EDI);
+ xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3,
+ "CS=0x%4.4x, SS=0x%4.4x,"
+ " DS=0x%4.4x, ES=0x%4.4x, FS=0x%4.4x, GS=0x%4.4x\n",
+ X86_CS, X86_SS, X86_DS, X86_ES, X86_FS, X86_GS);
+ xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3,
+ "EIP=0x%8.8lx, EFLAGS=0x%8.8lx\n",
+ (unsigned long)X86_EIP, (unsigned long)X86_EFLAGS);
+}
+
+void
+stack_trace(xf86Int10InfoPtr pInt)
+{
+ int i = 0;
+ unsigned long stack = SEG_ADR((CARD32), X86_SS, SP);
+ unsigned long tail = (CARD32)((X86_SS << 4) + 0x1000);
+
+ if (stack >= tail) return;
+
+ xf86MsgVerb(X_INFO, 3, "stack at 0x%8.8lx:\n", stack);
+ for (; stack < tail; stack++) {
+ xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, stack));
+ i = (i + 1) % 0x10;
+ if (!i)
+ xf86ErrorFVerb(3, "\n");
+ }
+ if (i)
+ xf86ErrorFVerb(3, "\n");
+}
+
+int
+port_rep_inb(xf86Int10InfoPtr pInt,
+ CARD16 port, CARD32 base, int d_f, CARD32 count)
+{
+ register int inc = d_f ? -1 : 1;
+ CARD32 dst = base;
+ if (PRINT_PORT && DEBUG_IO_TRACE())
+ ErrorF(" rep_insb(%#x) %ld bytes at %8.8lx %s\n",
+ port, count, base, d_f ? "up" : "down");
+ while (count--) {
+ MEM_WB(pInt, dst, x_inb(port));
+ dst += inc;
+ }
+ return dst - base;
+}
+
+int
+port_rep_inw(xf86Int10InfoPtr pInt,
+ CARD16 port, CARD32 base, int d_f, CARD32 count)
+{
+ register int inc = d_f ? -2 : 2;
+ CARD32 dst = base;
+ if (PRINT_PORT && DEBUG_IO_TRACE())
+ ErrorF(" rep_insw(%#x) %ld bytes at %8.8lx %s\n",
+ port, count, base, d_f ? "up" : "down");
+ while (count--) {
+ MEM_WW(pInt, dst, x_inw(port));
+ dst += inc;
+ }
+ return dst - base;
+}
+
+int
+port_rep_inl(xf86Int10InfoPtr pInt,
+ CARD16 port, CARD32 base, int d_f, CARD32 count)
+{
+ register int inc = d_f ? -4 : 4;
+ CARD32 dst = base;
+ if (PRINT_PORT && DEBUG_IO_TRACE())
+ ErrorF(" rep_insl(%#x) %ld bytes at %8.8lx %s\n",
+ port, count, base, d_f ? "up" : "down");
+ while (count--) {
+ MEM_WL(pInt, dst, x_inl(port));
+ dst += inc;
+ }
+ return dst - base;
+}
+
+int
+port_rep_outb(xf86Int10InfoPtr pInt,
+ CARD16 port, CARD32 base, int d_f, CARD32 count)
+{
+ register int inc = d_f ? -1 : 1;
+ CARD32 dst = base;
+ if (PRINT_PORT && DEBUG_IO_TRACE())
+ ErrorF(" rep_outb(%#x) %ld bytes at %8.8lx %s\n",
+ port, count, base, d_f ? "up" : "down");
+ while (count--) {
+ x_outb(port, MEM_RB(pInt, dst));
+ dst += inc;
+ }
+ return dst - base;
+}
+
+int
+port_rep_outw(xf86Int10InfoPtr pInt,
+ CARD16 port, CARD32 base, int d_f, CARD32 count)
+{
+ register int inc = d_f ? -2 : 2;
+ CARD32 dst = base;
+ if (PRINT_PORT && DEBUG_IO_TRACE())
+ ErrorF(" rep_outw(%#x) %ld bytes at %8.8lx %s\n",
+ port, count, base, d_f ? "up" : "down");
+ while (count--) {
+ x_outw(port, MEM_RW(pInt, dst));
+ dst += inc;
+ }
+ return dst - base;
+}
+
+int
+port_rep_outl(xf86Int10InfoPtr pInt,
+ CARD16 port, CARD32 base, int d_f, CARD32 count)
+{
+ register int inc = d_f ? -4 : 4;
+ CARD32 dst = base;
+ if (PRINT_PORT && DEBUG_IO_TRACE())
+ ErrorF(" rep_outl(%#x) %ld bytes at %8.8lx %s\n",
+ port, count, base, d_f ? "up" : "down");
+ while (count--) {
+ x_outl(port, MEM_RL(pInt, dst));
+ dst += inc;
+ }
+ return dst - base;
+}
+
+CARD8
+x_inb(CARD16 port)
+{
+ CARD8 val;
+
+ if (port == 0x40) {
+ Int10Current->inb40time++;
+ val = (CARD8)(Int10Current->inb40time >>
+ ((Int10Current->inb40time & 1) << 3));
+ if (PRINT_PORT && DEBUG_IO_TRACE())
+ ErrorF(" inb(%#x) = %2.2x\n", port, val);
+#ifdef __NOT_YET__
+ } else if (port < 0x0100) { /* Don't interfere with mainboard */
+ val = 0;
+ xf86DrvMsgVerb(Int10Current->scrnIndex, X_NOT_IMPLEMENTED, 2,
+ "inb 0x%4.4x\n", port);
+ if (xf86GetVerbosity() > 3) {
+ dump_registers(Int10Current);
+ stack_trace(Int10Current);
+ }
+#endif /* __NOT_YET__ */
+ } else if (!pciCfg1inb(port, &val)) {
+ val = inb(Int10Current->ioBase + port);
+ if (PRINT_PORT && DEBUG_IO_TRACE())
+ ErrorF(" inb(%#x) = %2.2x\n", port, val);
+ }
+ return val;
+}
+
+CARD16
+x_inw(CARD16 port)
+{
+ CARD16 val;
+
+ if (port == 0x5c) {
+ struct timeval tv;
+
+ /*
+ * Emulate a PC98's timer. Typical resolution is 3.26 usec.
+ * Approximate this by dividing by 3.
+ */
+ X_GETTIMEOFDAY(&tv);
+ val = (CARD16)(tv.tv_usec / 3);
+ } else if (!pciCfg1inw(port, &val)) {
+ val = inw(Int10Current->ioBase + port);
+ if (PRINT_PORT && DEBUG_IO_TRACE())
+ ErrorF(" inw(%#x) = %4.4x\n", port, val);
+ }
+ return val;
+}
+
+void
+x_outb(CARD16 port, CARD8 val)
+{
+ if ((port == 0x43) && (val == 0)) {
+ struct timeval tv;
+ /*
+ * Emulate a PC's timer 0. Such timers typically have a resolution of
+ * some .838 usec per tick, but this can only provide 1 usec per tick.
+ * (Not that this matters much, given inherent emulation delays.) Use
+ * the bottom bit as a byte select. See inb(0x40) above.
+ */
+ X_GETTIMEOFDAY(&tv);
+ Int10Current->inb40time = (CARD16)(tv.tv_usec | 1);
+ if (PRINT_PORT && DEBUG_IO_TRACE())
+ ErrorF(" outb(%#x, %2.2x)\n", port, val);
+#ifdef __NOT_YET__
+ } else if (port < 0x0100) { /* Don't interfere with mainboard */
+ xf86DrvMsgVerb(Int10Current->scrnIndex, X_NOT_IMPLEMENTED, 2,
+ "outb 0x%4.4x,0x%2.2x\n", port, val);
+ if (xf86GetVerbosity() > 3) {
+ dump_registers(Int10Current);
+ stack_trace(Int10Current);
+ }
+#endif /* __NOT_YET__ */
+ } else if (!pciCfg1outb(port, val)) {
+ if (PRINT_PORT && DEBUG_IO_TRACE())
+ ErrorF(" outb(%#x, %2.2x)\n", port, val);
+ outb(Int10Current->ioBase + port, val);
+ }
+}
+
+void
+x_outw(CARD16 port, CARD16 val)
+{
+
+ if (!pciCfg1outw(port, val)) {
+ if (PRINT_PORT && DEBUG_IO_TRACE())
+ ErrorF(" outw(%#x, %4.4x)\n", port, val);
+ outw(Int10Current->ioBase + port, val);
+ }
+}
+
+CARD32
+x_inl(CARD16 port)
+{
+ CARD32 val;
+
+ if (!pciCfg1in(port, &val)) {
+ val = inl(Int10Current->ioBase + port);
+ if (PRINT_PORT && DEBUG_IO_TRACE())
+ ErrorF(" inl(%#x) = %8.8lx\n", port, val);
+ }
+ return val;
+}
+
+void
+x_outl(CARD16 port, CARD32 val)
+{
+ if (!pciCfg1out(port, val)) {
+ if (PRINT_PORT && DEBUG_IO_TRACE())
+ ErrorF(" outl(%#x, %8.8lx)\n", port, val);
+ outl(Int10Current->ioBase + port, val);
+ }
+}
+
+CARD8
+Mem_rb(CARD32 addr)
+{
+ return (*Int10Current->mem->rb)(Int10Current, addr);
+}
+
+CARD16
+Mem_rw(CARD32 addr)
+{
+ return (*Int10Current->mem->rw)(Int10Current, addr);
+}
+
+CARD32
+Mem_rl(CARD32 addr)
+{
+ return (*Int10Current->mem->rl)(Int10Current, addr);
+}
+
+void
+Mem_wb(CARD32 addr, CARD8 val)
+{
+ (*Int10Current->mem->wb)(Int10Current, addr, val);
+}
+
+void
+Mem_ww(CARD32 addr, CARD16 val)
+{
+ (*Int10Current->mem->ww)(Int10Current, addr, val);
+}
+
+void
+Mem_wl(CARD32 addr, CARD32 val)
+{
+ (*Int10Current->mem->wl)(Int10Current, addr, val);
+}
+
+static CARD32 PciCfg1Addr = 0;
+
+#define PCI_DOM_FROM_TAG(tag) (((tag) >> 24) & (PCI_DOM_MASK))
+#define PCI_BUS_FROM_TAG(tag) (((tag) >> 16) & (PCI_DOMBUS_MASK))
+#define PCI_DEV_FROM_TAG(tag) (((tag) & 0x0000f800u) >> 11)
+#define PCI_FUNC_FROM_TAG(tag) (((tag) & 0x00000700u) >> 8)
+
+#define PCI_OFFSET(x) ((x) & 0x000000ff)
+#define PCI_TAG(x) ((x) & 0x7fffff00)
+
+static struct pci_device*
+pci_device_for_cfg_address (CARD32 addr)
+{
+ struct pci_device *dev = NULL;
+ PCITAG tag = PCI_TAG(addr);
+ struct pci_slot_match slot_match = {
+ .domain = PCI_DOM_FROM_TAG(tag),
+ .bus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(tag)),
+ .dev = PCI_DEV_FROM_TAG(tag),
+ .func = PCI_FUNC_FROM_TAG(tag),
+ .match_data = 0
+ };
+
+ struct pci_device_iterator *iter =
+ pci_slot_match_iterator_create (&slot_match);
+
+ if (iter)
+ dev = pci_device_next(iter);
+
+ pci_iterator_destroy(iter);
+
+ return dev;
+}
+
+static int
+pciCfg1in(CARD16 addr, CARD32 *val)
+{
+ if (addr == 0xCF8) {
+ *val = PciCfg1Addr;
+ return 1;
+ }
+ if (addr == 0xCFC) {
+ pci_device_cfg_read_u32(pci_device_for_cfg_address(PciCfg1Addr),
+ (uint32_t *)val, PCI_OFFSET(PciCfg1Addr));
+ if (PRINT_PORT && DEBUG_IO_TRACE())
+ ErrorF(" cfg_inl(%#lx) = %8.8lx\n", PciCfg1Addr, *val);
+ return 1;
+ }
+ return 0;
+}
+
+static int
+pciCfg1out(CARD16 addr, CARD32 val)
+{
+ if (addr == 0xCF8) {
+ PciCfg1Addr = val;
+ return 1;
+ }
+ if (addr == 0xCFC) {
+ if (PRINT_PORT && DEBUG_IO_TRACE())
+ ErrorF(" cfg_outl(%#lx, %8.8lx)\n", PciCfg1Addr, val);
+ pci_device_cfg_write_u32(pci_device_for_cfg_address(PciCfg1Addr),
+ val, PCI_OFFSET(PciCfg1Addr));
+ return 1;
+ }
+ return 0;
+}
+
+static int
+pciCfg1inw(CARD16 addr, CARD16 *val)
+{
+ int shift;
+
+ if ((addr >= 0xCF8) && (addr <= 0xCFB)) {
+ shift = (addr - 0xCF8) * 8;
+ *val = (PciCfg1Addr >> shift) & 0xffff;
+ return 1;
+ }
+ if ((addr >= 0xCFC) && (addr <= 0xCFF)) {
+ const unsigned offset = addr - 0xCFC;
+
+ pci_device_cfg_read_u16(pci_device_for_cfg_address(PciCfg1Addr),
+ val, PCI_OFFSET(PciCfg1Addr) + offset);
+ if (PRINT_PORT && DEBUG_IO_TRACE())
+ ErrorF(" cfg_inw(%#lx) = %4.4x\n", PciCfg1Addr + offset, *val);
+ return 1;
+ }
+ return 0;
+}
+
+static int
+pciCfg1outw(CARD16 addr, CARD16 val)
+{
+ int shift;
+
+ if ((addr >= 0xCF8) && (addr <= 0xCFB)) {
+ shift = (addr - 0xCF8) * 8;
+ PciCfg1Addr &= ~(0xffff << shift);
+ PciCfg1Addr |= ((CARD32) val) << shift;
+ return 1;
+ }
+ if ((addr >= 0xCFC) && (addr <= 0xCFF)) {
+ const unsigned offset = addr - 0xCFC;
+
+ if (PRINT_PORT && DEBUG_IO_TRACE())
+ ErrorF(" cfg_outw(%#lx, %4.4x)\n", PciCfg1Addr + offset, val);
+ pci_device_cfg_write_u16(pci_device_for_cfg_address(PciCfg1Addr),
+ val, PCI_OFFSET(PciCfg1Addr) + offset);
+ return 1;
+ }
+ return 0;
+}
+
+static int
+pciCfg1inb(CARD16 addr, CARD8 *val)
+{
+ int shift;
+
+ if ((addr >= 0xCF8) && (addr <= 0xCFB)) {
+ shift = (addr - 0xCF8) * 8;
+ *val = (PciCfg1Addr >> shift) & 0xff;
+ return 1;
+ }
+ if ((addr >= 0xCFC) && (addr <= 0xCFF)) {
+ const unsigned offset = addr - 0xCFC;
+
+ pci_device_cfg_read_u8(pci_device_for_cfg_address(PciCfg1Addr),
+ val, PCI_OFFSET(PciCfg1Addr) + offset);
+ if (PRINT_PORT && DEBUG_IO_TRACE())
+ ErrorF(" cfg_inb(%#lx) = %2.2x\n", PciCfg1Addr + offset, *val);
+ return 1;
+ }
+ return 0;
+}
+
+static int
+pciCfg1outb(CARD16 addr, CARD8 val)
+{
+ int shift;
+
+ if ((addr >= 0xCF8) && (addr <= 0xCFB)) {
+ shift = (addr - 0xCF8) * 8;
+ PciCfg1Addr &= ~(0xff << shift);
+ PciCfg1Addr |= ((CARD32) val) << shift;
+ return 1;
+ }
+ if ((addr >= 0xCFC) && (addr <= 0xCFF)) {
+ const unsigned offset = addr - 0xCFC;
+
+ if (PRINT_PORT && DEBUG_IO_TRACE())
+ ErrorF(" cfg_outb(%#lx, %2.2x)\n", PciCfg1Addr + offset, val);
+ pci_device_cfg_write_u8(pci_device_for_cfg_address(PciCfg1Addr),
+ val, PCI_OFFSET(PciCfg1Addr) + offset);
+ return 1;
+ }
+ return 0;
+}
+
+CARD8
+bios_checksum(const CARD8 *start, int size)
+{
+ CARD8 sum = 0;
+
+ while (size-- > 0)
+ sum += *start++;
+ return sum;
+}
+
+/*
+ * Lock/Unlock legacy VGA. Some Bioses try to be very clever and make
+ * an attempt to detect a legacy ISA card. If they find one they might
+ * act very strange: for example they might configure the card as a
+ * monochrome card. This might cause some drivers to choke.
+ * To avoid this we attempt legacy VGA by writing to all know VGA
+ * disable registers before we call the BIOS initialization and
+ * restore the original values afterwards. In beween we hold our
+ * breath. To get to a (possibly exising) ISA card need to disable
+ * our current PCI card.
+ */
+/*
+ * This is just for booting: we just want to catch pure
+ * legacy vga therefore we don't worry about mmio etc.
+ * This stuff should really go into vgaHW.c. However then
+ * the driver would have to load the vga-module prior to
+ * doing int10.
+ */
+void
+LockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga)
+{
+ vga->save_msr = inb(pInt->ioBase + 0x03CC);
+ vga->save_vse = inb(pInt->ioBase + 0x03C3);
+#ifndef __ia64__
+ vga->save_46e8 = inb(pInt->ioBase + 0x46E8);
+#endif
+ vga->save_pos102 = inb(pInt->ioBase + 0x0102);
+ outb(pInt->ioBase + 0x03C2, ~(CARD8)0x03 & vga->save_msr);
+ outb(pInt->ioBase + 0x03C3, ~(CARD8)0x01 & vga->save_vse);
+#ifndef __ia64__
+ outb(pInt->ioBase + 0x46E8, ~(CARD8)0x08 & vga->save_46e8);
+#endif
+ outb(pInt->ioBase + 0x0102, ~(CARD8)0x01 & vga->save_pos102);
+}
+
+void
+UnlockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga)
+{
+ outb(pInt->ioBase + 0x0102, vga->save_pos102);
+#ifndef __ia64__
+ outb(pInt->ioBase + 0x46E8, vga->save_46e8);
+#endif
+ outb(pInt->ioBase + 0x03C3, vga->save_vse);
+ outb(pInt->ioBase + 0x03C2, vga->save_msr);
+}
+
+#if defined (_PC)
+static void
+SetResetBIOSVars(xf86Int10InfoPtr pInt, Bool set)
+{
+ int pagesize = getpagesize();
+ unsigned char* base = xf86MapVidMem(pInt->scrnIndex,
+ VIDMEM_MMIO, 0, pagesize);
+ int i;
+
+ if (set) {
+ for (i = BIOS_SCRATCH_OFF; i < BIOS_SCRATCH_END; i++)
+ MEM_WW(pInt, i, *(base + i));
+ } else {
+ for (i = BIOS_SCRATCH_OFF; i < BIOS_SCRATCH_END; i++)
+ *(base + i) = MEM_RW(pInt, i);
+ }
+
+ xf86UnMapVidMem(pInt->scrnIndex,base,pagesize);
+}
+
+void
+xf86Int10SaveRestoreBIOSVars(xf86Int10InfoPtr pInt, Bool save)
+{
+ int pagesize = getpagesize();
+ unsigned char* base;
+ int i;
+
+ if (!xf86IsEntityPrimary(pInt->entityIndex)
+ || (!save && !pInt->BIOSScratch))
+ return;
+
+ base = xf86MapVidMem(pInt->scrnIndex, VIDMEM_MMIO, 0, pagesize);
+ base += BIOS_SCRATCH_OFF;
+ if (save) {
+ if ((pInt->BIOSScratch
+ = xnfalloc(BIOS_SCRATCH_LEN)))
+ for (i = 0; i < BIOS_SCRATCH_LEN; i++)
+ *(((char*)pInt->BIOSScratch + i)) = *(base + i);
+ } else {
+ if (pInt->BIOSScratch) {
+ for (i = 0; i < BIOS_SCRATCH_LEN; i++)
+ *(base + i) = *(pInt->BIOSScratch + i);
+ free(pInt->BIOSScratch);
+ pInt->BIOSScratch = NULL;
+ }
+ }
+
+ xf86UnMapVidMem(pInt->scrnIndex,base - BIOS_SCRATCH_OFF ,pagesize);
+}
+#endif
+
+xf86Int10InfoPtr
+xf86InitInt10(int entityIndex)
+{
+ return xf86ExtendedInitInt10(entityIndex, 0);
+}
diff --git a/xorg-server/hw/xfree86/modes/xf86Crtc.c b/xorg-server/hw/xfree86/modes/xf86Crtc.c index 47d3ad14c..d721b131f 100644 --- a/xorg-server/hw/xfree86/modes/xf86Crtc.c +++ b/xorg-server/hw/xfree86/modes/xf86Crtc.c @@ -1,3282 +1,3281 @@ -/* - * Copyright © 2006 Keith Packard - * Copyright © 2008 Red Hat, 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 the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS 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> -#else -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#endif - -#include <stddef.h> -#include <string.h> -#include <stdio.h> - -#include "xf86.h" -#include "xf86DDC.h" -#include "xf86Crtc.h" -#include "xf86Modes.h" -#include "xf86Priv.h" -#include "xf86RandR12.h" -#include "X11/extensions/render.h" -#include "X11/extensions/dpmsconst.h" -#include "X11/Xatom.h" -#include "picturestr.h" - -#include "xf86xv.h" - -#define NO_OUTPUT_DEFAULT_WIDTH 1024 -#define NO_OUTPUT_DEFAULT_HEIGHT 768 -/* - * Initialize xf86CrtcConfig structure - */ - -int xf86CrtcConfigPrivateIndex = -1; - -void -xf86CrtcConfigInit (ScrnInfoPtr scrn, - const xf86CrtcConfigFuncsRec *funcs) -{ - xf86CrtcConfigPtr config; - - if (xf86CrtcConfigPrivateIndex == -1) - xf86CrtcConfigPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); - config = xnfcalloc (1, sizeof (xf86CrtcConfigRec)); - - config->funcs = funcs; - - scrn->privates[xf86CrtcConfigPrivateIndex].ptr = config; -} - -void -xf86CrtcSetSizeRange (ScrnInfoPtr scrn, - int minWidth, int minHeight, - int maxWidth, int maxHeight) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - - config->minWidth = minWidth; - config->minHeight = minHeight; - config->maxWidth = maxWidth; - config->maxHeight = maxHeight; -} - -void -xf86CrtcSetScanoutFormats(ScrnInfoPtr scrn, - int num_formats, - xf86CrtcScanoutFormat *formats) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - - config->num_scanout_formats = num_formats; - config->scanout_formats = formats; -} - -/* - * Crtc functions - */ -xf86CrtcPtr -xf86CrtcCreate (ScrnInfoPtr scrn, - const xf86CrtcFuncsRec *funcs) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - xf86CrtcPtr crtc, *crtcs; - - crtc = calloc(sizeof (xf86CrtcRec), 1); - if (!crtc) - return NULL; - crtc->version = XF86_CRTC_VERSION; - crtc->scrn = scrn; - crtc->funcs = funcs; -#ifdef RANDR_12_INTERFACE - crtc->randr_crtc = NULL; -#endif - crtc->rotation = RR_Rotate_0; - crtc->desiredRotation = RR_Rotate_0; - pixman_transform_init_identity (&crtc->crtc_to_framebuffer); - pixman_f_transform_init_identity (&crtc->f_crtc_to_framebuffer); - pixman_f_transform_init_identity (&crtc->f_framebuffer_to_crtc); - pixman_f_transform_init_identity (&crtc->f_screen_to_crtc); - pixman_f_transform_init_identity (&crtc->user_sprite_position_transform); - pixman_f_transform_init_identity (&crtc->f_crtc_to_cursor); - pixman_f_transform_init_identity (&crtc->user_sprite_image_transform); - crtc->filter = NULL; - crtc->params = NULL; - crtc->nparams = 0; - crtc->filter_width = 0; - crtc->filter_height = 0; - crtc->transform_in_use = FALSE; - crtc->sprite_transform_in_use = FALSE; - crtc->transformPresent = FALSE; - crtc->desiredTransformPresent = FALSE; - memset (&crtc->bounds, '\0', sizeof (crtc->bounds)); - - /* Preallocate gamma at a sensible size. */ - crtc->gamma_size = 256; - crtc->gamma_red = malloc(3 * crtc->gamma_size * sizeof (CARD16)); - if (!crtc->gamma_red) { - free(crtc); - return NULL; - } - crtc->gamma_green = crtc->gamma_red + crtc->gamma_size; - crtc->gamma_blue = crtc->gamma_green + crtc->gamma_size; - - if (xf86_config->crtc) - crtcs = realloc(xf86_config->crtc, - (xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr)); - else - crtcs = malloc((xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr)); - if (!crtcs) - { - free(crtc); - return NULL; - } - xf86_config->crtc = crtcs; - xf86_config->crtc[xf86_config->num_crtc++] = crtc; - return crtc; -} - -void -xf86CrtcDestroy (xf86CrtcPtr crtc) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); - int c; - - (*crtc->funcs->destroy) (crtc); - for (c = 0; c < xf86_config->num_crtc; c++) - if (xf86_config->crtc[c] == crtc) - { - memmove (&xf86_config->crtc[c], - &xf86_config->crtc[c+1], - ((xf86_config->num_crtc - (c + 1)) * sizeof(void*))); - xf86_config->num_crtc--; - break; - } - free(crtc->params); - free(crtc->gamma_red); - free(crtc); -} - - -/** - * Return whether any outputs are connected to the specified pipe - */ - -Bool -xf86CrtcInUse (xf86CrtcPtr crtc) -{ - ScrnInfoPtr pScrn = crtc->scrn; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - int o; - - for (o = 0; o < xf86_config->num_output; o++) - if (xf86_config->output[o]->crtc == crtc) - return TRUE; - return FALSE; -} - -void -xf86CrtcSetScreenSubpixelOrder (ScreenPtr pScreen) -{ - int subpixel_order = SubPixelUnknown; - Bool has_none = FALSE; - ScrnInfoPtr scrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - int c, o; - - for (c = 0; c < xf86_config->num_crtc; c++) - { - xf86CrtcPtr crtc = xf86_config->crtc[c]; - - for (o = 0; o < xf86_config->num_output; o++) - { - xf86OutputPtr output = xf86_config->output[o]; - - if (output->crtc == crtc) - { - switch (output->subpixel_order) { - case SubPixelNone: - has_none = TRUE; - break; - case SubPixelUnknown: - break; - default: - subpixel_order = output->subpixel_order; - break; - } - } - if (subpixel_order != SubPixelUnknown) - break; - } - if (subpixel_order != SubPixelUnknown) - { - static const int circle[4] = { - SubPixelHorizontalRGB, - SubPixelVerticalRGB, - SubPixelHorizontalBGR, - SubPixelVerticalBGR, - }; - int rotate; - int c; - for (rotate = 0; rotate < 4; rotate++) - if (crtc->rotation & (1 << rotate)) - break; - for (c = 0; c < 4; c++) - if (circle[c] == subpixel_order) - break; - c = (c + rotate) & 0x3; - if ((crtc->rotation & RR_Reflect_X) && !(c & 1)) - c ^= 2; - if ((crtc->rotation & RR_Reflect_Y) && (c & 1)) - c ^= 2; - subpixel_order = circle[c]; - break; - } - } - if (subpixel_order == SubPixelUnknown && has_none) - subpixel_order = SubPixelNone; - PictureSetSubpixelOrder (pScreen, subpixel_order); -} - -/** - * Sets the given video mode on the given crtc - */ -Bool -xf86CrtcSet(xf86CrtcPtr crtc, xf86CrtcSetRec *set) -{ - ScrnInfoPtr scrn = crtc->scrn; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - int i; - Bool ret = FALSE; - Bool didLock = FALSE; - DisplayModePtr adjusted_mode = NULL; - DisplayModeRec saved_mode; - int saved_x, saved_y; - Rotation saved_rotation; - RRTransformRec saved_transform; - Bool saved_transform_present; - PixmapPtr saved_scanout_pixmap; - - crtc->enabled = xf86CrtcInUse (crtc); - - /* We only hit this if someone explicitly sends a "disabled" modeset. */ - if (!crtc->enabled) - { - /* Check everything for stuff that should be off. */ - xf86DisableUnusedFunctions(scrn); - return TRUE; - } - - /* See if nothing has changed */ - if (!set->flags) - return TRUE; - - saved_mode = crtc->mode; - saved_x = crtc->x; - saved_y = crtc->y; - saved_rotation = crtc->rotation; - saved_scanout_pixmap = crtc->scanoutPixmap; - if (crtc->transformPresent) { - RRTransformInit (&saved_transform); - RRTransformCopy (&saved_transform, &crtc->transform); - } - saved_transform_present = crtc->transformPresent; - - /* Update crtc values up front so the driver can rely on them for mode - * setting. - */ - if (set->flags & XF86CrtcSetMode) - crtc->mode = *set->mode; - if (set->flags & XF86CrtcSetOrigin) { - crtc->x = set->x; - crtc->y = set->y; - } - if (set->flags & XF86CrtcSetRotation) - crtc->rotation = set->rotation; - if (set->flags & XF86CrtcSetScanoutPixmap) - crtc->scanoutPixmap = set->scanout_pixmap; - - if (set->flags & XF86CrtcSetTransform) { - if (set->transform) { - RRTransformCopy (&crtc->transform, set->transform); - crtc->transformPresent = TRUE; - } else - crtc->transformPresent = FALSE; - } - - if (crtc->funcs->set) { - ret = crtc->funcs->set(crtc, set->flags); - goto done; - } - - if (set->flags == XF86CrtcSetOrigin && crtc->funcs->set_origin) { - ret = xf86CrtcRotate(crtc); - if (ret) - crtc->funcs->set_origin(crtc, crtc->x, crtc->y); - goto done; - } - - if (crtc->funcs->set_mode_major) { - ret = crtc->funcs->set_mode_major(crtc, &crtc->mode, - crtc->rotation, - crtc->x, crtc->y); - goto done; - } - - adjusted_mode = xf86DuplicateMode(&crtc->mode); - - didLock = crtc->funcs->lock (crtc); - /* Pass our mode to the outputs and the CRTC to give them a chance to - * adjust it according to limitations or output properties, and also - * a chance to reject the mode entirely. - */ - for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - - if (output->crtc != crtc) - continue; - - if (!output->funcs->mode_fixup(output, &crtc->mode, adjusted_mode)) { - goto done; - } - } - - if (!crtc->funcs->mode_fixup(crtc, &crtc->mode, adjusted_mode)) { - goto done; - } - - if (!xf86CrtcRotate (crtc)) - goto done; - - /* Prepare the outputs and CRTCs before setting the mode. */ - for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - - if (output->crtc != crtc) - continue; - - /* Disable the output as the first thing we do. */ - output->funcs->prepare(output); - } - - crtc->funcs->prepare(crtc); - - /* Set up the DPLL and any output state that needs to adjust or depend - * on the DPLL. - */ - crtc->funcs->mode_set(crtc, &crtc->mode, adjusted_mode, crtc->x, crtc->y); - for (i = 0; i < xf86_config->num_output; i++) - { - xf86OutputPtr output = xf86_config->output[i]; - if (output->crtc == crtc) - output->funcs->mode_set(output, &crtc->mode, adjusted_mode); - } - - /* Only upload when needed, to avoid unneeded delays. */ - if (!crtc->active && crtc->funcs->gamma_set) - crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, - crtc->gamma_blue, crtc->gamma_size); - - /* Now, enable the clocks, plane, pipe, and outputs that we set up. */ - crtc->funcs->commit(crtc); - for (i = 0; i < xf86_config->num_output; i++) - { - xf86OutputPtr output = xf86_config->output[i]; - if (output->crtc == crtc) - output->funcs->commit(output); - } - - ret = TRUE; - -done: - if (ret) { - crtc->active = TRUE; - if (scrn->pScreen) - xf86CrtcSetScreenSubpixelOrder (scrn->pScreen); - if (scrn->ModeSet) - scrn->ModeSet(scrn); - } else { - crtc->x = saved_x; - crtc->y = saved_y; - crtc->rotation = saved_rotation; - crtc->mode = saved_mode; - if (saved_transform_present) - RRTransformCopy (&crtc->transform, &saved_transform); - crtc->transformPresent = saved_transform_present; - crtc->scanoutPixmap = saved_scanout_pixmap; - } - - if (adjusted_mode) { - free(adjusted_mode->name); - free(adjusted_mode); - } - - if (didLock) - crtc->funcs->unlock (crtc); - - return ret; -} - -/** - * Pans the screen, does not change the mode - */ -void -xf86CrtcSetOrigin (xf86CrtcPtr crtc, int x, int y) -{ - xf86CrtcSetRec set; - - if (x != crtc->x || y != crtc->y) { - set.x = x; - set.y = y; - set.flags = XF86CrtcSetOrigin; - (void) xf86CrtcSet(crtc, &set); - } -} - -/* - * Output functions - */ - -extern XF86ConfigPtr xf86configptr; - -typedef enum { - OPTION_PREFERRED_MODE, - OPTION_POSITION, - OPTION_BELOW, - OPTION_RIGHT_OF, - OPTION_ABOVE, - OPTION_LEFT_OF, - OPTION_ENABLE, - OPTION_DISABLE, - OPTION_MIN_CLOCK, - OPTION_MAX_CLOCK, - OPTION_IGNORE, - OPTION_ROTATE, - OPTION_PANNING, - OPTION_PRIMARY, - OPTION_DEFAULT_MODES, -} OutputOpts; - -static OptionInfoRec xf86OutputOptions[] = { - {OPTION_PREFERRED_MODE, "PreferredMode", OPTV_STRING, {0}, FALSE }, - {OPTION_POSITION, "Position", OPTV_STRING, {0}, FALSE }, - {OPTION_BELOW, "Below", OPTV_STRING, {0}, FALSE }, - {OPTION_RIGHT_OF, "RightOf", OPTV_STRING, {0}, FALSE }, - {OPTION_ABOVE, "Above", OPTV_STRING, {0}, FALSE }, - {OPTION_LEFT_OF, "LeftOf", OPTV_STRING, {0}, FALSE }, - {OPTION_ENABLE, "Enable", OPTV_BOOLEAN, {0}, FALSE }, - {OPTION_DISABLE, "Disable", OPTV_BOOLEAN, {0}, FALSE }, - {OPTION_MIN_CLOCK, "MinClock", OPTV_FREQ, {0}, FALSE }, - {OPTION_MAX_CLOCK, "MaxClock", OPTV_FREQ, {0}, FALSE }, - {OPTION_IGNORE, "Ignore", OPTV_BOOLEAN, {0}, FALSE }, - {OPTION_ROTATE, "Rotate", OPTV_STRING, {0}, FALSE }, - {OPTION_PANNING, "Panning", OPTV_STRING, {0}, FALSE }, - {OPTION_PRIMARY, "Primary", OPTV_BOOLEAN, {0}, FALSE }, - {OPTION_DEFAULT_MODES, "DefaultModes", OPTV_BOOLEAN, {0}, FALSE }, - {-1, NULL, OPTV_NONE, {0}, FALSE }, -}; - -enum { - OPTION_MODEDEBUG, -}; - -static OptionInfoRec xf86DeviceOptions[] = { - {OPTION_MODEDEBUG, "ModeDebug", OPTV_BOOLEAN, {0}, FALSE }, - {-1, NULL, OPTV_NONE, {0}, FALSE }, -}; - -static void -xf86OutputSetMonitor (xf86OutputPtr output) -{ - char *option_name; - char *monitor; - - if (!output->name) - return; - - free(output->options); - - output->options = xnfalloc (sizeof (xf86OutputOptions)); - memcpy (output->options, xf86OutputOptions, sizeof (xf86OutputOptions)); - - XNFasprintf(&option_name, "monitor-%s", output->name); - monitor = xf86findOptionValue (output->scrn->options, option_name); - if (!monitor) - monitor = output->name; - else - xf86MarkOptionUsedByName (output->scrn->options, option_name); - free(option_name); - output->conf_monitor = xf86findMonitor (monitor, - xf86configptr->conf_monitor_lst); - /* - * Find the monitor section of the screen and use that - */ - if (!output->conf_monitor && output->use_screen_monitor) - output->conf_monitor = xf86findMonitor (output->scrn->monitor->id, - xf86configptr->conf_monitor_lst); - if (output->conf_monitor) - { - xf86DrvMsg (output->scrn->scrnIndex, X_INFO, - "Output %s using monitor section %s\n", - output->name, output->conf_monitor->mon_identifier); - xf86ProcessOptions (output->scrn->scrnIndex, - output->conf_monitor->mon_option_lst, - output->options); - } - else - xf86DrvMsg (output->scrn->scrnIndex, X_INFO, - "Output %s has no monitor section\n", - output->name); -} - -static Bool -xf86OutputEnabled (xf86OutputPtr output, Bool strict) -{ - Bool enable, disable; - - /* check to see if this output was enabled in the config file */ - if (xf86GetOptValBool (output->options, OPTION_ENABLE, &enable) && enable) - { - xf86DrvMsg (output->scrn->scrnIndex, X_INFO, - "Output %s enabled by config file\n", output->name); - return TRUE; - } - /* or if this output was disabled in the config file */ - if (xf86GetOptValBool (output->options, OPTION_DISABLE, &disable) && disable) - { - xf86DrvMsg (output->scrn->scrnIndex, X_INFO, - "Output %s disabled by config file\n", output->name); - return FALSE; - } - - /* If not, try to only light up the ones we know are connected */ - if (strict) { - enable = output->status == XF86OutputStatusConnected; - } - /* But if that fails, try to light up even outputs we're unsure of */ - else { - enable = output->status != XF86OutputStatusDisconnected; - } - - xf86DrvMsg (output->scrn->scrnIndex, X_INFO, - "Output %s %sconnected\n", output->name, enable ? "" : "dis"); - return enable; -} - -static Bool -xf86OutputIgnored (xf86OutputPtr output) -{ - return xf86ReturnOptValBool (output->options, OPTION_IGNORE, FALSE); -} - -static char *direction[4] = { - "normal", - "left", - "inverted", - "right" -}; - -static Rotation -xf86OutputInitialRotation (xf86OutputPtr output) -{ - char *rotate_name = xf86GetOptValString (output->options, - OPTION_ROTATE); - int i; - - if (!rotate_name) { - if (output->initial_rotation) - return output->initial_rotation; - return RR_Rotate_0; - } - - for (i = 0; i < 4; i++) - if (xf86nameCompare (direction[i], rotate_name) == 0) - return 1 << i; - return RR_Rotate_0; -} - -xf86OutputPtr -xf86OutputCreate (ScrnInfoPtr scrn, - const xf86OutputFuncsRec *funcs, - const char *name) -{ - xf86OutputPtr output, *outputs; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - int len; - Bool primary; - - if (name) - len = strlen (name) + 1; - else - len = 0; - - output = calloc(sizeof (xf86OutputRec) + len, 1); - if (!output) - return NULL; - output->scrn = scrn; - output->funcs = funcs; - if (name) - { - output->name = (char *) (output + 1); - strcpy (output->name, name); - } - output->subpixel_order = SubPixelUnknown; - /* - * Use the old per-screen monitor section for the first output - */ - output->use_screen_monitor = (xf86_config->num_output == 0); -#ifdef RANDR_12_INTERFACE - output->randr_output = NULL; -#endif - if (name) - { - xf86OutputSetMonitor (output); - if (xf86OutputIgnored (output)) - { - free(output); - return FALSE; - } - } - - - if (xf86_config->output) - outputs = realloc(xf86_config->output, - (xf86_config->num_output + 1) * sizeof (xf86OutputPtr)); - else - outputs = malloc((xf86_config->num_output + 1) * sizeof (xf86OutputPtr)); - if (!outputs) - { - free(output); - return NULL; - } - - xf86_config->output = outputs; - - if (xf86GetOptValBool (output->options, OPTION_PRIMARY, &primary) && primary) - { - memmove(xf86_config->output + 1, xf86_config->output, - xf86_config->num_output * sizeof (xf86OutputPtr)); - xf86_config->output[0] = output; - } - else - { - xf86_config->output[xf86_config->num_output] = output; - } - - xf86_config->num_output++; - - return output; -} - -Bool -xf86OutputRename (xf86OutputPtr output, const char *name) -{ - char *newname = strdup(name); - - if (!newname) - return FALSE; /* so sorry... */ - - if (output->name && output->name != (char *) (output + 1)) - free(output->name); - output->name = newname; - xf86OutputSetMonitor (output); - if (xf86OutputIgnored (output)) - return FALSE; - return TRUE; -} - -void -xf86OutputUseScreenMonitor (xf86OutputPtr output, Bool use_screen_monitor) -{ - if (use_screen_monitor != output->use_screen_monitor) - { - output->use_screen_monitor = use_screen_monitor; - xf86OutputSetMonitor (output); - } -} - -void -xf86OutputDestroy (xf86OutputPtr output) -{ - ScrnInfoPtr scrn = output->scrn; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - int o; - - (*output->funcs->destroy) (output); - while (output->probed_modes) - xf86DeleteMode (&output->probed_modes, output->probed_modes); - for (o = 0; o < xf86_config->num_output; o++) - if (xf86_config->output[o] == output) - { - memmove (&xf86_config->output[o], - &xf86_config->output[o+1], - ((xf86_config->num_output - (o + 1)) * sizeof(void*))); - xf86_config->num_output--; - break; - } - if (output->name && output->name != (char *) (output + 1)) - free(output->name); - free(output); -} - -/* - * Called during CreateScreenResources to hook up RandR - */ -static Bool -xf86CrtcCreateScreenResources (ScreenPtr screen) -{ - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - - screen->CreateScreenResources = config->CreateScreenResources; - - if (!(*screen->CreateScreenResources)(screen)) - return FALSE; - - if (!xf86RandR12CreateScreenResources (screen)) - return FALSE; - - return TRUE; -} - -/* - * Clean up config on server reset - */ -static Bool -xf86CrtcCloseScreen (int index, ScreenPtr screen) -{ - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o, c; - - screen->CloseScreen = config->CloseScreen; - - xf86RotateCloseScreen (screen); - - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - - output->randr_output = NULL; - } - for (c = 0; c < config->num_crtc; c++) - { - xf86CrtcPtr crtc = config->crtc[c]; - - crtc->randr_crtc = NULL; - } - xf86RandR12CloseScreen (screen); - - return screen->CloseScreen (index, screen); -} - -/* - * Called at ScreenInit time to set up - */ -#ifdef RANDR_13_INTERFACE -int -#else -Bool -#endif -xf86CrtcScreenInit (ScreenPtr screen) -{ - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int c; - - /* Rotation */ - xf86DrvMsg(scrn->scrnIndex, X_INFO, "RandR 1.2 enabled, ignore the following RandR disabled message.\n"); - xf86DisableRandR(); /* Disable old RandR extension support */ - xf86RandR12Init (screen); - - /* support all rotations if every crtc has the shadow alloc funcs */ - for (c = 0; c < config->num_crtc; c++) - { - xf86CrtcPtr crtc = config->crtc[c]; - if (!crtc->funcs->shadow_allocate || !crtc->funcs->shadow_create) - break; - } - if (c == config->num_crtc) - { - xf86RandR12SetRotations (screen, RR_Rotate_0 | RR_Rotate_90 | - RR_Rotate_180 | RR_Rotate_270 | - RR_Reflect_X | RR_Reflect_Y); - xf86RandR12SetTransformSupport (screen, TRUE); - } - else - { - xf86RandR12SetRotations (screen, RR_Rotate_0); - xf86RandR12SetTransformSupport (screen, FALSE); - } - - /* Wrap CreateScreenResources so we can initialize the RandR code */ - config->CreateScreenResources = screen->CreateScreenResources; - screen->CreateScreenResources = xf86CrtcCreateScreenResources; - - config->CloseScreen = screen->CloseScreen; - screen->CloseScreen = xf86CrtcCloseScreen; - -#ifdef XFreeXDGA - _xf86_di_dga_init_internal(screen); -#endif -#ifdef RANDR_13_INTERFACE - return RANDR_INTERFACE_VERSION; -#else - return TRUE; -#endif -} - -static DisplayModePtr -xf86DefaultMode (xf86OutputPtr output, int width, int height) -{ - DisplayModePtr target_mode = NULL; - DisplayModePtr mode; - int target_diff = 0; - int target_preferred = 0; - int mm_height; - - mm_height = output->mm_height; - if (!mm_height) - mm_height = (768 * 25.4) / DEFAULT_DPI; - /* - * Pick a mode closest to DEFAULT_DPI - */ - for (mode = output->probed_modes; mode; mode = mode->next) - { - int dpi; - int preferred = (((mode->type & M_T_PREFERRED) != 0) + - ((mode->type & M_T_USERPREF) != 0)); - int diff; - - if (xf86ModeWidth (mode, output->initial_rotation) > width || - xf86ModeHeight (mode, output->initial_rotation) > height) - continue; - - /* yes, use VDisplay here, not xf86ModeHeight */ - dpi = (mode->VDisplay * 254) / (mm_height * 10); - diff = dpi - DEFAULT_DPI; - diff = diff < 0 ? -diff : diff; - if (target_mode == NULL || (preferred > target_preferred) || - (preferred == target_preferred && diff < target_diff)) - { - target_mode = mode; - target_diff = diff; - target_preferred = preferred; - } - } - return target_mode; -} - -static DisplayModePtr -xf86ClosestMode (xf86OutputPtr output, - DisplayModePtr match, Rotation match_rotation, - int width, int height) -{ - DisplayModePtr target_mode = NULL; - DisplayModePtr mode; - int target_diff = 0; - - /* - * Pick a mode closest to the specified mode - */ - for (mode = output->probed_modes; mode; mode = mode->next) - { - int dx, dy; - int diff; - - if (xf86ModeWidth (mode, output->initial_rotation) > width || - xf86ModeHeight (mode, output->initial_rotation) > height) - continue; - - /* exact matches are preferred */ - if (output->initial_rotation == match_rotation && - xf86ModesEqual (mode, match)) - return mode; - - dx = xf86ModeWidth (match, match_rotation) - xf86ModeWidth (mode, output->initial_rotation); - dy = xf86ModeHeight (match, match_rotation) - xf86ModeHeight (mode, output->initial_rotation); - diff = dx * dx + dy * dy; - if (target_mode == NULL || diff < target_diff) - { - target_mode = mode; - target_diff = diff; - } - } - return target_mode; -} - -static DisplayModePtr -xf86OutputHasPreferredMode (xf86OutputPtr output, int width, int height) -{ - DisplayModePtr mode; - - for (mode = output->probed_modes; mode; mode = mode->next) - { - if (xf86ModeWidth (mode, output->initial_rotation) > width || - xf86ModeHeight (mode, output->initial_rotation) > height) - continue; - - if (mode->type & M_T_PREFERRED) - return mode; - } - return NULL; -} - -static DisplayModePtr -xf86OutputHasUserPreferredMode (xf86OutputPtr output) -{ - DisplayModePtr mode, first = output->probed_modes; - - for (mode = first; mode && mode->next != first; mode = mode->next) - if (mode->type & M_T_USERPREF) - return mode; - - return NULL; -} - -static int -xf86PickCrtcs (ScrnInfoPtr scrn, - xf86CrtcPtr *best_crtcs, - DisplayModePtr *modes, - int n, - int width, - int height) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int c, o; - xf86OutputPtr output; - xf86CrtcPtr crtc; - xf86CrtcPtr *crtcs; - xf86CrtcPtr best_crtc; - int best_score; - int score; - int my_score; - - if (n == config->num_output) - return 0; - output = config->output[n]; - - /* - * Compute score with this output disabled - */ - best_crtcs[n] = NULL; - best_crtc = NULL; - best_score = xf86PickCrtcs (scrn, best_crtcs, modes, n+1, width, height); - if (modes[n] == NULL) - return best_score; - - crtcs = malloc(config->num_output * sizeof (xf86CrtcPtr)); - if (!crtcs) - return best_score; - - my_score = 1; - /* Score outputs that are known to be connected higher */ - if (output->status == XF86OutputStatusConnected) - my_score++; - /* Score outputs with preferred modes higher */ - if (xf86OutputHasPreferredMode (output, width, height)) - my_score++; - /* - * Select a crtc for this output and - * then attempt to configure the remaining - * outputs - */ - for (c = 0; c < config->num_crtc; c++) - { - if ((output->possible_crtcs & (1 << c)) == 0) - continue; - - crtc = config->crtc[c]; - /* - * Check to see if some other output is - * using this crtc - */ - for (o = 0; o < n; o++) - if (best_crtcs[o] == crtc) - break; - if (o < n) - { - /* - * If the two outputs desire the same mode, - * see if they can be cloned - */ - if (xf86ModesEqual (modes[o], modes[n]) && - config->output[o]->initial_rotation == config->output[n]->initial_rotation && - config->output[o]->initial_x == config->output[n]->initial_x && - config->output[o]->initial_y == config->output[n]->initial_y) - { - if ((output->possible_clones & (1 << o)) == 0) - continue; /* nope, try next CRTC */ - } - else - continue; /* different modes, can't clone */ - } - crtcs[n] = crtc; - memcpy (crtcs, best_crtcs, n * sizeof (xf86CrtcPtr)); - score = my_score + xf86PickCrtcs (scrn, crtcs, modes, n+1, width, height); - if (score > best_score) - { - best_crtc = crtc; - best_score = score; - memcpy (best_crtcs, crtcs, config->num_output * sizeof (xf86CrtcPtr)); - } - } - free(crtcs); - return best_score; -} - - -/* - * Compute the virtual size necessary to place all of the available - * crtcs in the specified configuration. - * - * canGrow indicates that the driver can make the screen larger than its initial - * configuration. If FALSE, this function will enlarge the screen to include - * the largest available mode. - */ - -static void -xf86DefaultScreenLimits (ScrnInfoPtr scrn, int *widthp, int *heightp, - Bool canGrow) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int width = 0, height = 0; - int o; - int c; - int s; - - for (c = 0; c < config->num_crtc; c++) - { - int crtc_width = 0, crtc_height = 0; - xf86CrtcPtr crtc = config->crtc[c]; - - if (crtc->enabled) - { - crtc_width = crtc->desiredX + xf86ModeWidth (&crtc->desiredMode, crtc->desiredRotation); - crtc_height = crtc->desiredY + xf86ModeHeight (&crtc->desiredMode, crtc->desiredRotation); - } - if (!canGrow) { - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - - for (s = 0; s < config->num_crtc; s++) - if (output->possible_crtcs & (1 << s)) - { - DisplayModePtr mode; - for (mode = output->probed_modes; mode; mode = mode->next) - { - if (mode->HDisplay > crtc_width) - crtc_width = mode->HDisplay; - if (mode->VDisplay > crtc_width) - crtc_width = mode->VDisplay; - if (mode->VDisplay > crtc_height) - crtc_height = mode->VDisplay; - if (mode->HDisplay > crtc_height) - crtc_height = mode->HDisplay; - } - } - } - } - if (crtc_width > width) - width = crtc_width; - if (crtc_height > height) - height = crtc_height; - } - if (config->maxWidth && width > config->maxWidth) width = config->maxWidth; - if (config->maxHeight && height > config->maxHeight) height = config->maxHeight; - if (config->minWidth && width < config->minWidth) width = config->minWidth; - if (config->minHeight && height < config->minHeight) height = config->minHeight; - *widthp = width; - *heightp = height; -} - -#define POSITION_UNSET -100000 - -/* - * check if the user configured any outputs at all - * with either a position or a relative setting or a mode. - */ -static Bool -xf86UserConfiguredOutputs(ScrnInfoPtr scrn, DisplayModePtr *modes) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o; - Bool user_conf = FALSE; - - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - char *position; - char *relative_name; - OutputOpts relation; - int r; - static const OutputOpts relations[] = { - OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF - }; - - position = xf86GetOptValString (output->options, - OPTION_POSITION); - if (position) - user_conf = TRUE; - - relation = 0; - relative_name = NULL; - for (r = 0; r < 4; r++) - { - relation = relations[r]; - relative_name = xf86GetOptValString (output->options, - relation); - if (relative_name) - break; - } - if (relative_name) - user_conf = TRUE; - - modes[o] = xf86OutputHasUserPreferredMode(output); - if (modes[o]) - user_conf = TRUE; - } - - return user_conf; -} - -static Bool -xf86InitialOutputPositions (ScrnInfoPtr scrn, DisplayModePtr *modes) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o; - int min_x, min_y; - - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - - output->initial_x = output->initial_y = POSITION_UNSET; - } - - /* - * Loop until all outputs are set - */ - for (;;) - { - Bool any_set = FALSE; - Bool keep_going = FALSE; - - for (o = 0; o < config->num_output; o++) - { - static const OutputOpts relations[] = { - OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF - }; - xf86OutputPtr output = config->output[o]; - xf86OutputPtr relative; - char *relative_name; - char *position; - OutputOpts relation; - int r; - - if (output->initial_x != POSITION_UNSET) - continue; - position = xf86GetOptValString (output->options, - OPTION_POSITION); - /* - * Absolute position wins - */ - if (position) - { - int x, y; - if (sscanf (position, "%d %d", &x, &y) == 2) - { - output->initial_x = x; - output->initial_y = y; - } - else - { - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Output %s position not of form \"x y\"\n", - output->name); - output->initial_x = output->initial_y = 0; - } - any_set = TRUE; - continue; - } - /* - * Next comes relative positions - */ - relation = 0; - relative_name = NULL; - for (r = 0; r < 4; r++) - { - relation = relations[r]; - relative_name = xf86GetOptValString (output->options, - relation); - if (relative_name) - break; - } - if (relative_name) - { - int or; - relative = NULL; - for (or = 0; or < config->num_output; or++) - { - xf86OutputPtr out_rel = config->output[or]; - XF86ConfMonitorPtr rel_mon = out_rel->conf_monitor; - - if (rel_mon) - { - if (xf86nameCompare (rel_mon->mon_identifier, - relative_name) == 0) - { - relative = config->output[or]; - break; - } - } - if (strcmp (out_rel->name, relative_name) == 0) - { - relative = config->output[or]; - break; - } - } - if (!relative) - { - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Cannot position output %s relative to unknown output %s\n", - output->name, relative_name); - output->initial_x = 0; - output->initial_y = 0; - any_set = TRUE; - continue; - } - if (!modes[or]) - { - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Cannot position output %s relative to output %s without modes\n", - output->name, relative_name); - output->initial_x = 0; - output->initial_y = 0; - any_set = TRUE; - continue; - } - if (relative->initial_x == POSITION_UNSET) - { - keep_going = TRUE; - continue; - } - output->initial_x = relative->initial_x; - output->initial_y = relative->initial_y; - switch (relation) { - case OPTION_BELOW: - output->initial_y += xf86ModeHeight (modes[or], relative->initial_rotation); - break; - case OPTION_RIGHT_OF: - output->initial_x += xf86ModeWidth (modes[or], relative->initial_rotation); - break; - case OPTION_ABOVE: - if (modes[o]) - output->initial_y -= xf86ModeHeight (modes[o], output->initial_rotation); - break; - case OPTION_LEFT_OF: - if (modes[o]) - output->initial_x -= xf86ModeWidth (modes[o], output->initial_rotation); - break; - default: - break; - } - any_set = TRUE; - continue; - } - - /* Nothing set, just stick them at 0,0 */ - output->initial_x = 0; - output->initial_y = 0; - any_set = TRUE; - } - if (!keep_going) - break; - if (!any_set) - { - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - if (output->initial_x == POSITION_UNSET) - { - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Output position loop. Moving %s to 0,0\n", - output->name); - output->initial_x = output->initial_y = 0; - break; - } - } - } - } - - /* - * normalize positions - */ - min_x = 1000000; - min_y = 1000000; - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - - if (output->initial_x < min_x) - min_x = output->initial_x; - if (output->initial_y < min_y) - min_y = output->initial_y; - } - - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - - output->initial_x -= min_x; - output->initial_y -= min_y; - } - return TRUE; -} - -static void -xf86InitialPanning (ScrnInfoPtr scrn) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o; - - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - char *panning = xf86GetOptValString (output->options, OPTION_PANNING); - int width, height, left, top; - int track_width, track_height, track_left, track_top; - int brdr[4]; - - memset (&output->initialTotalArea, 0, sizeof(BoxRec)); - memset (&output->initialTrackingArea, 0, sizeof(BoxRec)); - memset (output->initialBorder, 0, 4*sizeof(INT16)); - - if (! panning) - continue; - - switch (sscanf (panning, "%dx%d+%d+%d/%dx%d+%d+%d/%d/%d/%d/%d", - &width, &height, &left, &top, - &track_width, &track_height, &track_left, &track_top, - &brdr[0], &brdr[1], &brdr[2], &brdr[3])) { - case 12: - output->initialBorder[0] = brdr[0]; - output->initialBorder[1] = brdr[1]; - output->initialBorder[2] = brdr[2]; - output->initialBorder[3] = brdr[3]; - /* fall through */ - case 8: - output->initialTrackingArea.x1 = track_left; - output->initialTrackingArea.y1 = track_top; - output->initialTrackingArea.x2 = track_left + track_width; - output->initialTrackingArea.y2 = track_top + track_height; - /* fall through */ - case 4: - output->initialTotalArea.x1 = left; - output->initialTotalArea.y1 = top; - /* fall through */ - case 2: - output->initialTotalArea.x2 = output->initialTotalArea.x1 + width; - output->initialTotalArea.y2 = output->initialTotalArea.y1 + height; - break; - default: - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Broken panning specification '%s' for output %s in config file\n", - panning, output->name); - } - } -} - -/** Return - 0 + if a should be earlier, same or later than b in list - */ -static int -xf86ModeCompare (DisplayModePtr a, DisplayModePtr b) -{ - int diff; - - diff = ((b->type & M_T_PREFERRED) != 0) - ((a->type & M_T_PREFERRED) != 0); - if (diff) - return diff; - diff = b->HDisplay * b->VDisplay - a->HDisplay * a->VDisplay; - if (diff) - return diff; - diff = b->Clock - a->Clock; - return diff; -} - -/** - * Insertion sort input in-place and return the resulting head - */ -static DisplayModePtr -xf86SortModes (DisplayModePtr input) -{ - DisplayModePtr output = NULL, i, o, n, *op, prev; - - /* sort by preferred status and pixel area */ - while (input) - { - i = input; - input = input->next; - for (op = &output; (o = *op); op = &o->next) - if (xf86ModeCompare (o, i) > 0) - break; - i->next = *op; - *op = i; - } - /* prune identical modes */ - for (o = output; o && (n = o->next); o = n) - { - if (!strcmp (o->name, n->name) && xf86ModesEqual (o, n)) - { - o->next = n->next; - free(n->name); - free(n); - n = o; - } - } - /* hook up backward links */ - prev = NULL; - for (o = output; o; o = o->next) - { - o->prev = prev; - prev = o; - } - return output; -} - -static char * -preferredMode(ScrnInfoPtr pScrn, xf86OutputPtr output) -{ - char *preferred_mode = NULL; - - /* Check for a configured preference for a particular mode */ - preferred_mode = xf86GetOptValString (output->options, - OPTION_PREFERRED_MODE); - if (preferred_mode) - return preferred_mode; - - if (pScrn->display->modes && *pScrn->display->modes) - preferred_mode = *pScrn->display->modes; - - return preferred_mode; -} - -static void -GuessRangeFromModes(MonPtr mon, DisplayModePtr mode) -{ - if (!mon || !mode) - return; - - mon->nHsync = 1; - mon->hsync[0].lo = 1024.0; - mon->hsync[0].hi = 0.0; - - mon->nVrefresh = 1; - mon->vrefresh[0].lo = 1024.0; - mon->vrefresh[0].hi = 0.0; - - while (mode) { - if (!mode->HSync) - mode->HSync = ((float) mode->Clock ) / ((float) mode->HTotal); - - if (!mode->VRefresh) - mode->VRefresh = (1000.0 * ((float) mode->Clock)) / - ((float) (mode->HTotal * mode->VTotal)); - - if (mode->HSync < mon->hsync[0].lo) - mon->hsync[0].lo = mode->HSync; - - if (mode->HSync > mon->hsync[0].hi) - mon->hsync[0].hi = mode->HSync; - - if (mode->VRefresh < mon->vrefresh[0].lo) - mon->vrefresh[0].lo = mode->VRefresh; - - if (mode->VRefresh > mon->vrefresh[0].hi) - mon->vrefresh[0].hi = mode->VRefresh; - - mode = mode->next; - } - - /* stretch out the bottom to fit 640x480@60 */ - if (mon->hsync[0].lo > 31.0) - mon->hsync[0].lo = 31.0; - if (mon->vrefresh[0].lo > 58.0) - mon->vrefresh[0].lo = 58.0; -} - -enum det_monrec_source { - sync_config, sync_edid, sync_default -}; - -struct det_monrec_parameter { - MonRec *mon_rec; - int *max_clock; - Bool set_hsync; - Bool set_vrefresh; - enum det_monrec_source *sync_source; -}; - -static void handle_detailed_monrec(struct detailed_monitor_section *det_mon, - void *data) -{ - enum { sync_config, sync_edid, sync_default }; - struct det_monrec_parameter *p; - p = (struct det_monrec_parameter *)data; - - if (det_mon->type == DS_RANGES) { - struct monitor_ranges *ranges = &det_mon->section.ranges; - if (p->set_hsync && ranges->max_h) { - p->mon_rec->hsync[p->mon_rec->nHsync].lo = ranges->min_h; - p->mon_rec->hsync[p->mon_rec->nHsync].hi = ranges->max_h; - p->mon_rec->nHsync++; - if (*p->sync_source == sync_default) - *p->sync_source = sync_edid; - } - if (p->set_vrefresh && ranges->max_v) { - p->mon_rec->vrefresh[p->mon_rec->nVrefresh].lo = ranges->min_v; - p->mon_rec->vrefresh[p->mon_rec->nVrefresh].hi = ranges->max_v; - p->mon_rec->nVrefresh++; - if (*p->sync_source == sync_default) - *p->sync_source = sync_edid; - } - if (ranges->max_clock * 1000 > *p->max_clock) - *p->max_clock = ranges->max_clock * 1000; - } -} - -void -xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o; - - /* When canGrow was TRUE in the initial configuration we have to - * compare against the maximum values so that we don't drop modes. - * When canGrow was FALSE, the maximum values would have been clamped - * anyway. - */ - if (maxX == 0 || maxY == 0) { - maxX = config->maxWidth; - maxY = config->maxHeight; - } - - /* Probe the list of modes for each output. */ - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - DisplayModePtr mode; - DisplayModePtr config_modes = NULL, output_modes, default_modes = NULL; - char *preferred_mode; - xf86MonPtr edid_monitor; - XF86ConfMonitorPtr conf_monitor; - MonRec mon_rec; - int min_clock = 0; - int max_clock = 0; - double clock; - Bool add_default_modes = xf86ReturnOptValBool(output->options, OPTION_DEFAULT_MODES, TRUE); - Bool debug_modes = config->debug_modes || - xf86Initialising; - enum det_monrec_source sync_source = sync_default; - - while (output->probed_modes != NULL) - xf86DeleteMode(&output->probed_modes, output->probed_modes); - - /* - * Check connection status - */ - output->status = (*output->funcs->detect)(output); - - if (output->status == XF86OutputStatusDisconnected && - !xf86ReturnOptValBool(output->options, OPTION_ENABLE, FALSE)) - { - xf86OutputSetEDID (output, NULL); - continue; - } - - memset (&mon_rec, '\0', sizeof (mon_rec)); - - conf_monitor = output->conf_monitor; - - if (conf_monitor) - { - int i; - - for (i = 0; i < conf_monitor->mon_n_hsync; i++) - { - mon_rec.hsync[mon_rec.nHsync].lo = conf_monitor->mon_hsync[i].lo; - mon_rec.hsync[mon_rec.nHsync].hi = conf_monitor->mon_hsync[i].hi; - mon_rec.nHsync++; - sync_source = sync_config; - } - for (i = 0; i < conf_monitor->mon_n_vrefresh; i++) - { - mon_rec.vrefresh[mon_rec.nVrefresh].lo = conf_monitor->mon_vrefresh[i].lo; - mon_rec.vrefresh[mon_rec.nVrefresh].hi = conf_monitor->mon_vrefresh[i].hi; - mon_rec.nVrefresh++; - sync_source = sync_config; - } - config_modes = xf86GetMonitorModes (scrn, conf_monitor); - } - - output_modes = (*output->funcs->get_modes) (output); - - edid_monitor = output->MonInfo; - - if (edid_monitor) - { - struct det_monrec_parameter p; - struct disp_features *features = &edid_monitor->features; - - /* if display is not continuous-frequency, don't add default modes */ - if (!GTF_SUPPORTED(features->msc)) - add_default_modes = FALSE; - - p.mon_rec = &mon_rec; - p.max_clock = &max_clock; - p.set_hsync = mon_rec.nHsync == 0; - p.set_vrefresh = mon_rec.nVrefresh == 0; - p.sync_source = &sync_source; - - xf86ForEachDetailedBlock(edid_monitor, - handle_detailed_monrec, - &p); - } - - if (xf86GetOptValFreq (output->options, OPTION_MIN_CLOCK, - OPTUNITS_KHZ, &clock)) - min_clock = (int) clock; - if (xf86GetOptValFreq (output->options, OPTION_MAX_CLOCK, - OPTUNITS_KHZ, &clock)) - max_clock = (int) clock; - - /* If we still don't have a sync range, guess wildly */ - if (!mon_rec.nHsync || !mon_rec.nVrefresh) - GuessRangeFromModes(&mon_rec, output_modes); - - /* - * These limits will end up setting a 1024x768@60Hz mode by default, - * which seems like a fairly good mode to use when nothing else is - * specified - */ - if (mon_rec.nHsync == 0) - { - mon_rec.hsync[0].lo = 31.0; - mon_rec.hsync[0].hi = 55.0; - mon_rec.nHsync = 1; - } - if (mon_rec.nVrefresh == 0) - { - mon_rec.vrefresh[0].lo = 58.0; - mon_rec.vrefresh[0].hi = 62.0; - mon_rec.nVrefresh = 1; - } - - if (add_default_modes) - default_modes = xf86GetDefaultModes (); - - /* - * If this is not an RB monitor, remove RB modes from the default - * pool. RB modes from the config or the monitor itself are fine. - */ - if (!mon_rec.reducedblanking) - xf86ValidateModesReducedBlanking (scrn, default_modes); - - if (sync_source == sync_config) - { - /* - * Check output and config modes against sync range from config file - */ - xf86ValidateModesSync (scrn, output_modes, &mon_rec); - xf86ValidateModesSync (scrn, config_modes, &mon_rec); - } - /* - * Check default modes against sync range - */ - xf86ValidateModesSync (scrn, default_modes, &mon_rec); - /* - * Check default modes against monitor max clock - */ - if (max_clock) { - xf86ValidateModesClocks(scrn, default_modes, - &min_clock, &max_clock, 1); - xf86ValidateModesClocks(scrn, output_modes, - &min_clock, &max_clock, 1); - } - - output->probed_modes = NULL; - output->probed_modes = xf86ModesAdd (output->probed_modes, config_modes); - output->probed_modes = xf86ModesAdd (output->probed_modes, output_modes); - output->probed_modes = xf86ModesAdd (output->probed_modes, default_modes); - - /* - * Check all modes against max size, interlace, and doublescan - */ - if (maxX && maxY) - xf86ValidateModesSize (scrn, output->probed_modes, - maxX, maxY, 0); - - { - int flags = (output->interlaceAllowed ? V_INTERLACE : 0) | - (output->doubleScanAllowed ? V_DBLSCAN : 0); - xf86ValidateModesFlags (scrn, output->probed_modes, flags); - } - - /* - * Check all modes against output - */ - for (mode = output->probed_modes; mode != NULL; mode = mode->next) - if (mode->status == MODE_OK) - mode->status = (*output->funcs->mode_valid)(output, mode); - - xf86PruneInvalidModes(scrn, &output->probed_modes, debug_modes); - - output->probed_modes = xf86SortModes (output->probed_modes); - - /* Check for a configured preference for a particular mode */ - preferred_mode = preferredMode(scrn, output); - - if (preferred_mode) - { - for (mode = output->probed_modes; mode; mode = mode->next) - { - if (!strcmp (preferred_mode, mode->name)) - { - if (mode != output->probed_modes) - { - if (mode->prev) - mode->prev->next = mode->next; - if (mode->next) - mode->next->prev = mode->prev; - mode->next = output->probed_modes; - output->probed_modes->prev = mode; - mode->prev = NULL; - output->probed_modes = mode; - } - mode->type |= (M_T_PREFERRED|M_T_USERPREF); - break; - } - } - } - - output->initial_rotation = xf86OutputInitialRotation (output); - - if (debug_modes) { - if (output->probed_modes != NULL) { - xf86DrvMsg(scrn->scrnIndex, X_INFO, - "Printing probed modes for output %s\n", - output->name); - } else { - xf86DrvMsg(scrn->scrnIndex, X_INFO, - "No remaining probed modes for output %s\n", - output->name); - } - } - for (mode = output->probed_modes; mode != NULL; mode = mode->next) - { - /* The code to choose the best mode per pipe later on will require - * VRefresh to be set. - */ - mode->VRefresh = xf86ModeVRefresh(mode); - xf86SetModeCrtc(mode, INTERLACE_HALVE_V); - - if (debug_modes) - xf86PrintModeline(scrn->scrnIndex, mode); - } - } -} - - -/** - * Copy one of the output mode lists to the ScrnInfo record - */ - -/* XXX where does this function belong? Here? */ -void -xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr scrn, int *x, int *y); - -static DisplayModePtr -biggestMode(DisplayModePtr a, DisplayModePtr b) -{ - int A, B; - - if (!a) - return b; - if (!b) - return a; - - A = a->HDisplay * a->VDisplay; - B = b->HDisplay * b->VDisplay; - - if (A > B) - return a; - - return b; -} - -static xf86OutputPtr -SetCompatOutput(xf86CrtcConfigPtr config) -{ - xf86OutputPtr output = NULL, test = NULL; - DisplayModePtr maxmode = NULL, testmode, mode; - int o, compat = -1, count, mincount = 0; - - /* Look for one that's definitely connected */ - for (o = 0; o < config->num_output; o++) - { - test = config->output[o]; - if (!test->crtc) - continue; - if (test->status != XF86OutputStatusConnected) - continue; - if (!test->probed_modes) - continue; - - testmode = mode = test->probed_modes; - for (count = 0; mode; mode = mode->next, count++) - testmode = biggestMode(testmode, mode); - - if (!output) { - output = test; - compat = o; - maxmode = testmode; - mincount = count; - } else if (maxmode == biggestMode(maxmode, testmode)) { - output = test; - compat = o; - maxmode = testmode; - mincount = count; - } else if ((maxmode->HDisplay == testmode->HDisplay) && - (maxmode->VDisplay == testmode->VDisplay) && - count <= mincount) { - output = test; - compat = o; - maxmode = testmode; - mincount = count; - } - } - - /* If we didn't find one, take anything we can get */ - if (!output) - { - for (o = 0; o < config->num_output; o++) - { - test = config->output[o]; - if (!test->crtc) - continue; - if (!test->probed_modes) - continue; - - if (!output) { - output = test; - compat = o; - } else if (test->probed_modes->HDisplay < output->probed_modes->HDisplay) { - output = test; - compat = o; - } - } - } - - if (compat >= 0) { - config->compat_output = compat; - } else { - /* Don't change the compat output when no valid outputs found */ - output = config->output[config->compat_output]; - } - - return output; -} - -void -xf86SetScrnInfoModes (ScrnInfoPtr scrn) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - xf86OutputPtr output; - xf86CrtcPtr crtc; - DisplayModePtr last, mode = NULL; - - output = SetCompatOutput(config); - - if (!output) - return; /* punt */ - - crtc = output->crtc; - - /* Clear any existing modes from scrn->modes */ - while (scrn->modes != NULL) - xf86DeleteMode(&scrn->modes, scrn->modes); - - /* Set scrn->modes to the mode list for the 'compat' output */ - scrn->modes = xf86DuplicateModes(scrn, output->probed_modes); - - if (crtc) { - for (mode = scrn->modes; mode; mode = mode->next) - if (xf86ModesEqual (mode, &crtc->desiredMode)) - break; - } - - if (scrn->modes != NULL) { - /* For some reason, scrn->modes is circular, unlike the other mode - * lists. How great is that? - */ - for (last = scrn->modes; last && last->next; last = last->next) - ; - last->next = scrn->modes; - scrn->modes->prev = last; - if (mode) { - while (scrn->modes != mode) - scrn->modes = scrn->modes->next; - } - } - scrn->currentMode = scrn->modes; -#ifdef XFreeXDGA - if (scrn->pScreen) - _xf86_di_dga_reinit_internal(scrn->pScreen); -#endif -} - -static Bool -xf86CollectEnabledOutputs(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, - Bool *enabled) -{ - Bool any_enabled = FALSE; - int o; - - for (o = 0; o < config->num_output; o++) - any_enabled |= enabled[o] = xf86OutputEnabled(config->output[o], TRUE); - - if (!any_enabled) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "No outputs definitely connected, trying again...\n"); - - for (o = 0; o < config->num_output; o++) - any_enabled |= enabled[o] = xf86OutputEnabled(config->output[o], FALSE); - } - - return any_enabled; -} - -static Bool -nextEnabledOutput(xf86CrtcConfigPtr config, Bool *enabled, int *index) -{ - int o = *index; - - for (o++; o < config->num_output; o++) { - if (enabled[o]) { - *index = o; - return TRUE; - } - } - - return FALSE; -} - -static Bool -aspectMatch(float a, float b) -{ - return fabs(1 - (a / b)) < 0.05; -} - -static DisplayModePtr -nextAspectMode(xf86OutputPtr o, DisplayModePtr last, float aspect) -{ - DisplayModePtr m = NULL; - - if (!o) - return NULL; - - if (!last) - m = o->probed_modes; - else - m = last->next; - - for (; m; m = m->next) - if (aspectMatch(aspect, (float)m->HDisplay / (float)m->VDisplay)) - return m; - - return NULL; -} - -static DisplayModePtr -bestModeForAspect(xf86CrtcConfigPtr config, Bool *enabled, float aspect) -{ - int o = -1, p; - DisplayModePtr mode = NULL, test = NULL, match = NULL; - - if (!nextEnabledOutput(config, enabled, &o)) - return NULL; - while ((mode = nextAspectMode(config->output[o], mode, aspect))) { - test = mode; - for (p = o; nextEnabledOutput(config, enabled, &p); ) { - test = xf86OutputFindClosestMode(config->output[p], mode); - if (!test) - break; - if (test->HDisplay != mode->HDisplay || - test->VDisplay != mode->VDisplay) { - test = NULL; - break; - } - } - - /* if we didn't match it on all outputs, try the next one */ - if (!test) - continue; - - /* if it's bigger than the last one, save it */ - if (!match || (test->HDisplay > match->HDisplay)) - match = test; - } - - /* return the biggest one found */ - return match; -} - -static Bool -xf86TargetPreferred(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, - DisplayModePtr *modes, Bool *enabled, - int width, int height) -{ - int o, p; - int max_pref_width = 0, max_pref_height = 0; - DisplayModePtr *preferred, *preferred_match; - Bool ret = FALSE; - - preferred = xnfcalloc(config->num_output, sizeof(DisplayModePtr)); - preferred_match = xnfcalloc(config->num_output, sizeof(DisplayModePtr)); - - /* Check if the preferred mode is available on all outputs */ - for (p = -1; nextEnabledOutput(config, enabled, &p); ) { - Rotation r = config->output[p]->initial_rotation; - DisplayModePtr mode; - if ((preferred[p] = xf86OutputHasPreferredMode(config->output[p], - width, height))) { - int pref_width = xf86ModeWidth(preferred[p], r); - int pref_height = xf86ModeHeight(preferred[p], r); - Bool all_match = TRUE; - - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - Bool match = FALSE; - xf86OutputPtr output = config->output[o]; - if (o == p) - continue; - - for (mode = output->probed_modes; mode; mode = mode->next) { - Rotation r = output->initial_rotation; - if (xf86ModeWidth(mode, r) == pref_width && - xf86ModeHeight(mode, r) == pref_height) { - preferred[o] = mode; - match = TRUE; - } - } - - all_match &= match; - } - - if (all_match && - (pref_width*pref_height > max_pref_width*max_pref_height)) { - for (o = -1; nextEnabledOutput(config, enabled, &o); ) - preferred_match[o] = preferred[o]; - max_pref_width = pref_width; - max_pref_height = pref_height; - ret = TRUE; - } - } - } - - /* - * If there's no preferred mode, but only one monitor, pick the - * biggest mode for its aspect ratio, assuming one exists. - */ - if (!ret) do { - int i = 0; - float aspect = 0.0; - - /* count the number of enabled outputs */ - for (i = 0, p = -1; nextEnabledOutput(config, enabled, &p); i++) ; - - if (i != 1) - break; - - p = -1; - nextEnabledOutput(config, enabled, &p); - if (config->output[p]->mm_height) - aspect = (float)config->output[p]->mm_width / - (float)config->output[p]->mm_height; - - if (aspect) - preferred_match[p] = bestModeForAspect(config, enabled, aspect); - - if (preferred_match[p]) - ret = TRUE; - - } while (0); - - if (ret) { - /* oh good, there is a match. stash the selected modes and return. */ - memcpy(modes, preferred_match, - config->num_output * sizeof(DisplayModePtr)); - } - - free(preferred); - free(preferred_match); - return ret; -} - -static Bool -xf86TargetAspect(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, - DisplayModePtr *modes, Bool *enabled, - int width, int height) -{ - int o; - float aspect = 0.0, *aspects; - xf86OutputPtr output; - Bool ret = FALSE; - DisplayModePtr guess = NULL, aspect_guess = NULL, base_guess = NULL; - - aspects = xnfcalloc(config->num_output, sizeof(float)); - - /* collect the aspect ratios */ - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - output = config->output[o]; - if (output->mm_height) - aspects[o] = (float)output->mm_width / (float)output->mm_height; - else - aspects[o] = 4.0 / 3.0; - } - - /* check that they're all the same */ - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - output = config->output[o]; - if (!aspect) { - aspect = aspects[o]; - } else if (!aspectMatch(aspect, aspects[o])) { - goto no_aspect_match; - } - } - - /* if they're all 4:3, just skip ahead and save effort */ - if (!aspectMatch(aspect, 4.0/3.0)) - aspect_guess = bestModeForAspect(config, enabled, aspect); - -no_aspect_match: - base_guess = bestModeForAspect(config, enabled, 4.0/3.0); - - guess = biggestMode(base_guess, aspect_guess); - - if (!guess) - goto out; - - /* found a mode that works everywhere, now apply it */ - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - modes[o] = xf86OutputFindClosestMode(config->output[o], guess); - } - ret = TRUE; - -out: - free(aspects); - return ret; -} - -static Bool -xf86TargetFallback(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, - DisplayModePtr *modes, Bool *enabled, - int width, int height) -{ - DisplayModePtr target_mode = NULL; - Rotation target_rotation = RR_Rotate_0; - DisplayModePtr default_mode; - int default_preferred, target_preferred = 0, o; - - /* User preferred > preferred > other modes */ - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - default_mode = xf86DefaultMode (config->output[o], width, height); - if (!default_mode) - continue; - - default_preferred = (((default_mode->type & M_T_PREFERRED) != 0) + - ((default_mode->type & M_T_USERPREF) != 0)); - - if (default_preferred > target_preferred || !target_mode) { - target_mode = default_mode; - target_preferred = default_preferred; - target_rotation = config->output[o]->initial_rotation; - config->compat_output = o; - } - } - - if (target_mode) - modes[config->compat_output] = target_mode; - - /* Fill in other output modes */ - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - if (!modes[o]) - modes[o] = xf86ClosestMode(config->output[o], target_mode, - target_rotation, width, height); - } - - return target_mode != NULL; -} - -static Bool -xf86TargetUserpref(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, - DisplayModePtr *modes, Bool *enabled, - int width, int height) -{ - int o; - - if (xf86UserConfiguredOutputs(scrn, modes)) - return xf86TargetFallback(scrn, config, modes, enabled, width, height); - - for (o = -1; nextEnabledOutput(config, enabled, &o); ) - if (xf86OutputHasUserPreferredMode(config->output[o])) - return - xf86TargetFallback(scrn, config, modes, enabled, width, height); - - return FALSE; -} - -static Bool -xf86CrtcSetInitialGamma(xf86CrtcPtr crtc, float gamma_red, float gamma_green, - float gamma_blue) -{ - int i, size = 256; - CARD16 *red, *green, *blue; - - red = malloc(3 * size * sizeof(CARD16)); - green = red + size; - blue = green + size; - - /* Only cause warning if user wanted gamma to be set. */ - if (!crtc->funcs->gamma_set && (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0)) { - free(red); - return FALSE; - } else if (!crtc->funcs->gamma_set) { - free(red); - return TRUE; - } - - /* At this early stage none of the randr-interface stuff is up. - * So take the default gamma size for lack of something better. - */ - for (i = 0; i < size; i++) { - if (gamma_red == 1.0) - red[i] = i << 8; - else - red[i] = (CARD16)(pow((double)i/(double)(size - 1), - 1. / (double)gamma_red) * (double)(size - 1) * 256); - - if (gamma_green == 1.0) - green[i] = i << 8; - else - green[i] = (CARD16)(pow((double)i/(double)(size - 1), - 1. / (double)gamma_green) * (double)(size - 1) * 256); - - if (gamma_blue == 1.0) - blue[i] = i << 8; - else - blue[i] = (CARD16)(pow((double)i/(double)(size - 1), - 1. / (double)gamma_blue) * (double)(size - 1) * 256); - } - - /* Default size is 256, so anything else is failure. */ - if (size != crtc->gamma_size) { - free(red); - return FALSE; - } - - crtc->gamma_size = size; - memcpy (crtc->gamma_red, red, crtc->gamma_size * sizeof (CARD16)); - memcpy (crtc->gamma_green, green, crtc->gamma_size * sizeof (CARD16)); - memcpy (crtc->gamma_blue, blue, crtc->gamma_size * sizeof (CARD16)); - - /* Do not set gamma now, delay until the crtc is activated. */ - - free(red); - - return TRUE; -} - -static Bool -xf86OutputSetInitialGamma(xf86OutputPtr output) -{ - XF86ConfMonitorPtr mon = output->conf_monitor; - float gamma_red = 1.0, gamma_green = 1.0, gamma_blue = 1.0; - - if (!mon) - return TRUE; - - if (!output->crtc) - return FALSE; - - /* Get configured values, where they exist. */ - if (mon->mon_gamma_red >= GAMMA_MIN && - mon->mon_gamma_red <= GAMMA_MAX) - gamma_red = mon->mon_gamma_red; - - if (mon->mon_gamma_green >= GAMMA_MIN && - mon->mon_gamma_green <= GAMMA_MAX) - gamma_green = mon->mon_gamma_green; - - if (mon->mon_gamma_blue >= GAMMA_MIN && - mon->mon_gamma_blue <= GAMMA_MAX) - gamma_blue = mon->mon_gamma_blue; - - /* This avoids setting gamma 1.0 in case another cloned output on this crtc has a specific gamma. */ - if (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0) { - xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "Output %s wants gamma correction (%.1f, %.1f, %.1f)\n", output->name, gamma_red, gamma_green, gamma_blue); - return xf86CrtcSetInitialGamma(output->crtc, gamma_red, gamma_green, gamma_blue); - }else - return TRUE; -} - -/** - * Construct default screen configuration - * - * Given auto-detected (and, eventually, configured) values, - * construct a usable configuration for the system - * - * canGrow indicates that the driver can resize the screen to larger than its - * initially configured size via the config->funcs->resize hook. If TRUE, this - * function will set virtualX and virtualY to match the initial configuration - * and leave config->max{Width,Height} alone. If FALSE, it will bloat - * virtual[XY] to include the largest modes and set config->max{Width,Height} - * accordingly. - */ - -Bool -xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o, c; - xf86CrtcPtr *crtcs; - DisplayModePtr *modes; - Bool *enabled; - int width, height; - int i = scrn->scrnIndex; - Bool have_outputs = TRUE; - Bool ret; - - /* Set up the device options */ - config->options = xnfalloc (sizeof (xf86DeviceOptions)); - memcpy (config->options, xf86DeviceOptions, sizeof (xf86DeviceOptions)); - xf86ProcessOptions (scrn->scrnIndex, - scrn->options, - config->options); - config->debug_modes = xf86ReturnOptValBool (config->options, - OPTION_MODEDEBUG, FALSE); - - if (scrn->display->virtualX) - width = scrn->display->virtualX; - else - width = config->maxWidth; - if (scrn->display->virtualY) - height = scrn->display->virtualY; - else - height = config->maxHeight; - - xf86ProbeOutputModes (scrn, width, height); - - crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr)); - modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr)); - enabled = xnfcalloc (config->num_output, sizeof (Bool)); - - ret = xf86CollectEnabledOutputs(scrn, config, enabled); - if (ret == FALSE && canGrow) { - xf86DrvMsg(i, X_WARNING, "Unable to find connected outputs - setting %dx%d initial framebuffer\n", - NO_OUTPUT_DEFAULT_WIDTH, NO_OUTPUT_DEFAULT_HEIGHT); - have_outputs = FALSE; - } else { - if (xf86TargetUserpref(scrn, config, modes, enabled, width, height)) - xf86DrvMsg(i, X_INFO, "Using user preference for initial modes\n"); - else if (xf86TargetPreferred(scrn, config, modes, enabled, width, height)) - xf86DrvMsg(i, X_INFO, "Using exact sizes for initial modes\n"); - else if (xf86TargetAspect(scrn, config, modes, enabled, width, height)) - xf86DrvMsg(i, X_INFO, "Using fuzzy aspect match for initial modes\n"); - else if (xf86TargetFallback(scrn, config, modes, enabled, width, height)) - xf86DrvMsg(i, X_INFO, "Using sloppy heuristic for initial modes\n"); - else - xf86DrvMsg(i, X_WARNING, "Unable to find initial modes\n"); - } - - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - if (!modes[o]) - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Output %s enabled but has no modes\n", - config->output[o]->name); - else - xf86DrvMsg (scrn->scrnIndex, X_INFO, - "Output %s using initial mode %s\n", - config->output[o]->name, modes[o]->name); - } - - /* - * Set the position of each output - */ - if (!xf86InitialOutputPositions (scrn, modes)) - { - free(crtcs); - free(modes); - return FALSE; - } - - /* - * Set initial panning of each output - */ - xf86InitialPanning (scrn); - - /* - * Assign CRTCs to fit output configuration - */ - if (have_outputs && !xf86PickCrtcs (scrn, crtcs, modes, 0, width, height)) - { - free(crtcs); - free(modes); - return FALSE; - } - - /* XXX override xf86 common frame computation code */ - - scrn->display->frameX0 = 0; - scrn->display->frameY0 = 0; - - for (c = 0; c < config->num_crtc; c++) - { - xf86CrtcPtr crtc = config->crtc[c]; - - crtc->enabled = FALSE; - memset (&crtc->desiredMode, '\0', sizeof (crtc->desiredMode)); - /* Set default gamma for all crtc's. */ - /* This is done to avoid problems later on with cloned outputs. */ - xf86CrtcSetInitialGamma(crtc, 1.0, 1.0, 1.0); - } - - if (xf86_crtc_supports_gamma(scrn)) - xf86DrvMsg(scrn->scrnIndex, X_INFO, "Using default gamma of (1.0, 1.0, 1.0) unless otherwise stated.\n"); - - /* - * Set initial configuration - */ - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - DisplayModePtr mode = modes[o]; - xf86CrtcPtr crtc = crtcs[o]; - - if (mode && crtc) - { - crtc->desiredMode = *mode; - crtc->desiredRotation = output->initial_rotation; - crtc->desiredX = output->initial_x; - crtc->desiredY = output->initial_y; - crtc->desiredTransformPresent = FALSE; - crtc->enabled = TRUE; - memcpy (&crtc->panningTotalArea, &output->initialTotalArea, sizeof(BoxRec)); - memcpy (&crtc->panningTrackingArea, &output->initialTrackingArea, sizeof(BoxRec)); - memcpy (crtc->panningBorder, output->initialBorder, 4*sizeof(INT16)); - output->crtc = crtc; - if (!xf86OutputSetInitialGamma(output)) - xf86DrvMsg (scrn->scrnIndex, X_WARNING, "Initial gamma correction for output %s: failed.\n", output->name); - } else { - output->crtc = NULL; - } - } - - if (scrn->display->virtualX == 0) - { - /* - * Expand virtual size to cover the current config and potential mode - * switches, if the driver can't enlarge the screen later. - */ - xf86DefaultScreenLimits (scrn, &width, &height, canGrow); - - if (have_outputs == FALSE) { - if (width < NO_OUTPUT_DEFAULT_WIDTH && height < NO_OUTPUT_DEFAULT_HEIGHT) { - width = NO_OUTPUT_DEFAULT_WIDTH; - height = NO_OUTPUT_DEFAULT_HEIGHT; - } - } - - scrn->display->virtualX = width; - scrn->display->virtualY = height; - } - - if (width > scrn->virtualX) - scrn->virtualX = width; - if (height > scrn->virtualY) - scrn->virtualY = height; - - /* - * Make sure the configuration isn't too small. - */ - if (width < config->minWidth || height < config->minHeight) - return FALSE; - - /* - * Limit the crtc config to virtual[XY] if the driver can't grow the - * desktop. - */ - if (!canGrow) - { - xf86CrtcSetSizeRange (scrn, config->minWidth, config->minHeight, - width, height); - } - - if (have_outputs) { - /* Mirror output modes to scrn mode list */ - xf86SetScrnInfoModes (scrn); - } else { - /* Clear any existing modes from scrn->modes */ - while (scrn->modes != NULL) - xf86DeleteMode(&scrn->modes, scrn->modes); - scrn->modes = xf86ModesAdd(scrn->modes, - xf86CVTMode(width, height, 60, 0, 0)); - } - - - free(crtcs); - free(modes); - return TRUE; -} - -/* - * Check the CRTC we're going to map each output to vs. it's current - * CRTC. If they don't match, we have to disable the output and the CRTC - * since the driver will have to re-route things. - */ -static void -xf86PrepareOutputs (ScrnInfoPtr scrn) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o; - - for (o = 0; o < config->num_output; o++) { - xf86OutputPtr output = config->output[o]; -#if RANDR_GET_CRTC_INTERFACE - /* Disable outputs that are unused or will be re-routed */ - if (!output->funcs->get_crtc || - output->crtc != (*output->funcs->get_crtc)(output) || - output->crtc == NULL) -#endif - (*output->funcs->dpms)(output, DPMSModeOff); - } -} - -static void -xf86PrepareCrtcs (ScrnInfoPtr scrn) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int c; - - for (c = 0; c < config->num_crtc; c++) { -#if RANDR_GET_CRTC_INTERFACE - xf86CrtcPtr crtc = config->crtc[c]; - xf86OutputPtr output = NULL; - uint32_t desired_outputs = 0, current_outputs = 0; - int o; - - for (o = 0; o < config->num_output; o++) { - output = config->output[o]; - if (output->crtc == crtc) - desired_outputs |= (1<<o); - /* If we can't tell where it's mapped, force it off */ - if (!output->funcs->get_crtc) { - desired_outputs = 0; - break; - } - if ((*output->funcs->get_crtc)(output) == crtc) - current_outputs |= (1<<o); - } - - /* - * If mappings are different or the CRTC is unused, - * we need to disable it - */ - if (desired_outputs != current_outputs || - !desired_outputs) - (*crtc->funcs->dpms)(crtc, DPMSModeOff); -#else - (*crtc->funcs->dpms)(crtc, DPMSModeOff); -#endif - } -} - -/* - * Using the desired mode information in each crtc, set - * modes (used in EnterVT functions, or at server startup) - */ - -Bool -xf86SetDesiredModes (ScrnInfoPtr scrn) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - xf86CrtcPtr crtc = config->crtc[0]; - int c; - - /* A driver with this hook will take care of this */ - if (!crtc->funcs->set_mode_major) { - xf86PrepareOutputs(scrn); - xf86PrepareCrtcs(scrn); - } - - for (c = 0; c < config->num_crtc; c++) - { - xf86OutputPtr output = NULL; - xf86CrtcSetRec set; - int o; - RRTransformPtr transform; - - crtc = config->crtc[c]; - - /* Skip disabled CRTCs */ - if (!crtc->enabled) - continue; - - if (xf86CompatOutput(scrn) && xf86CompatCrtc(scrn) == crtc) - output = xf86CompatOutput(scrn); - else - { - for (o = 0; o < config->num_output; o++) - if (config->output[o]->crtc == crtc) - { - output = config->output[o]; - break; - } - } - /* paranoia */ - if (!output) - continue; - - /* Mark that we'll need to re-set the mode for sure */ - memset(&crtc->mode, 0, sizeof(crtc->mode)); - if (!crtc->desiredMode.CrtcHDisplay) - { - DisplayModePtr mode = xf86OutputFindClosestMode (output, scrn->currentMode); - - if (!mode) - return FALSE; - crtc->desiredMode = *mode; - crtc->desiredRotation = RR_Rotate_0; - crtc->desiredTransformPresent = FALSE; - crtc->desiredX = 0; - crtc->desiredY = 0; - } - - if (crtc->desiredTransformPresent) - transform = &crtc->desiredTransform; - else - transform = NULL; - set.mode = &crtc->desiredMode; - set.rotation = crtc->desiredRotation; - set.transform = transform; - set.x = crtc->desiredX; - set.y = crtc->desiredY; - set.flags = (XF86CrtcSetMode | XF86CrtcSetOutput | - XF86CrtcSetOrigin | XF86CrtcSetTransform | - XF86CrtcSetRotation); - if (!xf86CrtcSet(crtc, &set)) - return FALSE; - } - - xf86DisableUnusedFunctions(scrn); - return TRUE; -} - -/** - * In the current world order, there are lists of modes per output, which may - * or may not include the mode that was asked to be set by XFree86's mode - * selection. Find the closest one, in the following preference order: - * - * - Equality - * - Closer in size to the requested mode, but no larger - * - Closer in refresh rate to the requested mode. - */ - -DisplayModePtr -xf86OutputFindClosestMode (xf86OutputPtr output, DisplayModePtr desired) -{ - DisplayModePtr best = NULL, scan = NULL; - - for (scan = output->probed_modes; scan != NULL; scan = scan->next) - { - /* If there's an exact match, we're done. */ - if (xf86ModesEqual(scan, desired)) { - best = desired; - break; - } - - /* Reject if it's larger than the desired mode. */ - if (scan->HDisplay > desired->HDisplay || - scan->VDisplay > desired->VDisplay) - { - continue; - } - - /* - * If we haven't picked a best mode yet, use the first - * one in the size range - */ - if (best == NULL) - { - best = scan; - continue; - } - - /* Find if it's closer to the right size than the current best - * option. - */ - if ((scan->HDisplay > best->HDisplay && - scan->VDisplay >= best->VDisplay) || - (scan->HDisplay >= best->HDisplay && - scan->VDisplay > best->VDisplay)) - { - best = scan; - continue; - } - - /* Find if it's still closer to the right refresh than the current - * best resolution. - */ - if (scan->HDisplay == best->HDisplay && - scan->VDisplay == best->VDisplay && - (fabs(scan->VRefresh - desired->VRefresh) < - fabs(best->VRefresh - desired->VRefresh))) { - best = scan; - } - } - return best; -} - -/** - * When setting a mode through XFree86-VidModeExtension or XFree86-DGA, - * take the specified mode and apply it to the crtc connected to the compat - * output. Then, find similar modes for the other outputs, as with the - * InitialConfiguration code above. The goal is to clone the desired - * mode across all outputs that are currently active. - */ - -Bool -xf86SetSingleMode (ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - Bool ok = TRUE; - xf86OutputPtr compat_output; - DisplayModePtr compat_mode = NULL; - int c; - - /* - * Let the compat output drive the final mode selection - */ - compat_output = xf86CompatOutput(pScrn); - if (compat_output) - compat_mode = xf86OutputFindClosestMode (compat_output, desired); - if (compat_mode) - desired = compat_mode; - - for (c = 0; c < config->num_crtc; c++) - { - xf86CrtcPtr crtc = config->crtc[c]; - DisplayModePtr crtc_mode = NULL; - int o; - xf86CrtcSetRec set; - - if (!crtc->enabled) - continue; - - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - DisplayModePtr output_mode; - - /* skip outputs not on this crtc */ - if (output->crtc != crtc) - continue; - - if (crtc_mode) - { - output_mode = xf86OutputFindClosestMode (output, crtc_mode); - if (output_mode != crtc_mode) - output->crtc = NULL; - } - else - crtc_mode = xf86OutputFindClosestMode (output, desired); - } - if (!crtc_mode) - { - crtc->enabled = FALSE; - continue; - } - set.mode = crtc_mode; - set.rotation = rotation; - set.transform = NULL; - set.x = 0; - set.y = 0; - set.flags = (XF86CrtcSetMode | XF86CrtcSetOutput | - XF86CrtcSetOrigin | XF86CrtcSetTransform | - XF86CrtcSetRotation); - if (!xf86CrtcSet (crtc, &set)) - ok = FALSE; - else - { - crtc->desiredMode = *crtc_mode; - crtc->desiredRotation = rotation; - crtc->desiredTransformPresent = FALSE; - crtc->desiredX = 0; - crtc->desiredY = 0; - } - } - xf86DisableUnusedFunctions(pScrn); -#ifdef RANDR_12_INTERFACE - xf86RandR12TellChanged (pScrn->pScreen); -#endif - return ok; -} - - -/** - * Set the DPMS power mode of all outputs and CRTCs. - * - * If the new mode is off, it will turn off outputs and then CRTCs. - * Otherwise, it will affect CRTCs before outputs. - */ -void -xf86DPMSSet(ScrnInfoPtr scrn, int mode, int flags) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int i; - - if (!scrn->vtSema) - return; - - if (mode == DPMSModeOff) { - for (i = 0; i < config->num_output; i++) { - xf86OutputPtr output = config->output[i]; - if (output->crtc != NULL) - (*output->funcs->dpms) (output, mode); - } - } - - for (i = 0; i < config->num_crtc; i++) { - xf86CrtcPtr crtc = config->crtc[i]; - if (crtc->enabled) - (*crtc->funcs->dpms) (crtc, mode); - } - - if (mode != DPMSModeOff) { - for (i = 0; i < config->num_output; i++) { - xf86OutputPtr output = config->output[i]; - if (output->crtc != NULL) - (*output->funcs->dpms) (output, mode); - } - } -} - -/** - * Implement the screensaver by just calling down into the driver DPMS hooks. - * - * Even for monitors with no DPMS support, by the definition of our DPMS hooks, - * the outputs will still get disabled (blanked). - */ -Bool -xf86SaveScreen(ScreenPtr pScreen, int mode) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - - if (xf86IsUnblank(mode)) - xf86DPMSSet(pScrn, DPMSModeOn, 0); - else - xf86DPMSSet(pScrn, DPMSModeOff, 0); - - return TRUE; -} - -/** - * Disable all inactive crtcs and outputs - */ -void -xf86DisableUnusedFunctions(ScrnInfoPtr pScrn) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - int o, c; - - for (o = 0; o < xf86_config->num_output; o++) - { - xf86OutputPtr output = xf86_config->output[o]; - if (!output->crtc) - (*output->funcs->dpms)(output, DPMSModeOff); - } - - for (c = 0; c < xf86_config->num_crtc; c++) - { - xf86CrtcPtr crtc = xf86_config->crtc[c]; - - if (!crtc->enabled) - { - crtc->funcs->dpms(crtc, DPMSModeOff); - memset(&crtc->mode, 0, sizeof(crtc->mode)); - xf86RotateDestroy(crtc); - crtc->active = FALSE; - } - } - if (pScrn->pScreen) - xf86_crtc_notify(pScrn->pScreen); - if (pScrn->ModeSet) - pScrn->ModeSet(pScrn); -} - -#ifdef RANDR_12_INTERFACE - -#define EDID_ATOM_NAME "EDID" - -/** - * Set the RandR EDID property - */ -static void -xf86OutputSetEDIDProperty (xf86OutputPtr output, void *data, int data_len) -{ - Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME) - 1, TRUE); - - /* This may get called before the RandR resources have been created */ - if (output->randr_output == NULL) - return; - - if (data_len != 0) { - RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8, - PropModeReplace, data_len, data, FALSE, TRUE); - } else { - RRDeleteOutputProperty(output->randr_output, edid_atom); - } -} - -#endif - -/* Pull out a phyiscal size from a detailed timing if available. */ -struct det_phySize_parameter { - xf86OutputPtr output; - ddc_quirk_t quirks; - Bool ret; -}; - -static void handle_detailed_physical_size(struct detailed_monitor_section - *det_mon, void *data) -{ - struct det_phySize_parameter *p; - p = (struct det_phySize_parameter *)data; - - if (p->ret == TRUE ) - return ; - - xf86DetTimingApplyQuirks(det_mon, p->quirks, - p->output->MonInfo->features.hsize, - p->output->MonInfo->features.vsize); - if (det_mon->type == DT && - det_mon->section.d_timings.h_size != 0 && - det_mon->section.d_timings.v_size != 0) { - - p->output->mm_width = det_mon->section.d_timings.h_size; - p->output->mm_height = det_mon->section.d_timings.v_size; - p->ret = TRUE; - } -} - -/** - * Set the EDID information for the specified output - */ -void -xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon) -{ - ScrnInfoPtr scrn = output->scrn; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - Bool debug_modes = config->debug_modes || xf86Initialising; -#ifdef RANDR_12_INTERFACE - int size; -#endif - - free(output->MonInfo); - - output->MonInfo = edid_mon; - output->mm_width = 0; - output->mm_height = 0; - - if (debug_modes) { - xf86DrvMsg(scrn->scrnIndex, X_INFO, "EDID for output %s\n", - output->name); - xf86PrintEDID(edid_mon); - } - - /* Set the DDC properties for the 'compat' output */ - if (output == xf86CompatOutput(scrn)) - xf86SetDDCproperties(scrn, edid_mon); - -#ifdef RANDR_12_INTERFACE - /* Set the RandR output properties */ - size = 0; - if (edid_mon) - { - if (edid_mon->ver.version == 1) { - size = 128; - if (edid_mon->flags & EDID_COMPLETE_RAWDATA) - size += edid_mon->no_sections * 128; - } else if (edid_mon->ver.version == 2) - size = 256; - } - xf86OutputSetEDIDProperty (output, edid_mon ? edid_mon->rawData : NULL, size); -#endif - - if (edid_mon) { - - struct det_phySize_parameter p; - p.output = output; - p.quirks = xf86DDCDetectQuirks(scrn->scrnIndex,edid_mon, FALSE); - p.ret = FALSE; - xf86ForEachDetailedBlock(edid_mon, - handle_detailed_physical_size, &p); - - /* if no mm size is available from a detailed timing, check the max size field */ - if ((!output->mm_width || !output->mm_height) && - (edid_mon->features.hsize && edid_mon->features.vsize)) - { - output->mm_width = edid_mon->features.hsize * 10; - output->mm_height = edid_mon->features.vsize * 10; - } - } -} - -/** - * Return the list of modes supported by the EDID information - * stored in 'output' - */ -DisplayModePtr -xf86OutputGetEDIDModes (xf86OutputPtr output) -{ - ScrnInfoPtr scrn = output->scrn; - xf86MonPtr edid_mon = output->MonInfo; - - if (!edid_mon) - return NULL; - return xf86DDCGetModes(scrn->scrnIndex, edid_mon); -} - -/* maybe we should care about DDC1? meh. */ -xf86MonPtr -xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus) -{ - ScrnInfoPtr scrn = output->scrn; - xf86MonPtr mon; - - mon = xf86DoEEDID(scrn->scrnIndex, pDDCBus, TRUE); - if (mon) - xf86DDCApplyQuirks(scrn->scrnIndex, mon); - - return mon; -} - -static char *_xf86ConnectorNames[] = { - "None", "VGA", "DVI-I", "DVI-D", - "DVI-A", "Composite", "S-Video", - "Component", "LFP", "Proprietary", - "HDMI", "DisplayPort", - }; -char * -xf86ConnectorGetName(xf86ConnectorType connector) -{ - return _xf86ConnectorNames[connector]; -} - -static void -x86_crtc_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b) -{ - dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1; - dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2; - dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1; - dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2; - - if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2) - dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; -} - -static void -x86_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box) -{ - if (crtc->enabled) { - crtc_box->x1 = crtc->x; - crtc_box->x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation); - crtc_box->y1 = crtc->y; - crtc_box->y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation); - } else - crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0; -} - -static int -xf86_crtc_box_area(BoxPtr box) -{ - return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1); -} - -/* - * Return the crtc covering 'box'. If two crtcs cover a portion of - * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc - * with greater coverage - */ - -static xf86CrtcPtr -xf86_covering_crtc(ScrnInfoPtr pScrn, - BoxPtr box, - xf86CrtcPtr desired, - BoxPtr crtc_box_ret) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - xf86CrtcPtr crtc, best_crtc; - int coverage, best_coverage; - int c; - BoxRec crtc_box, cover_box; - - best_crtc = NULL; - best_coverage = 0; - crtc_box_ret->x1 = 0; - crtc_box_ret->x2 = 0; - crtc_box_ret->y1 = 0; - crtc_box_ret->y2 = 0; - for (c = 0; c < xf86_config->num_crtc; c++) { - crtc = xf86_config->crtc[c]; - x86_crtc_box(crtc, &crtc_box); - x86_crtc_box_intersect(&cover_box, &crtc_box, box); - coverage = xf86_crtc_box_area(&cover_box); - if (coverage && crtc == desired) { - *crtc_box_ret = crtc_box; - return crtc; - } else if (coverage > best_coverage) { - *crtc_box_ret = crtc_box; - best_crtc = crtc; - best_coverage = coverage; - } - } - return best_crtc; -} - -/* - * For overlay video, compute the relevant CRTC and - * clip video to that. - * - * returning FALSE means there was a memory failure of some kind, - * not that the video shouldn't be displayed - */ - -Bool -xf86_crtc_clip_video_helper(ScrnInfoPtr pScrn, - xf86CrtcPtr *crtc_ret, - xf86CrtcPtr desired_crtc, - BoxPtr dst, - INT32 *xa, - INT32 *xb, - INT32 *ya, - INT32 *yb, - RegionPtr reg, - INT32 width, - INT32 height) -{ - Bool ret; - RegionRec crtc_region_local; - RegionPtr crtc_region = reg; - - if (crtc_ret) { - BoxRec crtc_box; - xf86CrtcPtr crtc = xf86_covering_crtc(pScrn, dst, - desired_crtc, - &crtc_box); - - if (crtc) { - RegionInit(&crtc_region_local, &crtc_box, 1); - crtc_region = &crtc_region_local; - RegionIntersect(crtc_region, crtc_region, reg); - } - *crtc_ret = crtc; - } - - ret = xf86XVClipVideoHelper(dst, xa, xb, ya, yb, - crtc_region, width, height); - - if (crtc_region != reg) - RegionUninit(&crtc_region_local); - - return ret; -} - -xf86_crtc_notify_proc_ptr -xf86_wrap_crtc_notify (ScreenPtr screen, xf86_crtc_notify_proc_ptr new) -{ - if (xf86CrtcConfigPrivateIndex != -1) - { - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - xf86_crtc_notify_proc_ptr old; - - old = config->xf86_crtc_notify; - config->xf86_crtc_notify = new; - return old; - } - return NULL; -} - -void -xf86_unwrap_crtc_notify(ScreenPtr screen, xf86_crtc_notify_proc_ptr old) -{ - if (xf86CrtcConfigPrivateIndex != -1) - { - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - - config->xf86_crtc_notify = old; - } -} - -void -xf86_crtc_notify(ScreenPtr screen) -{ - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - - if (config->xf86_crtc_notify) - config->xf86_crtc_notify(screen); -} - -Bool -xf86_crtc_supports_gamma(ScrnInfoPtr pScrn) -{ - if (xf86CrtcConfigPrivateIndex != -1) { - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - xf86CrtcPtr crtc; - - /* for multiple drivers loaded we need this */ - if (!xf86_config) - return FALSE; - if (xf86_config->num_crtc == 0) - return FALSE; - crtc = xf86_config->crtc[0]; - - return crtc->funcs->gamma_set != NULL; - } - - return FALSE; -} +/*
+ * Copyright © 2006 Keith Packard
+ * Copyright © 2008 Red Hat, 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS 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>
+#else
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#endif
+
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "xf86.h"
+#include "xf86DDC.h"
+#include "xf86Crtc.h"
+#include "xf86Modes.h"
+#include "xf86Priv.h"
+#include "xf86RandR12.h"
+#include "X11/extensions/render.h"
+#include "X11/extensions/dpmsconst.h"
+#include "X11/Xatom.h"
+#include "picturestr.h"
+
+#include "xf86xv.h"
+
+#define NO_OUTPUT_DEFAULT_WIDTH 1024
+#define NO_OUTPUT_DEFAULT_HEIGHT 768
+/*
+ * Initialize xf86CrtcConfig structure
+ */
+
+int xf86CrtcConfigPrivateIndex = -1;
+
+void
+xf86CrtcConfigInit (ScrnInfoPtr scrn,
+ const xf86CrtcConfigFuncsRec *funcs)
+{
+ xf86CrtcConfigPtr config;
+
+ if (xf86CrtcConfigPrivateIndex == -1)
+ xf86CrtcConfigPrivateIndex = xf86AllocateScrnInfoPrivateIndex();
+ config = xnfcalloc (1, sizeof (xf86CrtcConfigRec));
+
+ config->funcs = funcs;
+
+ scrn->privates[xf86CrtcConfigPrivateIndex].ptr = config;
+}
+
+void
+xf86CrtcSetSizeRange (ScrnInfoPtr scrn,
+ int minWidth, int minHeight,
+ int maxWidth, int maxHeight)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+
+ config->minWidth = minWidth;
+ config->minHeight = minHeight;
+ config->maxWidth = maxWidth;
+ config->maxHeight = maxHeight;
+}
+
+void
+xf86CrtcSetScanoutFormats(ScrnInfoPtr scrn,
+ int num_formats,
+ xf86CrtcScanoutFormat *formats)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+
+ config->num_scanout_formats = num_formats;
+ config->scanout_formats = formats;
+}
+
+/*
+ * Crtc functions
+ */
+xf86CrtcPtr
+xf86CrtcCreate (ScrnInfoPtr scrn,
+ const xf86CrtcFuncsRec *funcs)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ xf86CrtcPtr crtc, *crtcs;
+
+ crtc = calloc(sizeof (xf86CrtcRec), 1);
+ if (!crtc)
+ return NULL;
+ crtc->version = XF86_CRTC_VERSION;
+ crtc->scrn = scrn;
+ crtc->funcs = funcs;
+#ifdef RANDR_12_INTERFACE
+ crtc->randr_crtc = NULL;
+#endif
+ crtc->rotation = RR_Rotate_0;
+ crtc->desiredRotation = RR_Rotate_0;
+ pixman_transform_init_identity (&crtc->crtc_to_framebuffer);
+ pixman_f_transform_init_identity (&crtc->f_crtc_to_framebuffer);
+ pixman_f_transform_init_identity (&crtc->f_framebuffer_to_crtc);
+ pixman_f_transform_init_identity (&crtc->f_screen_to_crtc);
+ pixman_f_transform_init_identity (&crtc->user_sprite_position_transform);
+ pixman_f_transform_init_identity (&crtc->f_crtc_to_cursor);
+ pixman_f_transform_init_identity (&crtc->user_sprite_image_transform);
+ crtc->filter = NULL;
+ crtc->params = NULL;
+ crtc->nparams = 0;
+ crtc->filter_width = 0;
+ crtc->filter_height = 0;
+ crtc->transform_in_use = FALSE;
+ crtc->sprite_transform_in_use = FALSE;
+ crtc->transformPresent = FALSE;
+ crtc->desiredTransformPresent = FALSE;
+ memset (&crtc->bounds, '\0', sizeof (crtc->bounds));
+
+ /* Preallocate gamma at a sensible size. */
+ crtc->gamma_size = 256;
+ crtc->gamma_red = malloc(3 * crtc->gamma_size * sizeof (CARD16));
+ if (!crtc->gamma_red) {
+ free(crtc);
+ return NULL;
+ }
+ crtc->gamma_green = crtc->gamma_red + crtc->gamma_size;
+ crtc->gamma_blue = crtc->gamma_green + crtc->gamma_size;
+
+ if (xf86_config->crtc)
+ crtcs = realloc(xf86_config->crtc,
+ (xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr));
+ else
+ crtcs = malloc((xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr));
+ if (!crtcs)
+ {
+ free(crtc);
+ return NULL;
+ }
+ xf86_config->crtc = crtcs;
+ xf86_config->crtc[xf86_config->num_crtc++] = crtc;
+ return crtc;
+}
+
+void
+xf86CrtcDestroy (xf86CrtcPtr crtc)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+ int c;
+
+ (*crtc->funcs->destroy) (crtc);
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ if (xf86_config->crtc[c] == crtc)
+ {
+ memmove (&xf86_config->crtc[c],
+ &xf86_config->crtc[c+1],
+ ((xf86_config->num_crtc - (c + 1)) * sizeof(void*)));
+ xf86_config->num_crtc--;
+ break;
+ }
+ free(crtc->params);
+ free(crtc->gamma_red);
+ free(crtc);
+}
+
+
+/**
+ * Return whether any outputs are connected to the specified pipe
+ */
+
+Bool
+xf86CrtcInUse (xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int o;
+
+ for (o = 0; o < xf86_config->num_output; o++)
+ if (xf86_config->output[o]->crtc == crtc)
+ return TRUE;
+ return FALSE;
+}
+
+void
+xf86CrtcSetScreenSubpixelOrder (ScreenPtr pScreen)
+{
+ int subpixel_order = SubPixelUnknown;
+ Bool has_none = FALSE;
+ ScrnInfoPtr scrn = xf86Screens[pScreen->myNum];
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c, o;
+
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+ for (o = 0; o < xf86_config->num_output; o++)
+ {
+ xf86OutputPtr output = xf86_config->output[o];
+
+ if (output->crtc == crtc)
+ {
+ switch (output->subpixel_order) {
+ case SubPixelNone:
+ has_none = TRUE;
+ break;
+ case SubPixelUnknown:
+ break;
+ default:
+ subpixel_order = output->subpixel_order;
+ break;
+ }
+ }
+ if (subpixel_order != SubPixelUnknown)
+ break;
+ }
+ if (subpixel_order != SubPixelUnknown)
+ {
+ static const int circle[4] = {
+ SubPixelHorizontalRGB,
+ SubPixelVerticalRGB,
+ SubPixelHorizontalBGR,
+ SubPixelVerticalBGR,
+ };
+ int rotate;
+ int c;
+ for (rotate = 0; rotate < 4; rotate++)
+ if (crtc->rotation & (1 << rotate))
+ break;
+ for (c = 0; c < 4; c++)
+ if (circle[c] == subpixel_order)
+ break;
+ c = (c + rotate) & 0x3;
+ if ((crtc->rotation & RR_Reflect_X) && !(c & 1))
+ c ^= 2;
+ if ((crtc->rotation & RR_Reflect_Y) && (c & 1))
+ c ^= 2;
+ subpixel_order = circle[c];
+ break;
+ }
+ }
+ if (subpixel_order == SubPixelUnknown && has_none)
+ subpixel_order = SubPixelNone;
+ PictureSetSubpixelOrder (pScreen, subpixel_order);
+}
+
+/**
+ * Sets the given video mode on the given crtc
+ */
+Bool
+xf86CrtcSet(xf86CrtcPtr crtc, xf86CrtcSetRec *set)
+{
+ ScrnInfoPtr scrn = crtc->scrn;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int i;
+ Bool ret = FALSE;
+ Bool didLock = FALSE;
+ DisplayModePtr adjusted_mode = NULL;
+ DisplayModeRec saved_mode;
+ int saved_x, saved_y;
+ Rotation saved_rotation;
+ RRTransformRec saved_transform;
+ Bool saved_transform_present;
+ PixmapPtr saved_scanout_pixmap;
+
+ crtc->enabled = xf86CrtcInUse (crtc);
+
+ /* We only hit this if someone explicitly sends a "disabled" modeset. */
+ if (!crtc->enabled)
+ {
+ /* Check everything for stuff that should be off. */
+ xf86DisableUnusedFunctions(scrn);
+ return TRUE;
+ }
+
+ /* See if nothing has changed */
+ if (!set->flags)
+ return TRUE;
+
+ saved_mode = crtc->mode;
+ saved_x = crtc->x;
+ saved_y = crtc->y;
+ saved_rotation = crtc->rotation;
+ saved_scanout_pixmap = crtc->scanoutPixmap;
+ if (crtc->transformPresent) {
+ RRTransformInit (&saved_transform);
+ RRTransformCopy (&saved_transform, &crtc->transform);
+ }
+ saved_transform_present = crtc->transformPresent;
+
+ /* Update crtc values up front so the driver can rely on them for mode
+ * setting.
+ */
+ if (set->flags & XF86CrtcSetMode)
+ crtc->mode = *set->mode;
+ if (set->flags & XF86CrtcSetOrigin) {
+ crtc->x = set->x;
+ crtc->y = set->y;
+ }
+ if (set->flags & XF86CrtcSetRotation)
+ crtc->rotation = set->rotation;
+ if (set->flags & XF86CrtcSetScanoutPixmap)
+ crtc->scanoutPixmap = set->scanout_pixmap;
+
+ if (set->flags & XF86CrtcSetTransform) {
+ if (set->transform) {
+ RRTransformCopy (&crtc->transform, set->transform);
+ crtc->transformPresent = TRUE;
+ } else
+ crtc->transformPresent = FALSE;
+ }
+
+ if (crtc->funcs->set) {
+ ret = crtc->funcs->set(crtc, set->flags);
+ goto done;
+ }
+
+ if (set->flags == XF86CrtcSetOrigin && crtc->funcs->set_origin) {
+ ret = xf86CrtcRotate(crtc);
+ if (ret)
+ crtc->funcs->set_origin(crtc, crtc->x, crtc->y);
+ goto done;
+ }
+
+ if (crtc->funcs->set_mode_major) {
+ ret = crtc->funcs->set_mode_major(crtc, &crtc->mode,
+ crtc->rotation,
+ crtc->x, crtc->y);
+ goto done;
+ }
+
+ adjusted_mode = xf86DuplicateMode(&crtc->mode);
+
+ didLock = crtc->funcs->lock (crtc);
+ /* Pass our mode to the outputs and the CRTC to give them a chance to
+ * adjust it according to limitations or output properties, and also
+ * a chance to reject the mode entirely.
+ */
+ for (i = 0; i < xf86_config->num_output; i++) {
+ xf86OutputPtr output = xf86_config->output[i];
+
+ if (output->crtc != crtc)
+ continue;
+
+ if (!output->funcs->mode_fixup(output, &crtc->mode, adjusted_mode)) {
+ goto done;
+ }
+ }
+
+ if (!crtc->funcs->mode_fixup(crtc, &crtc->mode, adjusted_mode)) {
+ goto done;
+ }
+
+ if (!xf86CrtcRotate (crtc))
+ goto done;
+
+ /* Prepare the outputs and CRTCs before setting the mode. */
+ for (i = 0; i < xf86_config->num_output; i++) {
+ xf86OutputPtr output = xf86_config->output[i];
+
+ if (output->crtc != crtc)
+ continue;
+
+ /* Disable the output as the first thing we do. */
+ output->funcs->prepare(output);
+ }
+
+ crtc->funcs->prepare(crtc);
+
+ /* Set up the DPLL and any output state that needs to adjust or depend
+ * on the DPLL.
+ */
+ crtc->funcs->mode_set(crtc, &crtc->mode, adjusted_mode, crtc->x, crtc->y);
+ for (i = 0; i < xf86_config->num_output; i++)
+ {
+ xf86OutputPtr output = xf86_config->output[i];
+ if (output->crtc == crtc)
+ output->funcs->mode_set(output, &crtc->mode, adjusted_mode);
+ }
+
+ /* Only upload when needed, to avoid unneeded delays. */
+ if (!crtc->active && crtc->funcs->gamma_set)
+ crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
+ crtc->gamma_blue, crtc->gamma_size);
+
+ /* Now, enable the clocks, plane, pipe, and outputs that we set up. */
+ crtc->funcs->commit(crtc);
+ for (i = 0; i < xf86_config->num_output; i++)
+ {
+ xf86OutputPtr output = xf86_config->output[i];
+ if (output->crtc == crtc)
+ output->funcs->commit(output);
+ }
+
+ ret = TRUE;
+
+done:
+ if (ret) {
+ crtc->active = TRUE;
+ if (scrn->pScreen)
+ xf86CrtcSetScreenSubpixelOrder (scrn->pScreen);
+ if (scrn->ModeSet)
+ scrn->ModeSet(scrn);
+ } else {
+ crtc->x = saved_x;
+ crtc->y = saved_y;
+ crtc->rotation = saved_rotation;
+ crtc->mode = saved_mode;
+ if (saved_transform_present)
+ RRTransformCopy (&crtc->transform, &saved_transform);
+ crtc->transformPresent = saved_transform_present;
+ crtc->scanoutPixmap = saved_scanout_pixmap;
+ }
+
+ if (adjusted_mode) {
+ free(adjusted_mode->name);
+ free(adjusted_mode);
+ }
+
+ if (didLock)
+ crtc->funcs->unlock (crtc);
+
+ return ret;
+}
+
+/**
+ * Pans the screen, does not change the mode
+ */
+void
+xf86CrtcSetOrigin (xf86CrtcPtr crtc, int x, int y)
+{
+ xf86CrtcSetRec set;
+
+ if (x != crtc->x || y != crtc->y) {
+ set.x = x;
+ set.y = y;
+ set.flags = XF86CrtcSetOrigin;
+ (void) xf86CrtcSet(crtc, &set);
+ }
+}
+
+/*
+ * Output functions
+ */
+
+extern XF86ConfigPtr xf86configptr;
+
+typedef enum {
+ OPTION_PREFERRED_MODE,
+ OPTION_POSITION,
+ OPTION_BELOW,
+ OPTION_RIGHT_OF,
+ OPTION_ABOVE,
+ OPTION_LEFT_OF,
+ OPTION_ENABLE,
+ OPTION_DISABLE,
+ OPTION_MIN_CLOCK,
+ OPTION_MAX_CLOCK,
+ OPTION_IGNORE,
+ OPTION_ROTATE,
+ OPTION_PANNING,
+ OPTION_PRIMARY,
+ OPTION_DEFAULT_MODES,
+} OutputOpts;
+
+static OptionInfoRec xf86OutputOptions[] = {
+ {OPTION_PREFERRED_MODE, "PreferredMode", OPTV_STRING, {0}, FALSE },
+ {OPTION_POSITION, "Position", OPTV_STRING, {0}, FALSE },
+ {OPTION_BELOW, "Below", OPTV_STRING, {0}, FALSE },
+ {OPTION_RIGHT_OF, "RightOf", OPTV_STRING, {0}, FALSE },
+ {OPTION_ABOVE, "Above", OPTV_STRING, {0}, FALSE },
+ {OPTION_LEFT_OF, "LeftOf", OPTV_STRING, {0}, FALSE },
+ {OPTION_ENABLE, "Enable", OPTV_BOOLEAN, {0}, FALSE },
+ {OPTION_DISABLE, "Disable", OPTV_BOOLEAN, {0}, FALSE },
+ {OPTION_MIN_CLOCK, "MinClock", OPTV_FREQ, {0}, FALSE },
+ {OPTION_MAX_CLOCK, "MaxClock", OPTV_FREQ, {0}, FALSE },
+ {OPTION_IGNORE, "Ignore", OPTV_BOOLEAN, {0}, FALSE },
+ {OPTION_ROTATE, "Rotate", OPTV_STRING, {0}, FALSE },
+ {OPTION_PANNING, "Panning", OPTV_STRING, {0}, FALSE },
+ {OPTION_PRIMARY, "Primary", OPTV_BOOLEAN, {0}, FALSE },
+ {OPTION_DEFAULT_MODES, "DefaultModes", OPTV_BOOLEAN, {0}, FALSE },
+ {-1, NULL, OPTV_NONE, {0}, FALSE },
+};
+
+enum {
+ OPTION_MODEDEBUG,
+};
+
+static OptionInfoRec xf86DeviceOptions[] = {
+ {OPTION_MODEDEBUG, "ModeDebug", OPTV_BOOLEAN, {0}, FALSE },
+ {-1, NULL, OPTV_NONE, {0}, FALSE },
+};
+
+static void
+xf86OutputSetMonitor (xf86OutputPtr output)
+{
+ char *option_name;
+ char *monitor;
+
+ if (!output->name)
+ return;
+
+ free(output->options);
+
+ output->options = xnfalloc (sizeof (xf86OutputOptions));
+ memcpy (output->options, xf86OutputOptions, sizeof (xf86OutputOptions));
+
+ XNFasprintf(&option_name, "monitor-%s", output->name);
+ monitor = xf86findOptionValue (output->scrn->options, option_name);
+ if (!monitor)
+ monitor = output->name;
+ else
+ xf86MarkOptionUsedByName (output->scrn->options, option_name);
+ free(option_name);
+ output->conf_monitor = xf86findMonitor (monitor,
+ xf86configptr->conf_monitor_lst);
+ /*
+ * Find the monitor section of the screen and use that
+ */
+ if (!output->conf_monitor && output->use_screen_monitor)
+ output->conf_monitor = xf86findMonitor (output->scrn->monitor->id,
+ xf86configptr->conf_monitor_lst);
+ if (output->conf_monitor)
+ {
+ xf86DrvMsg (output->scrn->scrnIndex, X_INFO,
+ "Output %s using monitor section %s\n",
+ output->name, output->conf_monitor->mon_identifier);
+ xf86ProcessOptions (output->scrn->scrnIndex,
+ output->conf_monitor->mon_option_lst,
+ output->options);
+ }
+ else
+ xf86DrvMsg (output->scrn->scrnIndex, X_INFO,
+ "Output %s has no monitor section\n",
+ output->name);
+}
+
+static Bool
+xf86OutputEnabled (xf86OutputPtr output, Bool strict)
+{
+ Bool enable, disable;
+
+ /* check to see if this output was enabled in the config file */
+ if (xf86GetOptValBool (output->options, OPTION_ENABLE, &enable) && enable)
+ {
+ xf86DrvMsg (output->scrn->scrnIndex, X_INFO,
+ "Output %s enabled by config file\n", output->name);
+ return TRUE;
+ }
+ /* or if this output was disabled in the config file */
+ if (xf86GetOptValBool (output->options, OPTION_DISABLE, &disable) && disable)
+ {
+ xf86DrvMsg (output->scrn->scrnIndex, X_INFO,
+ "Output %s disabled by config file\n", output->name);
+ return FALSE;
+ }
+
+ /* If not, try to only light up the ones we know are connected */
+ if (strict) {
+ enable = output->status == XF86OutputStatusConnected;
+ }
+ /* But if that fails, try to light up even outputs we're unsure of */
+ else {
+ enable = output->status != XF86OutputStatusDisconnected;
+ }
+
+ xf86DrvMsg (output->scrn->scrnIndex, X_INFO,
+ "Output %s %sconnected\n", output->name, enable ? "" : "dis");
+ return enable;
+}
+
+static Bool
+xf86OutputIgnored (xf86OutputPtr output)
+{
+ return xf86ReturnOptValBool (output->options, OPTION_IGNORE, FALSE);
+}
+
+static char *direction[4] = {
+ "normal",
+ "left",
+ "inverted",
+ "right"
+};
+
+static Rotation
+xf86OutputInitialRotation (xf86OutputPtr output)
+{
+ char *rotate_name = xf86GetOptValString (output->options,
+ OPTION_ROTATE);
+ int i;
+
+ if (!rotate_name) {
+ if (output->initial_rotation)
+ return output->initial_rotation;
+ return RR_Rotate_0;
+ }
+
+ for (i = 0; i < 4; i++)
+ if (xf86nameCompare (direction[i], rotate_name) == 0)
+ return 1 << i;
+ return RR_Rotate_0;
+}
+
+xf86OutputPtr
+xf86OutputCreate (ScrnInfoPtr scrn,
+ const xf86OutputFuncsRec *funcs,
+ const char *name)
+{
+ xf86OutputPtr output, *outputs;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int len;
+ Bool primary;
+
+ if (name)
+ len = strlen (name) + 1;
+ else
+ len = 0;
+
+ output = calloc(sizeof (xf86OutputRec) + len, 1);
+ if (!output)
+ return NULL;
+ output->scrn = scrn;
+ output->funcs = funcs;
+ if (name)
+ {
+ output->name = (char *) (output + 1);
+ strcpy (output->name, name);
+ }
+ output->subpixel_order = SubPixelUnknown;
+ /*
+ * Use the old per-screen monitor section for the first output
+ */
+ output->use_screen_monitor = (xf86_config->num_output == 0);
+#ifdef RANDR_12_INTERFACE
+ output->randr_output = NULL;
+#endif
+ if (name)
+ {
+ xf86OutputSetMonitor (output);
+ if (xf86OutputIgnored (output))
+ {
+ free(output);
+ return FALSE;
+ }
+ }
+
+
+ if (xf86_config->output)
+ outputs = realloc(xf86_config->output,
+ (xf86_config->num_output + 1) * sizeof (xf86OutputPtr));
+ else
+ outputs = malloc((xf86_config->num_output + 1) * sizeof (xf86OutputPtr));
+ if (!outputs)
+ {
+ free(output);
+ return NULL;
+ }
+
+ xf86_config->output = outputs;
+
+ if (xf86GetOptValBool (output->options, OPTION_PRIMARY, &primary) && primary)
+ {
+ memmove(xf86_config->output + 1, xf86_config->output,
+ xf86_config->num_output * sizeof (xf86OutputPtr));
+ xf86_config->output[0] = output;
+ }
+ else
+ {
+ xf86_config->output[xf86_config->num_output] = output;
+ }
+
+ xf86_config->num_output++;
+
+ return output;
+}
+
+Bool
+xf86OutputRename (xf86OutputPtr output, const char *name)
+{
+ char *newname = strdup(name);
+
+ if (!newname)
+ return FALSE; /* so sorry... */
+
+ if (output->name && output->name != (char *) (output + 1))
+ free(output->name);
+ output->name = newname;
+ xf86OutputSetMonitor (output);
+ if (xf86OutputIgnored (output))
+ return FALSE;
+ return TRUE;
+}
+
+void
+xf86OutputUseScreenMonitor (xf86OutputPtr output, Bool use_screen_monitor)
+{
+ if (use_screen_monitor != output->use_screen_monitor)
+ {
+ output->use_screen_monitor = use_screen_monitor;
+ xf86OutputSetMonitor (output);
+ }
+}
+
+void
+xf86OutputDestroy (xf86OutputPtr output)
+{
+ ScrnInfoPtr scrn = output->scrn;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int o;
+
+ (*output->funcs->destroy) (output);
+ while (output->probed_modes)
+ xf86DeleteMode (&output->probed_modes, output->probed_modes);
+ for (o = 0; o < xf86_config->num_output; o++)
+ if (xf86_config->output[o] == output)
+ {
+ memmove (&xf86_config->output[o],
+ &xf86_config->output[o+1],
+ ((xf86_config->num_output - (o + 1)) * sizeof(void*)));
+ xf86_config->num_output--;
+ break;
+ }
+ if (output->name && output->name != (char *) (output + 1))
+ free(output->name);
+ free(output);
+}
+
+/*
+ * Called during CreateScreenResources to hook up RandR
+ */
+static Bool
+xf86CrtcCreateScreenResources (ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+
+ screen->CreateScreenResources = config->CreateScreenResources;
+
+ if (!(*screen->CreateScreenResources)(screen))
+ return FALSE;
+
+ if (!xf86RandR12CreateScreenResources (screen))
+ return FALSE;
+
+ return TRUE;
+}
+
+/*
+ * Clean up config on server reset
+ */
+static Bool
+xf86CrtcCloseScreen (int index, ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int o, c;
+
+ screen->CloseScreen = config->CloseScreen;
+
+ xf86RotateCloseScreen (screen);
+
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+
+ output->randr_output = NULL;
+ }
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = config->crtc[c];
+
+ crtc->randr_crtc = NULL;
+ }
+ xf86RandR12CloseScreen (screen);
+
+ return screen->CloseScreen (index, screen);
+}
+
+/*
+ * Called at ScreenInit time to set up
+ */
+#ifdef RANDR_13_INTERFACE
+int
+#else
+Bool
+#endif
+xf86CrtcScreenInit (ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c;
+
+ /* Rotation */
+ xf86DrvMsg(scrn->scrnIndex, X_INFO, "RandR 1.2 enabled, ignore the following RandR disabled message.\n");
+ xf86DisableRandR(); /* Disable old RandR extension support */
+ xf86RandR12Init (screen);
+
+ /* support all rotations if every crtc has the shadow alloc funcs */
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = config->crtc[c];
+ if (!crtc->funcs->shadow_allocate || !crtc->funcs->shadow_create)
+ break;
+ }
+ if (c == config->num_crtc)
+ {
+ xf86RandR12SetRotations (screen, RR_Rotate_0 | RR_Rotate_90 |
+ RR_Rotate_180 | RR_Rotate_270 |
+ RR_Reflect_X | RR_Reflect_Y);
+ xf86RandR12SetTransformSupport (screen, TRUE);
+ }
+ else
+ {
+ xf86RandR12SetRotations (screen, RR_Rotate_0);
+ xf86RandR12SetTransformSupport (screen, FALSE);
+ }
+
+ /* Wrap CreateScreenResources so we can initialize the RandR code */
+ config->CreateScreenResources = screen->CreateScreenResources;
+ screen->CreateScreenResources = xf86CrtcCreateScreenResources;
+
+ config->CloseScreen = screen->CloseScreen;
+ screen->CloseScreen = xf86CrtcCloseScreen;
+
+#ifdef XFreeXDGA
+ _xf86_di_dga_init_internal(screen);
+#endif
+#ifdef RANDR_13_INTERFACE
+ return RANDR_INTERFACE_VERSION;
+#else
+ return TRUE;
+#endif
+}
+
+static DisplayModePtr
+xf86DefaultMode (xf86OutputPtr output, int width, int height)
+{
+ DisplayModePtr target_mode = NULL;
+ DisplayModePtr mode;
+ int target_diff = 0;
+ int target_preferred = 0;
+ int mm_height;
+
+ mm_height = output->mm_height;
+ if (!mm_height)
+ mm_height = (768 * 25.4) / DEFAULT_DPI;
+ /*
+ * Pick a mode closest to DEFAULT_DPI
+ */
+ for (mode = output->probed_modes; mode; mode = mode->next)
+ {
+ int dpi;
+ int preferred = (((mode->type & M_T_PREFERRED) != 0) +
+ ((mode->type & M_T_USERPREF) != 0));
+ int diff;
+
+ if (xf86ModeWidth (mode, output->initial_rotation) > width ||
+ xf86ModeHeight (mode, output->initial_rotation) > height)
+ continue;
+
+ /* yes, use VDisplay here, not xf86ModeHeight */
+ dpi = (mode->VDisplay * 254) / (mm_height * 10);
+ diff = dpi - DEFAULT_DPI;
+ diff = diff < 0 ? -diff : diff;
+ if (target_mode == NULL || (preferred > target_preferred) ||
+ (preferred == target_preferred && diff < target_diff))
+ {
+ target_mode = mode;
+ target_diff = diff;
+ target_preferred = preferred;
+ }
+ }
+ return target_mode;
+}
+
+static DisplayModePtr
+xf86ClosestMode (xf86OutputPtr output,
+ DisplayModePtr match, Rotation match_rotation,
+ int width, int height)
+{
+ DisplayModePtr target_mode = NULL;
+ DisplayModePtr mode;
+ int target_diff = 0;
+
+ /*
+ * Pick a mode closest to the specified mode
+ */
+ for (mode = output->probed_modes; mode; mode = mode->next)
+ {
+ int dx, dy;
+ int diff;
+
+ if (xf86ModeWidth (mode, output->initial_rotation) > width ||
+ xf86ModeHeight (mode, output->initial_rotation) > height)
+ continue;
+
+ /* exact matches are preferred */
+ if (output->initial_rotation == match_rotation &&
+ xf86ModesEqual (mode, match))
+ return mode;
+
+ dx = xf86ModeWidth (match, match_rotation) - xf86ModeWidth (mode, output->initial_rotation);
+ dy = xf86ModeHeight (match, match_rotation) - xf86ModeHeight (mode, output->initial_rotation);
+ diff = dx * dx + dy * dy;
+ if (target_mode == NULL || diff < target_diff)
+ {
+ target_mode = mode;
+ target_diff = diff;
+ }
+ }
+ return target_mode;
+}
+
+static DisplayModePtr
+xf86OutputHasPreferredMode (xf86OutputPtr output, int width, int height)
+{
+ DisplayModePtr mode;
+
+ for (mode = output->probed_modes; mode; mode = mode->next)
+ {
+ if (xf86ModeWidth (mode, output->initial_rotation) > width ||
+ xf86ModeHeight (mode, output->initial_rotation) > height)
+ continue;
+
+ if (mode->type & M_T_PREFERRED)
+ return mode;
+ }
+ return NULL;
+}
+
+static DisplayModePtr
+xf86OutputHasUserPreferredMode (xf86OutputPtr output)
+{
+ DisplayModePtr mode, first = output->probed_modes;
+
+ for (mode = first; mode && mode->next != first; mode = mode->next)
+ if (mode->type & M_T_USERPREF)
+ return mode;
+
+ return NULL;
+}
+
+static int
+xf86PickCrtcs (ScrnInfoPtr scrn,
+ xf86CrtcPtr *best_crtcs,
+ DisplayModePtr *modes,
+ int n,
+ int width,
+ int height)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c, o;
+ xf86OutputPtr output;
+ xf86CrtcPtr crtc;
+ xf86CrtcPtr *crtcs;
+ xf86CrtcPtr best_crtc;
+ int best_score;
+ int score;
+ int my_score;
+
+ if (n == config->num_output)
+ return 0;
+ output = config->output[n];
+
+ /*
+ * Compute score with this output disabled
+ */
+ best_crtcs[n] = NULL;
+ best_crtc = NULL;
+ best_score = xf86PickCrtcs (scrn, best_crtcs, modes, n+1, width, height);
+ if (modes[n] == NULL)
+ return best_score;
+
+ crtcs = malloc(config->num_output * sizeof (xf86CrtcPtr));
+ if (!crtcs)
+ return best_score;
+
+ my_score = 1;
+ /* Score outputs that are known to be connected higher */
+ if (output->status == XF86OutputStatusConnected)
+ my_score++;
+ /* Score outputs with preferred modes higher */
+ if (xf86OutputHasPreferredMode (output, width, height))
+ my_score++;
+ /*
+ * Select a crtc for this output and
+ * then attempt to configure the remaining
+ * outputs
+ */
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ if ((output->possible_crtcs & (1 << c)) == 0)
+ continue;
+
+ crtc = config->crtc[c];
+ /*
+ * Check to see if some other output is
+ * using this crtc
+ */
+ for (o = 0; o < n; o++)
+ if (best_crtcs[o] == crtc)
+ break;
+ if (o < n)
+ {
+ /*
+ * If the two outputs desire the same mode,
+ * see if they can be cloned
+ */
+ if (xf86ModesEqual (modes[o], modes[n]) &&
+ config->output[o]->initial_rotation == config->output[n]->initial_rotation &&
+ config->output[o]->initial_x == config->output[n]->initial_x &&
+ config->output[o]->initial_y == config->output[n]->initial_y)
+ {
+ if ((output->possible_clones & (1 << o)) == 0)
+ continue; /* nope, try next CRTC */
+ }
+ else
+ continue; /* different modes, can't clone */
+ }
+ crtcs[n] = crtc;
+ memcpy (crtcs, best_crtcs, n * sizeof (xf86CrtcPtr));
+ score = my_score + xf86PickCrtcs (scrn, crtcs, modes, n+1, width, height);
+ if (score > best_score)
+ {
+ best_crtc = crtc;
+ best_score = score;
+ memcpy (best_crtcs, crtcs, config->num_output * sizeof (xf86CrtcPtr));
+ }
+ }
+ free(crtcs);
+ return best_score;
+}
+
+
+/*
+ * Compute the virtual size necessary to place all of the available
+ * crtcs in the specified configuration.
+ *
+ * canGrow indicates that the driver can make the screen larger than its initial
+ * configuration. If FALSE, this function will enlarge the screen to include
+ * the largest available mode.
+ */
+
+static void
+xf86DefaultScreenLimits (ScrnInfoPtr scrn, int *widthp, int *heightp,
+ Bool canGrow)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int width = 0, height = 0;
+ int o;
+ int c;
+ int s;
+
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ int crtc_width = 0, crtc_height = 0;
+ xf86CrtcPtr crtc = config->crtc[c];
+
+ if (crtc->enabled)
+ {
+ crtc_width = crtc->desiredX + xf86ModeWidth (&crtc->desiredMode, crtc->desiredRotation);
+ crtc_height = crtc->desiredY + xf86ModeHeight (&crtc->desiredMode, crtc->desiredRotation);
+ }
+ if (!canGrow) {
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+
+ for (s = 0; s < config->num_crtc; s++)
+ if (output->possible_crtcs & (1 << s))
+ {
+ DisplayModePtr mode;
+ for (mode = output->probed_modes; mode; mode = mode->next)
+ {
+ if (mode->HDisplay > crtc_width)
+ crtc_width = mode->HDisplay;
+ if (mode->VDisplay > crtc_width)
+ crtc_width = mode->VDisplay;
+ if (mode->VDisplay > crtc_height)
+ crtc_height = mode->VDisplay;
+ if (mode->HDisplay > crtc_height)
+ crtc_height = mode->HDisplay;
+ }
+ }
+ }
+ }
+ if (crtc_width > width)
+ width = crtc_width;
+ if (crtc_height > height)
+ height = crtc_height;
+ }
+ if (config->maxWidth && width > config->maxWidth) width = config->maxWidth;
+ if (config->maxHeight && height > config->maxHeight) height = config->maxHeight;
+ if (config->minWidth && width < config->minWidth) width = config->minWidth;
+ if (config->minHeight && height < config->minHeight) height = config->minHeight;
+ *widthp = width;
+ *heightp = height;
+}
+
+#define POSITION_UNSET -100000
+
+/*
+ * check if the user configured any outputs at all
+ * with either a position or a relative setting or a mode.
+ */
+static Bool
+xf86UserConfiguredOutputs(ScrnInfoPtr scrn, DisplayModePtr *modes)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int o;
+ Bool user_conf = FALSE;
+
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+ char *position;
+ char *relative_name;
+ OutputOpts relation;
+ int r;
+ static const OutputOpts relations[] = {
+ OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF
+ };
+
+ position = xf86GetOptValString (output->options,
+ OPTION_POSITION);
+ if (position)
+ user_conf = TRUE;
+
+ relation = 0;
+ relative_name = NULL;
+ for (r = 0; r < 4; r++)
+ {
+ relation = relations[r];
+ relative_name = xf86GetOptValString (output->options,
+ relation);
+ if (relative_name)
+ break;
+ }
+ if (relative_name)
+ user_conf = TRUE;
+
+ modes[o] = xf86OutputHasUserPreferredMode(output);
+ if (modes[o])
+ user_conf = TRUE;
+ }
+
+ return user_conf;
+}
+
+static Bool
+xf86InitialOutputPositions (ScrnInfoPtr scrn, DisplayModePtr *modes)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int o;
+ int min_x, min_y;
+
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+
+ output->initial_x = output->initial_y = POSITION_UNSET;
+ }
+
+ /*
+ * Loop until all outputs are set
+ */
+ for (;;)
+ {
+ Bool any_set = FALSE;
+ Bool keep_going = FALSE;
+
+ for (o = 0; o < config->num_output; o++)
+ {
+ static const OutputOpts relations[] = {
+ OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF
+ };
+ xf86OutputPtr output = config->output[o];
+ xf86OutputPtr relative;
+ char *relative_name;
+ char *position;
+ OutputOpts relation;
+ int r;
+
+ if (output->initial_x != POSITION_UNSET)
+ continue;
+ position = xf86GetOptValString (output->options,
+ OPTION_POSITION);
+ /*
+ * Absolute position wins
+ */
+ if (position)
+ {
+ int x, y;
+ if (sscanf (position, "%d %d", &x, &y) == 2)
+ {
+ output->initial_x = x;
+ output->initial_y = y;
+ }
+ else
+ {
+ xf86DrvMsg (scrn->scrnIndex, X_ERROR,
+ "Output %s position not of form \"x y\"\n",
+ output->name);
+ output->initial_x = output->initial_y = 0;
+ }
+ any_set = TRUE;
+ continue;
+ }
+ /*
+ * Next comes relative positions
+ */
+ relation = 0;
+ relative_name = NULL;
+ for (r = 0; r < 4; r++)
+ {
+ relation = relations[r];
+ relative_name = xf86GetOptValString (output->options,
+ relation);
+ if (relative_name)
+ break;
+ }
+ if (relative_name)
+ {
+ int or;
+ relative = NULL;
+ for (or = 0; or < config->num_output; or++)
+ {
+ xf86OutputPtr out_rel = config->output[or];
+ XF86ConfMonitorPtr rel_mon = out_rel->conf_monitor;
+
+ if (rel_mon)
+ {
+ if (xf86nameCompare (rel_mon->mon_identifier,
+ relative_name) == 0)
+ {
+ relative = config->output[or];
+ break;
+ }
+ }
+ if (strcmp (out_rel->name, relative_name) == 0)
+ {
+ relative = config->output[or];
+ break;
+ }
+ }
+ if (!relative)
+ {
+ xf86DrvMsg (scrn->scrnIndex, X_ERROR,
+ "Cannot position output %s relative to unknown output %s\n",
+ output->name, relative_name);
+ output->initial_x = 0;
+ output->initial_y = 0;
+ any_set = TRUE;
+ continue;
+ }
+ if (!modes[or])
+ {
+ xf86DrvMsg (scrn->scrnIndex, X_ERROR,
+ "Cannot position output %s relative to output %s without modes\n",
+ output->name, relative_name);
+ output->initial_x = 0;
+ output->initial_y = 0;
+ any_set = TRUE;
+ continue;
+ }
+ if (relative->initial_x == POSITION_UNSET)
+ {
+ keep_going = TRUE;
+ continue;
+ }
+ output->initial_x = relative->initial_x;
+ output->initial_y = relative->initial_y;
+ switch (relation) {
+ case OPTION_BELOW:
+ output->initial_y += xf86ModeHeight (modes[or], relative->initial_rotation);
+ break;
+ case OPTION_RIGHT_OF:
+ output->initial_x += xf86ModeWidth (modes[or], relative->initial_rotation);
+ break;
+ case OPTION_ABOVE:
+ if (modes[o])
+ output->initial_y -= xf86ModeHeight (modes[o], output->initial_rotation);
+ break;
+ case OPTION_LEFT_OF:
+ if (modes[o])
+ output->initial_x -= xf86ModeWidth (modes[o], output->initial_rotation);
+ break;
+ default:
+ break;
+ }
+ any_set = TRUE;
+ continue;
+ }
+
+ /* Nothing set, just stick them at 0,0 */
+ output->initial_x = 0;
+ output->initial_y = 0;
+ any_set = TRUE;
+ }
+ if (!keep_going)
+ break;
+ if (!any_set)
+ {
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+ if (output->initial_x == POSITION_UNSET)
+ {
+ xf86DrvMsg (scrn->scrnIndex, X_ERROR,
+ "Output position loop. Moving %s to 0,0\n",
+ output->name);
+ output->initial_x = output->initial_y = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ * normalize positions
+ */
+ min_x = 1000000;
+ min_y = 1000000;
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+
+ if (output->initial_x < min_x)
+ min_x = output->initial_x;
+ if (output->initial_y < min_y)
+ min_y = output->initial_y;
+ }
+
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+
+ output->initial_x -= min_x;
+ output->initial_y -= min_y;
+ }
+ return TRUE;
+}
+
+static void
+xf86InitialPanning (ScrnInfoPtr scrn)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int o;
+
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+ char *panning = xf86GetOptValString (output->options, OPTION_PANNING);
+ int width, height, left, top;
+ int track_width, track_height, track_left, track_top;
+ int brdr[4];
+
+ memset (&output->initialTotalArea, 0, sizeof(BoxRec));
+ memset (&output->initialTrackingArea, 0, sizeof(BoxRec));
+ memset (output->initialBorder, 0, 4*sizeof(INT16));
+
+ if (! panning)
+ continue;
+
+ switch (sscanf (panning, "%dx%d+%d+%d/%dx%d+%d+%d/%d/%d/%d/%d",
+ &width, &height, &left, &top,
+ &track_width, &track_height, &track_left, &track_top,
+ &brdr[0], &brdr[1], &brdr[2], &brdr[3])) {
+ case 12:
+ output->initialBorder[0] = brdr[0];
+ output->initialBorder[1] = brdr[1];
+ output->initialBorder[2] = brdr[2];
+ output->initialBorder[3] = brdr[3];
+ /* fall through */
+ case 8:
+ output->initialTrackingArea.x1 = track_left;
+ output->initialTrackingArea.y1 = track_top;
+ output->initialTrackingArea.x2 = track_left + track_width;
+ output->initialTrackingArea.y2 = track_top + track_height;
+ /* fall through */
+ case 4:
+ output->initialTotalArea.x1 = left;
+ output->initialTotalArea.y1 = top;
+ /* fall through */
+ case 2:
+ output->initialTotalArea.x2 = output->initialTotalArea.x1 + width;
+ output->initialTotalArea.y2 = output->initialTotalArea.y1 + height;
+ break;
+ default:
+ xf86DrvMsg (scrn->scrnIndex, X_ERROR,
+ "Broken panning specification '%s' for output %s in config file\n",
+ panning, output->name);
+ }
+ }
+}
+
+/** Return - 0 + if a should be earlier, same or later than b in list
+ */
+static int
+xf86ModeCompare (DisplayModePtr a, DisplayModePtr b)
+{
+ int diff;
+
+ diff = ((b->type & M_T_PREFERRED) != 0) - ((a->type & M_T_PREFERRED) != 0);
+ if (diff)
+ return diff;
+ diff = b->HDisplay * b->VDisplay - a->HDisplay * a->VDisplay;
+ if (diff)
+ return diff;
+ diff = b->Clock - a->Clock;
+ return diff;
+}
+
+/**
+ * Insertion sort input in-place and return the resulting head
+ */
+static DisplayModePtr
+xf86SortModes (DisplayModePtr input)
+{
+ DisplayModePtr output = NULL, i, o, n, *op, prev;
+
+ /* sort by preferred status and pixel area */
+ while (input)
+ {
+ i = input;
+ input = input->next;
+ for (op = &output; (o = *op); op = &o->next)
+ if (xf86ModeCompare (o, i) > 0)
+ break;
+ i->next = *op;
+ *op = i;
+ }
+ /* prune identical modes */
+ for (o = output; o && (n = o->next); o = n)
+ {
+ if (!strcmp (o->name, n->name) && xf86ModesEqual (o, n))
+ {
+ o->next = n->next;
+ free(n->name);
+ free(n);
+ n = o;
+ }
+ }
+ /* hook up backward links */
+ prev = NULL;
+ for (o = output; o; o = o->next)
+ {
+ o->prev = prev;
+ prev = o;
+ }
+ return output;
+}
+
+static char *
+preferredMode(ScrnInfoPtr pScrn, xf86OutputPtr output)
+{
+ char *preferred_mode = NULL;
+
+ /* Check for a configured preference for a particular mode */
+ preferred_mode = xf86GetOptValString (output->options,
+ OPTION_PREFERRED_MODE);
+ if (preferred_mode)
+ return preferred_mode;
+
+ if (pScrn->display->modes && *pScrn->display->modes)
+ preferred_mode = *pScrn->display->modes;
+
+ return preferred_mode;
+}
+
+static void
+GuessRangeFromModes(MonPtr mon, DisplayModePtr mode)
+{
+ if (!mon || !mode)
+ return;
+
+ mon->nHsync = 1;
+ mon->hsync[0].lo = 1024.0;
+ mon->hsync[0].hi = 0.0;
+
+ mon->nVrefresh = 1;
+ mon->vrefresh[0].lo = 1024.0;
+ mon->vrefresh[0].hi = 0.0;
+
+ while (mode) {
+ if (!mode->HSync)
+ mode->HSync = ((float) mode->Clock ) / ((float) mode->HTotal);
+
+ if (!mode->VRefresh)
+ mode->VRefresh = (1000.0 * ((float) mode->Clock)) /
+ ((float) (mode->HTotal * mode->VTotal));
+
+ if (mode->HSync < mon->hsync[0].lo)
+ mon->hsync[0].lo = mode->HSync;
+
+ if (mode->HSync > mon->hsync[0].hi)
+ mon->hsync[0].hi = mode->HSync;
+
+ if (mode->VRefresh < mon->vrefresh[0].lo)
+ mon->vrefresh[0].lo = mode->VRefresh;
+
+ if (mode->VRefresh > mon->vrefresh[0].hi)
+ mon->vrefresh[0].hi = mode->VRefresh;
+
+ mode = mode->next;
+ }
+
+ /* stretch out the bottom to fit 640x480@60 */
+ if (mon->hsync[0].lo > 31.0)
+ mon->hsync[0].lo = 31.0;
+ if (mon->vrefresh[0].lo > 58.0)
+ mon->vrefresh[0].lo = 58.0;
+}
+
+enum det_monrec_source {
+ sync_config, sync_edid, sync_default
+};
+
+struct det_monrec_parameter {
+ MonRec *mon_rec;
+ int *max_clock;
+ Bool set_hsync;
+ Bool set_vrefresh;
+ enum det_monrec_source *sync_source;
+};
+
+static void handle_detailed_monrec(struct detailed_monitor_section *det_mon,
+ void *data)
+{
+ struct det_monrec_parameter *p;
+ p = (struct det_monrec_parameter *)data;
+
+ if (det_mon->type == DS_RANGES) {
+ struct monitor_ranges *ranges = &det_mon->section.ranges;
+ if (p->set_hsync && ranges->max_h) {
+ p->mon_rec->hsync[p->mon_rec->nHsync].lo = ranges->min_h;
+ p->mon_rec->hsync[p->mon_rec->nHsync].hi = ranges->max_h;
+ p->mon_rec->nHsync++;
+ if (*p->sync_source == sync_default)
+ *p->sync_source = sync_edid;
+ }
+ if (p->set_vrefresh && ranges->max_v) {
+ p->mon_rec->vrefresh[p->mon_rec->nVrefresh].lo = ranges->min_v;
+ p->mon_rec->vrefresh[p->mon_rec->nVrefresh].hi = ranges->max_v;
+ p->mon_rec->nVrefresh++;
+ if (*p->sync_source == sync_default)
+ *p->sync_source = sync_edid;
+ }
+ if (ranges->max_clock * 1000 > *p->max_clock)
+ *p->max_clock = ranges->max_clock * 1000;
+ }
+}
+
+void
+xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int o;
+
+ /* When canGrow was TRUE in the initial configuration we have to
+ * compare against the maximum values so that we don't drop modes.
+ * When canGrow was FALSE, the maximum values would have been clamped
+ * anyway.
+ */
+ if (maxX == 0 || maxY == 0) {
+ maxX = config->maxWidth;
+ maxY = config->maxHeight;
+ }
+
+ /* Probe the list of modes for each output. */
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+ DisplayModePtr mode;
+ DisplayModePtr config_modes = NULL, output_modes, default_modes = NULL;
+ char *preferred_mode;
+ xf86MonPtr edid_monitor;
+ XF86ConfMonitorPtr conf_monitor;
+ MonRec mon_rec;
+ int min_clock = 0;
+ int max_clock = 0;
+ double clock;
+ Bool add_default_modes = xf86ReturnOptValBool(output->options, OPTION_DEFAULT_MODES, TRUE);
+ Bool debug_modes = config->debug_modes ||
+ xf86Initialising;
+ enum det_monrec_source sync_source = sync_default;
+
+ while (output->probed_modes != NULL)
+ xf86DeleteMode(&output->probed_modes, output->probed_modes);
+
+ /*
+ * Check connection status
+ */
+ output->status = (*output->funcs->detect)(output);
+
+ if (output->status == XF86OutputStatusDisconnected &&
+ !xf86ReturnOptValBool(output->options, OPTION_ENABLE, FALSE))
+ {
+ xf86OutputSetEDID (output, NULL);
+ continue;
+ }
+
+ memset (&mon_rec, '\0', sizeof (mon_rec));
+
+ conf_monitor = output->conf_monitor;
+
+ if (conf_monitor)
+ {
+ int i;
+
+ for (i = 0; i < conf_monitor->mon_n_hsync; i++)
+ {
+ mon_rec.hsync[mon_rec.nHsync].lo = conf_monitor->mon_hsync[i].lo;
+ mon_rec.hsync[mon_rec.nHsync].hi = conf_monitor->mon_hsync[i].hi;
+ mon_rec.nHsync++;
+ sync_source = sync_config;
+ }
+ for (i = 0; i < conf_monitor->mon_n_vrefresh; i++)
+ {
+ mon_rec.vrefresh[mon_rec.nVrefresh].lo = conf_monitor->mon_vrefresh[i].lo;
+ mon_rec.vrefresh[mon_rec.nVrefresh].hi = conf_monitor->mon_vrefresh[i].hi;
+ mon_rec.nVrefresh++;
+ sync_source = sync_config;
+ }
+ config_modes = xf86GetMonitorModes (scrn, conf_monitor);
+ }
+
+ output_modes = (*output->funcs->get_modes) (output);
+
+ edid_monitor = output->MonInfo;
+
+ if (edid_monitor)
+ {
+ struct det_monrec_parameter p;
+ struct disp_features *features = &edid_monitor->features;
+
+ /* if display is not continuous-frequency, don't add default modes */
+ if (!GTF_SUPPORTED(features->msc))
+ add_default_modes = FALSE;
+
+ p.mon_rec = &mon_rec;
+ p.max_clock = &max_clock;
+ p.set_hsync = mon_rec.nHsync == 0;
+ p.set_vrefresh = mon_rec.nVrefresh == 0;
+ p.sync_source = &sync_source;
+
+ xf86ForEachDetailedBlock(edid_monitor,
+ handle_detailed_monrec,
+ &p);
+ }
+
+ if (xf86GetOptValFreq (output->options, OPTION_MIN_CLOCK,
+ OPTUNITS_KHZ, &clock))
+ min_clock = (int) clock;
+ if (xf86GetOptValFreq (output->options, OPTION_MAX_CLOCK,
+ OPTUNITS_KHZ, &clock))
+ max_clock = (int) clock;
+
+ /* If we still don't have a sync range, guess wildly */
+ if (!mon_rec.nHsync || !mon_rec.nVrefresh)
+ GuessRangeFromModes(&mon_rec, output_modes);
+
+ /*
+ * These limits will end up setting a 1024x768@60Hz mode by default,
+ * which seems like a fairly good mode to use when nothing else is
+ * specified
+ */
+ if (mon_rec.nHsync == 0)
+ {
+ mon_rec.hsync[0].lo = 31.0;
+ mon_rec.hsync[0].hi = 55.0;
+ mon_rec.nHsync = 1;
+ }
+ if (mon_rec.nVrefresh == 0)
+ {
+ mon_rec.vrefresh[0].lo = 58.0;
+ mon_rec.vrefresh[0].hi = 62.0;
+ mon_rec.nVrefresh = 1;
+ }
+
+ if (add_default_modes)
+ default_modes = xf86GetDefaultModes ();
+
+ /*
+ * If this is not an RB monitor, remove RB modes from the default
+ * pool. RB modes from the config or the monitor itself are fine.
+ */
+ if (!mon_rec.reducedblanking)
+ xf86ValidateModesReducedBlanking (scrn, default_modes);
+
+ if (sync_source == sync_config)
+ {
+ /*
+ * Check output and config modes against sync range from config file
+ */
+ xf86ValidateModesSync (scrn, output_modes, &mon_rec);
+ xf86ValidateModesSync (scrn, config_modes, &mon_rec);
+ }
+ /*
+ * Check default modes against sync range
+ */
+ xf86ValidateModesSync (scrn, default_modes, &mon_rec);
+ /*
+ * Check default modes against monitor max clock
+ */
+ if (max_clock) {
+ xf86ValidateModesClocks(scrn, default_modes,
+ &min_clock, &max_clock, 1);
+ xf86ValidateModesClocks(scrn, output_modes,
+ &min_clock, &max_clock, 1);
+ }
+
+ output->probed_modes = NULL;
+ output->probed_modes = xf86ModesAdd (output->probed_modes, config_modes);
+ output->probed_modes = xf86ModesAdd (output->probed_modes, output_modes);
+ output->probed_modes = xf86ModesAdd (output->probed_modes, default_modes);
+
+ /*
+ * Check all modes against max size, interlace, and doublescan
+ */
+ if (maxX && maxY)
+ xf86ValidateModesSize (scrn, output->probed_modes,
+ maxX, maxY, 0);
+
+ {
+ int flags = (output->interlaceAllowed ? V_INTERLACE : 0) |
+ (output->doubleScanAllowed ? V_DBLSCAN : 0);
+ xf86ValidateModesFlags (scrn, output->probed_modes, flags);
+ }
+
+ /*
+ * Check all modes against output
+ */
+ for (mode = output->probed_modes; mode != NULL; mode = mode->next)
+ if (mode->status == MODE_OK)
+ mode->status = (*output->funcs->mode_valid)(output, mode);
+
+ xf86PruneInvalidModes(scrn, &output->probed_modes, debug_modes);
+
+ output->probed_modes = xf86SortModes (output->probed_modes);
+
+ /* Check for a configured preference for a particular mode */
+ preferred_mode = preferredMode(scrn, output);
+
+ if (preferred_mode)
+ {
+ for (mode = output->probed_modes; mode; mode = mode->next)
+ {
+ if (!strcmp (preferred_mode, mode->name))
+ {
+ if (mode != output->probed_modes)
+ {
+ if (mode->prev)
+ mode->prev->next = mode->next;
+ if (mode->next)
+ mode->next->prev = mode->prev;
+ mode->next = output->probed_modes;
+ output->probed_modes->prev = mode;
+ mode->prev = NULL;
+ output->probed_modes = mode;
+ }
+ mode->type |= (M_T_PREFERRED|M_T_USERPREF);
+ break;
+ }
+ }
+ }
+
+ output->initial_rotation = xf86OutputInitialRotation (output);
+
+ if (debug_modes) {
+ if (output->probed_modes != NULL) {
+ xf86DrvMsg(scrn->scrnIndex, X_INFO,
+ "Printing probed modes for output %s\n",
+ output->name);
+ } else {
+ xf86DrvMsg(scrn->scrnIndex, X_INFO,
+ "No remaining probed modes for output %s\n",
+ output->name);
+ }
+ }
+ for (mode = output->probed_modes; mode != NULL; mode = mode->next)
+ {
+ /* The code to choose the best mode per pipe later on will require
+ * VRefresh to be set.
+ */
+ mode->VRefresh = xf86ModeVRefresh(mode);
+ xf86SetModeCrtc(mode, INTERLACE_HALVE_V);
+
+ if (debug_modes)
+ xf86PrintModeline(scrn->scrnIndex, mode);
+ }
+ }
+}
+
+
+/**
+ * Copy one of the output mode lists to the ScrnInfo record
+ */
+
+/* XXX where does this function belong? Here? */
+void
+xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr scrn, int *x, int *y);
+
+static DisplayModePtr
+biggestMode(DisplayModePtr a, DisplayModePtr b)
+{
+ int A, B;
+
+ if (!a)
+ return b;
+ if (!b)
+ return a;
+
+ A = a->HDisplay * a->VDisplay;
+ B = b->HDisplay * b->VDisplay;
+
+ if (A > B)
+ return a;
+
+ return b;
+}
+
+static xf86OutputPtr
+SetCompatOutput(xf86CrtcConfigPtr config)
+{
+ xf86OutputPtr output = NULL, test = NULL;
+ DisplayModePtr maxmode = NULL, testmode, mode;
+ int o, compat = -1, count, mincount = 0;
+
+ /* Look for one that's definitely connected */
+ for (o = 0; o < config->num_output; o++)
+ {
+ test = config->output[o];
+ if (!test->crtc)
+ continue;
+ if (test->status != XF86OutputStatusConnected)
+ continue;
+ if (!test->probed_modes)
+ continue;
+
+ testmode = mode = test->probed_modes;
+ for (count = 0; mode; mode = mode->next, count++)
+ testmode = biggestMode(testmode, mode);
+
+ if (!output) {
+ output = test;
+ compat = o;
+ maxmode = testmode;
+ mincount = count;
+ } else if (maxmode == biggestMode(maxmode, testmode)) {
+ output = test;
+ compat = o;
+ maxmode = testmode;
+ mincount = count;
+ } else if ((maxmode->HDisplay == testmode->HDisplay) &&
+ (maxmode->VDisplay == testmode->VDisplay) &&
+ count <= mincount) {
+ output = test;
+ compat = o;
+ maxmode = testmode;
+ mincount = count;
+ }
+ }
+
+ /* If we didn't find one, take anything we can get */
+ if (!output)
+ {
+ for (o = 0; o < config->num_output; o++)
+ {
+ test = config->output[o];
+ if (!test->crtc)
+ continue;
+ if (!test->probed_modes)
+ continue;
+
+ if (!output) {
+ output = test;
+ compat = o;
+ } else if (test->probed_modes->HDisplay < output->probed_modes->HDisplay) {
+ output = test;
+ compat = o;
+ }
+ }
+ }
+
+ if (compat >= 0) {
+ config->compat_output = compat;
+ } else {
+ /* Don't change the compat output when no valid outputs found */
+ output = config->output[config->compat_output];
+ }
+
+ return output;
+}
+
+void
+xf86SetScrnInfoModes (ScrnInfoPtr scrn)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ xf86OutputPtr output;
+ xf86CrtcPtr crtc;
+ DisplayModePtr last, mode = NULL;
+
+ output = SetCompatOutput(config);
+
+ if (!output)
+ return; /* punt */
+
+ crtc = output->crtc;
+
+ /* Clear any existing modes from scrn->modes */
+ while (scrn->modes != NULL)
+ xf86DeleteMode(&scrn->modes, scrn->modes);
+
+ /* Set scrn->modes to the mode list for the 'compat' output */
+ scrn->modes = xf86DuplicateModes(scrn, output->probed_modes);
+
+ if (crtc) {
+ for (mode = scrn->modes; mode; mode = mode->next)
+ if (xf86ModesEqual (mode, &crtc->desiredMode))
+ break;
+ }
+
+ if (scrn->modes != NULL) {
+ /* For some reason, scrn->modes is circular, unlike the other mode
+ * lists. How great is that?
+ */
+ for (last = scrn->modes; last && last->next; last = last->next)
+ ;
+ last->next = scrn->modes;
+ scrn->modes->prev = last;
+ if (mode) {
+ while (scrn->modes != mode)
+ scrn->modes = scrn->modes->next;
+ }
+ }
+ scrn->currentMode = scrn->modes;
+#ifdef XFreeXDGA
+ if (scrn->pScreen)
+ _xf86_di_dga_reinit_internal(scrn->pScreen);
+#endif
+}
+
+static Bool
+xf86CollectEnabledOutputs(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
+ Bool *enabled)
+{
+ Bool any_enabled = FALSE;
+ int o;
+
+ for (o = 0; o < config->num_output; o++)
+ any_enabled |= enabled[o] = xf86OutputEnabled(config->output[o], TRUE);
+
+ if (!any_enabled) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "No outputs definitely connected, trying again...\n");
+
+ for (o = 0; o < config->num_output; o++)
+ any_enabled |= enabled[o] = xf86OutputEnabled(config->output[o], FALSE);
+ }
+
+ return any_enabled;
+}
+
+static Bool
+nextEnabledOutput(xf86CrtcConfigPtr config, Bool *enabled, int *index)
+{
+ int o = *index;
+
+ for (o++; o < config->num_output; o++) {
+ if (enabled[o]) {
+ *index = o;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static Bool
+aspectMatch(float a, float b)
+{
+ return fabs(1 - (a / b)) < 0.05;
+}
+
+static DisplayModePtr
+nextAspectMode(xf86OutputPtr o, DisplayModePtr last, float aspect)
+{
+ DisplayModePtr m = NULL;
+
+ if (!o)
+ return NULL;
+
+ if (!last)
+ m = o->probed_modes;
+ else
+ m = last->next;
+
+ for (; m; m = m->next)
+ if (aspectMatch(aspect, (float)m->HDisplay / (float)m->VDisplay))
+ return m;
+
+ return NULL;
+}
+
+static DisplayModePtr
+bestModeForAspect(xf86CrtcConfigPtr config, Bool *enabled, float aspect)
+{
+ int o = -1, p;
+ DisplayModePtr mode = NULL, test = NULL, match = NULL;
+
+ if (!nextEnabledOutput(config, enabled, &o))
+ return NULL;
+ while ((mode = nextAspectMode(config->output[o], mode, aspect))) {
+ test = mode;
+ for (p = o; nextEnabledOutput(config, enabled, &p); ) {
+ test = xf86OutputFindClosestMode(config->output[p], mode);
+ if (!test)
+ break;
+ if (test->HDisplay != mode->HDisplay ||
+ test->VDisplay != mode->VDisplay) {
+ test = NULL;
+ break;
+ }
+ }
+
+ /* if we didn't match it on all outputs, try the next one */
+ if (!test)
+ continue;
+
+ /* if it's bigger than the last one, save it */
+ if (!match || (test->HDisplay > match->HDisplay))
+ match = test;
+ }
+
+ /* return the biggest one found */
+ return match;
+}
+
+static Bool
+xf86TargetPreferred(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
+ DisplayModePtr *modes, Bool *enabled,
+ int width, int height)
+{
+ int o, p;
+ int max_pref_width = 0, max_pref_height = 0;
+ DisplayModePtr *preferred, *preferred_match;
+ Bool ret = FALSE;
+
+ preferred = xnfcalloc(config->num_output, sizeof(DisplayModePtr));
+ preferred_match = xnfcalloc(config->num_output, sizeof(DisplayModePtr));
+
+ /* Check if the preferred mode is available on all outputs */
+ for (p = -1; nextEnabledOutput(config, enabled, &p); ) {
+ Rotation r = config->output[p]->initial_rotation;
+ DisplayModePtr mode;
+ if ((preferred[p] = xf86OutputHasPreferredMode(config->output[p],
+ width, height))) {
+ int pref_width = xf86ModeWidth(preferred[p], r);
+ int pref_height = xf86ModeHeight(preferred[p], r);
+ Bool all_match = TRUE;
+
+ for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+ Bool match = FALSE;
+ xf86OutputPtr output = config->output[o];
+ if (o == p)
+ continue;
+
+ for (mode = output->probed_modes; mode; mode = mode->next) {
+ Rotation r = output->initial_rotation;
+ if (xf86ModeWidth(mode, r) == pref_width &&
+ xf86ModeHeight(mode, r) == pref_height) {
+ preferred[o] = mode;
+ match = TRUE;
+ }
+ }
+
+ all_match &= match;
+ }
+
+ if (all_match &&
+ (pref_width*pref_height > max_pref_width*max_pref_height)) {
+ for (o = -1; nextEnabledOutput(config, enabled, &o); )
+ preferred_match[o] = preferred[o];
+ max_pref_width = pref_width;
+ max_pref_height = pref_height;
+ ret = TRUE;
+ }
+ }
+ }
+
+ /*
+ * If there's no preferred mode, but only one monitor, pick the
+ * biggest mode for its aspect ratio, assuming one exists.
+ */
+ if (!ret) do {
+ int i = 0;
+ float aspect = 0.0;
+
+ /* count the number of enabled outputs */
+ for (i = 0, p = -1; nextEnabledOutput(config, enabled, &p); i++) ;
+
+ if (i != 1)
+ break;
+
+ p = -1;
+ nextEnabledOutput(config, enabled, &p);
+ if (config->output[p]->mm_height)
+ aspect = (float)config->output[p]->mm_width /
+ (float)config->output[p]->mm_height;
+
+ if (aspect)
+ preferred_match[p] = bestModeForAspect(config, enabled, aspect);
+
+ if (preferred_match[p])
+ ret = TRUE;
+
+ } while (0);
+
+ if (ret) {
+ /* oh good, there is a match. stash the selected modes and return. */
+ memcpy(modes, preferred_match,
+ config->num_output * sizeof(DisplayModePtr));
+ }
+
+ free(preferred);
+ free(preferred_match);
+ return ret;
+}
+
+static Bool
+xf86TargetAspect(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
+ DisplayModePtr *modes, Bool *enabled,
+ int width, int height)
+{
+ int o;
+ float aspect = 0.0, *aspects;
+ xf86OutputPtr output;
+ Bool ret = FALSE;
+ DisplayModePtr guess = NULL, aspect_guess = NULL, base_guess = NULL;
+
+ aspects = xnfcalloc(config->num_output, sizeof(float));
+
+ /* collect the aspect ratios */
+ for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+ output = config->output[o];
+ if (output->mm_height)
+ aspects[o] = (float)output->mm_width / (float)output->mm_height;
+ else
+ aspects[o] = 4.0 / 3.0;
+ }
+
+ /* check that they're all the same */
+ for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+ output = config->output[o];
+ if (!aspect) {
+ aspect = aspects[o];
+ } else if (!aspectMatch(aspect, aspects[o])) {
+ goto no_aspect_match;
+ }
+ }
+
+ /* if they're all 4:3, just skip ahead and save effort */
+ if (!aspectMatch(aspect, 4.0/3.0))
+ aspect_guess = bestModeForAspect(config, enabled, aspect);
+
+no_aspect_match:
+ base_guess = bestModeForAspect(config, enabled, 4.0/3.0);
+
+ guess = biggestMode(base_guess, aspect_guess);
+
+ if (!guess)
+ goto out;
+
+ /* found a mode that works everywhere, now apply it */
+ for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+ modes[o] = xf86OutputFindClosestMode(config->output[o], guess);
+ }
+ ret = TRUE;
+
+out:
+ free(aspects);
+ return ret;
+}
+
+static Bool
+xf86TargetFallback(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
+ DisplayModePtr *modes, Bool *enabled,
+ int width, int height)
+{
+ DisplayModePtr target_mode = NULL;
+ Rotation target_rotation = RR_Rotate_0;
+ DisplayModePtr default_mode;
+ int default_preferred, target_preferred = 0, o;
+
+ /* User preferred > preferred > other modes */
+ for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+ default_mode = xf86DefaultMode (config->output[o], width, height);
+ if (!default_mode)
+ continue;
+
+ default_preferred = (((default_mode->type & M_T_PREFERRED) != 0) +
+ ((default_mode->type & M_T_USERPREF) != 0));
+
+ if (default_preferred > target_preferred || !target_mode) {
+ target_mode = default_mode;
+ target_preferred = default_preferred;
+ target_rotation = config->output[o]->initial_rotation;
+ config->compat_output = o;
+ }
+ }
+
+ if (target_mode)
+ modes[config->compat_output] = target_mode;
+
+ /* Fill in other output modes */
+ for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+ if (!modes[o])
+ modes[o] = xf86ClosestMode(config->output[o], target_mode,
+ target_rotation, width, height);
+ }
+
+ return target_mode != NULL;
+}
+
+static Bool
+xf86TargetUserpref(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
+ DisplayModePtr *modes, Bool *enabled,
+ int width, int height)
+{
+ int o;
+
+ if (xf86UserConfiguredOutputs(scrn, modes))
+ return xf86TargetFallback(scrn, config, modes, enabled, width, height);
+
+ for (o = -1; nextEnabledOutput(config, enabled, &o); )
+ if (xf86OutputHasUserPreferredMode(config->output[o]))
+ return
+ xf86TargetFallback(scrn, config, modes, enabled, width, height);
+
+ return FALSE;
+}
+
+static Bool
+xf86CrtcSetInitialGamma(xf86CrtcPtr crtc, float gamma_red, float gamma_green,
+ float gamma_blue)
+{
+ int i, size = 256;
+ CARD16 *red, *green, *blue;
+
+ red = malloc(3 * size * sizeof(CARD16));
+ green = red + size;
+ blue = green + size;
+
+ /* Only cause warning if user wanted gamma to be set. */
+ if (!crtc->funcs->gamma_set && (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0)) {
+ free(red);
+ return FALSE;
+ } else if (!crtc->funcs->gamma_set) {
+ free(red);
+ return TRUE;
+ }
+
+ /* At this early stage none of the randr-interface stuff is up.
+ * So take the default gamma size for lack of something better.
+ */
+ for (i = 0; i < size; i++) {
+ if (gamma_red == 1.0)
+ red[i] = i << 8;
+ else
+ red[i] = (CARD16)(pow((double)i/(double)(size - 1),
+ 1. / (double)gamma_red) * (double)(size - 1) * 256);
+
+ if (gamma_green == 1.0)
+ green[i] = i << 8;
+ else
+ green[i] = (CARD16)(pow((double)i/(double)(size - 1),
+ 1. / (double)gamma_green) * (double)(size - 1) * 256);
+
+ if (gamma_blue == 1.0)
+ blue[i] = i << 8;
+ else
+ blue[i] = (CARD16)(pow((double)i/(double)(size - 1),
+ 1. / (double)gamma_blue) * (double)(size - 1) * 256);
+ }
+
+ /* Default size is 256, so anything else is failure. */
+ if (size != crtc->gamma_size) {
+ free(red);
+ return FALSE;
+ }
+
+ crtc->gamma_size = size;
+ memcpy (crtc->gamma_red, red, crtc->gamma_size * sizeof (CARD16));
+ memcpy (crtc->gamma_green, green, crtc->gamma_size * sizeof (CARD16));
+ memcpy (crtc->gamma_blue, blue, crtc->gamma_size * sizeof (CARD16));
+
+ /* Do not set gamma now, delay until the crtc is activated. */
+
+ free(red);
+
+ return TRUE;
+}
+
+static Bool
+xf86OutputSetInitialGamma(xf86OutputPtr output)
+{
+ XF86ConfMonitorPtr mon = output->conf_monitor;
+ float gamma_red = 1.0, gamma_green = 1.0, gamma_blue = 1.0;
+
+ if (!mon)
+ return TRUE;
+
+ if (!output->crtc)
+ return FALSE;
+
+ /* Get configured values, where they exist. */
+ if (mon->mon_gamma_red >= GAMMA_MIN &&
+ mon->mon_gamma_red <= GAMMA_MAX)
+ gamma_red = mon->mon_gamma_red;
+
+ if (mon->mon_gamma_green >= GAMMA_MIN &&
+ mon->mon_gamma_green <= GAMMA_MAX)
+ gamma_green = mon->mon_gamma_green;
+
+ if (mon->mon_gamma_blue >= GAMMA_MIN &&
+ mon->mon_gamma_blue <= GAMMA_MAX)
+ gamma_blue = mon->mon_gamma_blue;
+
+ /* This avoids setting gamma 1.0 in case another cloned output on this crtc has a specific gamma. */
+ if (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0) {
+ xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "Output %s wants gamma correction (%.1f, %.1f, %.1f)\n", output->name, gamma_red, gamma_green, gamma_blue);
+ return xf86CrtcSetInitialGamma(output->crtc, gamma_red, gamma_green, gamma_blue);
+ }else
+ return TRUE;
+}
+
+/**
+ * Construct default screen configuration
+ *
+ * Given auto-detected (and, eventually, configured) values,
+ * construct a usable configuration for the system
+ *
+ * canGrow indicates that the driver can resize the screen to larger than its
+ * initially configured size via the config->funcs->resize hook. If TRUE, this
+ * function will set virtualX and virtualY to match the initial configuration
+ * and leave config->max{Width,Height} alone. If FALSE, it will bloat
+ * virtual[XY] to include the largest modes and set config->max{Width,Height}
+ * accordingly.
+ */
+
+Bool
+xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int o, c;
+ xf86CrtcPtr *crtcs;
+ DisplayModePtr *modes;
+ Bool *enabled;
+ int width, height;
+ int i = scrn->scrnIndex;
+ Bool have_outputs = TRUE;
+ Bool ret;
+
+ /* Set up the device options */
+ config->options = xnfalloc (sizeof (xf86DeviceOptions));
+ memcpy (config->options, xf86DeviceOptions, sizeof (xf86DeviceOptions));
+ xf86ProcessOptions (scrn->scrnIndex,
+ scrn->options,
+ config->options);
+ config->debug_modes = xf86ReturnOptValBool (config->options,
+ OPTION_MODEDEBUG, FALSE);
+
+ if (scrn->display->virtualX)
+ width = scrn->display->virtualX;
+ else
+ width = config->maxWidth;
+ if (scrn->display->virtualY)
+ height = scrn->display->virtualY;
+ else
+ height = config->maxHeight;
+
+ xf86ProbeOutputModes (scrn, width, height);
+
+ crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr));
+ modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr));
+ enabled = xnfcalloc (config->num_output, sizeof (Bool));
+
+ ret = xf86CollectEnabledOutputs(scrn, config, enabled);
+ if (ret == FALSE && canGrow) {
+ xf86DrvMsg(i, X_WARNING, "Unable to find connected outputs - setting %dx%d initial framebuffer\n",
+ NO_OUTPUT_DEFAULT_WIDTH, NO_OUTPUT_DEFAULT_HEIGHT);
+ have_outputs = FALSE;
+ } else {
+ if (xf86TargetUserpref(scrn, config, modes, enabled, width, height))
+ xf86DrvMsg(i, X_INFO, "Using user preference for initial modes\n");
+ else if (xf86TargetPreferred(scrn, config, modes, enabled, width, height))
+ xf86DrvMsg(i, X_INFO, "Using exact sizes for initial modes\n");
+ else if (xf86TargetAspect(scrn, config, modes, enabled, width, height))
+ xf86DrvMsg(i, X_INFO, "Using fuzzy aspect match for initial modes\n");
+ else if (xf86TargetFallback(scrn, config, modes, enabled, width, height))
+ xf86DrvMsg(i, X_INFO, "Using sloppy heuristic for initial modes\n");
+ else
+ xf86DrvMsg(i, X_WARNING, "Unable to find initial modes\n");
+ }
+
+ for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+ if (!modes[o])
+ xf86DrvMsg (scrn->scrnIndex, X_ERROR,
+ "Output %s enabled but has no modes\n",
+ config->output[o]->name);
+ else
+ xf86DrvMsg (scrn->scrnIndex, X_INFO,
+ "Output %s using initial mode %s\n",
+ config->output[o]->name, modes[o]->name);
+ }
+
+ /*
+ * Set the position of each output
+ */
+ if (!xf86InitialOutputPositions (scrn, modes))
+ {
+ free(crtcs);
+ free(modes);
+ return FALSE;
+ }
+
+ /*
+ * Set initial panning of each output
+ */
+ xf86InitialPanning (scrn);
+
+ /*
+ * Assign CRTCs to fit output configuration
+ */
+ if (have_outputs && !xf86PickCrtcs (scrn, crtcs, modes, 0, width, height))
+ {
+ free(crtcs);
+ free(modes);
+ return FALSE;
+ }
+
+ /* XXX override xf86 common frame computation code */
+
+ scrn->display->frameX0 = 0;
+ scrn->display->frameY0 = 0;
+
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = config->crtc[c];
+
+ crtc->enabled = FALSE;
+ memset (&crtc->desiredMode, '\0', sizeof (crtc->desiredMode));
+ /* Set default gamma for all crtc's. */
+ /* This is done to avoid problems later on with cloned outputs. */
+ xf86CrtcSetInitialGamma(crtc, 1.0, 1.0, 1.0);
+ }
+
+ if (xf86_crtc_supports_gamma(scrn))
+ xf86DrvMsg(scrn->scrnIndex, X_INFO, "Using default gamma of (1.0, 1.0, 1.0) unless otherwise stated.\n");
+
+ /*
+ * Set initial configuration
+ */
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+ DisplayModePtr mode = modes[o];
+ xf86CrtcPtr crtc = crtcs[o];
+
+ if (mode && crtc)
+ {
+ crtc->desiredMode = *mode;
+ crtc->desiredRotation = output->initial_rotation;
+ crtc->desiredX = output->initial_x;
+ crtc->desiredY = output->initial_y;
+ crtc->desiredTransformPresent = FALSE;
+ crtc->enabled = TRUE;
+ memcpy (&crtc->panningTotalArea, &output->initialTotalArea, sizeof(BoxRec));
+ memcpy (&crtc->panningTrackingArea, &output->initialTrackingArea, sizeof(BoxRec));
+ memcpy (crtc->panningBorder, output->initialBorder, 4*sizeof(INT16));
+ output->crtc = crtc;
+ if (!xf86OutputSetInitialGamma(output))
+ xf86DrvMsg (scrn->scrnIndex, X_WARNING, "Initial gamma correction for output %s: failed.\n", output->name);
+ } else {
+ output->crtc = NULL;
+ }
+ }
+
+ if (scrn->display->virtualX == 0)
+ {
+ /*
+ * Expand virtual size to cover the current config and potential mode
+ * switches, if the driver can't enlarge the screen later.
+ */
+ xf86DefaultScreenLimits (scrn, &width, &height, canGrow);
+
+ if (have_outputs == FALSE) {
+ if (width < NO_OUTPUT_DEFAULT_WIDTH && height < NO_OUTPUT_DEFAULT_HEIGHT) {
+ width = NO_OUTPUT_DEFAULT_WIDTH;
+ height = NO_OUTPUT_DEFAULT_HEIGHT;
+ }
+ }
+
+ scrn->display->virtualX = width;
+ scrn->display->virtualY = height;
+ }
+
+ if (width > scrn->virtualX)
+ scrn->virtualX = width;
+ if (height > scrn->virtualY)
+ scrn->virtualY = height;
+
+ /*
+ * Make sure the configuration isn't too small.
+ */
+ if (width < config->minWidth || height < config->minHeight)
+ return FALSE;
+
+ /*
+ * Limit the crtc config to virtual[XY] if the driver can't grow the
+ * desktop.
+ */
+ if (!canGrow)
+ {
+ xf86CrtcSetSizeRange (scrn, config->minWidth, config->minHeight,
+ width, height);
+ }
+
+ if (have_outputs) {
+ /* Mirror output modes to scrn mode list */
+ xf86SetScrnInfoModes (scrn);
+ } else {
+ /* Clear any existing modes from scrn->modes */
+ while (scrn->modes != NULL)
+ xf86DeleteMode(&scrn->modes, scrn->modes);
+ scrn->modes = xf86ModesAdd(scrn->modes,
+ xf86CVTMode(width, height, 60, 0, 0));
+ }
+
+
+ free(crtcs);
+ free(modes);
+ return TRUE;
+}
+
+/*
+ * Check the CRTC we're going to map each output to vs. it's current
+ * CRTC. If they don't match, we have to disable the output and the CRTC
+ * since the driver will have to re-route things.
+ */
+static void
+xf86PrepareOutputs (ScrnInfoPtr scrn)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int o;
+
+ for (o = 0; o < config->num_output; o++) {
+ xf86OutputPtr output = config->output[o];
+#if RANDR_GET_CRTC_INTERFACE
+ /* Disable outputs that are unused or will be re-routed */
+ if (!output->funcs->get_crtc ||
+ output->crtc != (*output->funcs->get_crtc)(output) ||
+ output->crtc == NULL)
+#endif
+ (*output->funcs->dpms)(output, DPMSModeOff);
+ }
+}
+
+static void
+xf86PrepareCrtcs (ScrnInfoPtr scrn)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c;
+
+ for (c = 0; c < config->num_crtc; c++) {
+#if RANDR_GET_CRTC_INTERFACE
+ xf86CrtcPtr crtc = config->crtc[c];
+ xf86OutputPtr output = NULL;
+ uint32_t desired_outputs = 0, current_outputs = 0;
+ int o;
+
+ for (o = 0; o < config->num_output; o++) {
+ output = config->output[o];
+ if (output->crtc == crtc)
+ desired_outputs |= (1<<o);
+ /* If we can't tell where it's mapped, force it off */
+ if (!output->funcs->get_crtc) {
+ desired_outputs = 0;
+ break;
+ }
+ if ((*output->funcs->get_crtc)(output) == crtc)
+ current_outputs |= (1<<o);
+ }
+
+ /*
+ * If mappings are different or the CRTC is unused,
+ * we need to disable it
+ */
+ if (desired_outputs != current_outputs ||
+ !desired_outputs)
+ (*crtc->funcs->dpms)(crtc, DPMSModeOff);
+#else
+ (*crtc->funcs->dpms)(crtc, DPMSModeOff);
+#endif
+ }
+}
+
+/*
+ * Using the desired mode information in each crtc, set
+ * modes (used in EnterVT functions, or at server startup)
+ */
+
+Bool
+xf86SetDesiredModes (ScrnInfoPtr scrn)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ xf86CrtcPtr crtc = config->crtc[0];
+ int c;
+
+ /* A driver with this hook will take care of this */
+ if (!crtc->funcs->set_mode_major) {
+ xf86PrepareOutputs(scrn);
+ xf86PrepareCrtcs(scrn);
+ }
+
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ xf86OutputPtr output = NULL;
+ xf86CrtcSetRec set;
+ int o;
+ RRTransformPtr transform;
+
+ crtc = config->crtc[c];
+
+ /* Skip disabled CRTCs */
+ if (!crtc->enabled)
+ continue;
+
+ if (xf86CompatOutput(scrn) && xf86CompatCrtc(scrn) == crtc)
+ output = xf86CompatOutput(scrn);
+ else
+ {
+ for (o = 0; o < config->num_output; o++)
+ if (config->output[o]->crtc == crtc)
+ {
+ output = config->output[o];
+ break;
+ }
+ }
+ /* paranoia */
+ if (!output)
+ continue;
+
+ /* Mark that we'll need to re-set the mode for sure */
+ memset(&crtc->mode, 0, sizeof(crtc->mode));
+ if (!crtc->desiredMode.CrtcHDisplay)
+ {
+ DisplayModePtr mode = xf86OutputFindClosestMode (output, scrn->currentMode);
+
+ if (!mode)
+ return FALSE;
+ crtc->desiredMode = *mode;
+ crtc->desiredRotation = RR_Rotate_0;
+ crtc->desiredTransformPresent = FALSE;
+ crtc->desiredX = 0;
+ crtc->desiredY = 0;
+ }
+
+ if (crtc->desiredTransformPresent)
+ transform = &crtc->desiredTransform;
+ else
+ transform = NULL;
+ set.mode = &crtc->desiredMode;
+ set.rotation = crtc->desiredRotation;
+ set.transform = transform;
+ set.x = crtc->desiredX;
+ set.y = crtc->desiredY;
+ set.flags = (XF86CrtcSetMode | XF86CrtcSetOutput |
+ XF86CrtcSetOrigin | XF86CrtcSetTransform |
+ XF86CrtcSetRotation);
+ if (!xf86CrtcSet(crtc, &set))
+ return FALSE;
+ }
+
+ xf86DisableUnusedFunctions(scrn);
+ return TRUE;
+}
+
+/**
+ * In the current world order, there are lists of modes per output, which may
+ * or may not include the mode that was asked to be set by XFree86's mode
+ * selection. Find the closest one, in the following preference order:
+ *
+ * - Equality
+ * - Closer in size to the requested mode, but no larger
+ * - Closer in refresh rate to the requested mode.
+ */
+
+DisplayModePtr
+xf86OutputFindClosestMode (xf86OutputPtr output, DisplayModePtr desired)
+{
+ DisplayModePtr best = NULL, scan = NULL;
+
+ for (scan = output->probed_modes; scan != NULL; scan = scan->next)
+ {
+ /* If there's an exact match, we're done. */
+ if (xf86ModesEqual(scan, desired)) {
+ best = desired;
+ break;
+ }
+
+ /* Reject if it's larger than the desired mode. */
+ if (scan->HDisplay > desired->HDisplay ||
+ scan->VDisplay > desired->VDisplay)
+ {
+ continue;
+ }
+
+ /*
+ * If we haven't picked a best mode yet, use the first
+ * one in the size range
+ */
+ if (best == NULL)
+ {
+ best = scan;
+ continue;
+ }
+
+ /* Find if it's closer to the right size than the current best
+ * option.
+ */
+ if ((scan->HDisplay > best->HDisplay &&
+ scan->VDisplay >= best->VDisplay) ||
+ (scan->HDisplay >= best->HDisplay &&
+ scan->VDisplay > best->VDisplay))
+ {
+ best = scan;
+ continue;
+ }
+
+ /* Find if it's still closer to the right refresh than the current
+ * best resolution.
+ */
+ if (scan->HDisplay == best->HDisplay &&
+ scan->VDisplay == best->VDisplay &&
+ (fabs(scan->VRefresh - desired->VRefresh) <
+ fabs(best->VRefresh - desired->VRefresh))) {
+ best = scan;
+ }
+ }
+ return best;
+}
+
+/**
+ * When setting a mode through XFree86-VidModeExtension or XFree86-DGA,
+ * take the specified mode and apply it to the crtc connected to the compat
+ * output. Then, find similar modes for the other outputs, as with the
+ * InitialConfiguration code above. The goal is to clone the desired
+ * mode across all outputs that are currently active.
+ */
+
+Bool
+xf86SetSingleMode (ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ Bool ok = TRUE;
+ xf86OutputPtr compat_output;
+ DisplayModePtr compat_mode = NULL;
+ int c;
+
+ /*
+ * Let the compat output drive the final mode selection
+ */
+ compat_output = xf86CompatOutput(pScrn);
+ if (compat_output)
+ compat_mode = xf86OutputFindClosestMode (compat_output, desired);
+ if (compat_mode)
+ desired = compat_mode;
+
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = config->crtc[c];
+ DisplayModePtr crtc_mode = NULL;
+ int o;
+ xf86CrtcSetRec set;
+
+ if (!crtc->enabled)
+ continue;
+
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+ DisplayModePtr output_mode;
+
+ /* skip outputs not on this crtc */
+ if (output->crtc != crtc)
+ continue;
+
+ if (crtc_mode)
+ {
+ output_mode = xf86OutputFindClosestMode (output, crtc_mode);
+ if (output_mode != crtc_mode)
+ output->crtc = NULL;
+ }
+ else
+ crtc_mode = xf86OutputFindClosestMode (output, desired);
+ }
+ if (!crtc_mode)
+ {
+ crtc->enabled = FALSE;
+ continue;
+ }
+ set.mode = crtc_mode;
+ set.rotation = rotation;
+ set.transform = NULL;
+ set.x = 0;
+ set.y = 0;
+ set.flags = (XF86CrtcSetMode | XF86CrtcSetOutput |
+ XF86CrtcSetOrigin | XF86CrtcSetTransform |
+ XF86CrtcSetRotation);
+ if (!xf86CrtcSet (crtc, &set))
+ ok = FALSE;
+ else
+ {
+ crtc->desiredMode = *crtc_mode;
+ crtc->desiredRotation = rotation;
+ crtc->desiredTransformPresent = FALSE;
+ crtc->desiredX = 0;
+ crtc->desiredY = 0;
+ }
+ }
+ xf86DisableUnusedFunctions(pScrn);
+#ifdef RANDR_12_INTERFACE
+ xf86RandR12TellChanged (pScrn->pScreen);
+#endif
+ return ok;
+}
+
+
+/**
+ * Set the DPMS power mode of all outputs and CRTCs.
+ *
+ * If the new mode is off, it will turn off outputs and then CRTCs.
+ * Otherwise, it will affect CRTCs before outputs.
+ */
+void
+xf86DPMSSet(ScrnInfoPtr scrn, int mode, int flags)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int i;
+
+ if (!scrn->vtSema)
+ return;
+
+ if (mode == DPMSModeOff) {
+ for (i = 0; i < config->num_output; i++) {
+ xf86OutputPtr output = config->output[i];
+ if (output->crtc != NULL)
+ (*output->funcs->dpms) (output, mode);
+ }
+ }
+
+ for (i = 0; i < config->num_crtc; i++) {
+ xf86CrtcPtr crtc = config->crtc[i];
+ if (crtc->enabled)
+ (*crtc->funcs->dpms) (crtc, mode);
+ }
+
+ if (mode != DPMSModeOff) {
+ for (i = 0; i < config->num_output; i++) {
+ xf86OutputPtr output = config->output[i];
+ if (output->crtc != NULL)
+ (*output->funcs->dpms) (output, mode);
+ }
+ }
+}
+
+/**
+ * Implement the screensaver by just calling down into the driver DPMS hooks.
+ *
+ * Even for monitors with no DPMS support, by the definition of our DPMS hooks,
+ * the outputs will still get disabled (blanked).
+ */
+Bool
+xf86SaveScreen(ScreenPtr pScreen, int mode)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+ if (xf86IsUnblank(mode))
+ xf86DPMSSet(pScrn, DPMSModeOn, 0);
+ else
+ xf86DPMSSet(pScrn, DPMSModeOff, 0);
+
+ return TRUE;
+}
+
+/**
+ * Disable all inactive crtcs and outputs
+ */
+void
+xf86DisableUnusedFunctions(ScrnInfoPtr pScrn)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int o, c;
+
+ for (o = 0; o < xf86_config->num_output; o++)
+ {
+ xf86OutputPtr output = xf86_config->output[o];
+ if (!output->crtc)
+ (*output->funcs->dpms)(output, DPMSModeOff);
+ }
+
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+ if (!crtc->enabled)
+ {
+ crtc->funcs->dpms(crtc, DPMSModeOff);
+ memset(&crtc->mode, 0, sizeof(crtc->mode));
+ xf86RotateDestroy(crtc);
+ crtc->active = FALSE;
+ }
+ }
+ if (pScrn->pScreen)
+ xf86_crtc_notify(pScrn->pScreen);
+ if (pScrn->ModeSet)
+ pScrn->ModeSet(pScrn);
+}
+
+#ifdef RANDR_12_INTERFACE
+
+#define EDID_ATOM_NAME "EDID"
+
+/**
+ * Set the RandR EDID property
+ */
+static void
+xf86OutputSetEDIDProperty (xf86OutputPtr output, void *data, int data_len)
+{
+ Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME) - 1, TRUE);
+
+ /* This may get called before the RandR resources have been created */
+ if (output->randr_output == NULL)
+ return;
+
+ if (data_len != 0) {
+ RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8,
+ PropModeReplace, data_len, data, FALSE, TRUE);
+ } else {
+ RRDeleteOutputProperty(output->randr_output, edid_atom);
+ }
+}
+
+#endif
+
+/* Pull out a phyiscal size from a detailed timing if available. */
+struct det_phySize_parameter {
+ xf86OutputPtr output;
+ ddc_quirk_t quirks;
+ Bool ret;
+};
+
+static void handle_detailed_physical_size(struct detailed_monitor_section
+ *det_mon, void *data)
+{
+ struct det_phySize_parameter *p;
+ p = (struct det_phySize_parameter *)data;
+
+ if (p->ret == TRUE )
+ return ;
+
+ xf86DetTimingApplyQuirks(det_mon, p->quirks,
+ p->output->MonInfo->features.hsize,
+ p->output->MonInfo->features.vsize);
+ if (det_mon->type == DT &&
+ det_mon->section.d_timings.h_size != 0 &&
+ det_mon->section.d_timings.v_size != 0) {
+
+ p->output->mm_width = det_mon->section.d_timings.h_size;
+ p->output->mm_height = det_mon->section.d_timings.v_size;
+ p->ret = TRUE;
+ }
+}
+
+/**
+ * Set the EDID information for the specified output
+ */
+void
+xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon)
+{
+ ScrnInfoPtr scrn = output->scrn;
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ Bool debug_modes = config->debug_modes || xf86Initialising;
+#ifdef RANDR_12_INTERFACE
+ int size;
+#endif
+
+ free(output->MonInfo);
+
+ output->MonInfo = edid_mon;
+ output->mm_width = 0;
+ output->mm_height = 0;
+
+ if (debug_modes) {
+ xf86DrvMsg(scrn->scrnIndex, X_INFO, "EDID for output %s\n",
+ output->name);
+ xf86PrintEDID(edid_mon);
+ }
+
+ /* Set the DDC properties for the 'compat' output */
+ if (output == xf86CompatOutput(scrn))
+ xf86SetDDCproperties(scrn, edid_mon);
+
+#ifdef RANDR_12_INTERFACE
+ /* Set the RandR output properties */
+ size = 0;
+ if (edid_mon)
+ {
+ if (edid_mon->ver.version == 1) {
+ size = 128;
+ if (edid_mon->flags & EDID_COMPLETE_RAWDATA)
+ size += edid_mon->no_sections * 128;
+ } else if (edid_mon->ver.version == 2)
+ size = 256;
+ }
+ xf86OutputSetEDIDProperty (output, edid_mon ? edid_mon->rawData : NULL, size);
+#endif
+
+ if (edid_mon) {
+
+ struct det_phySize_parameter p;
+ p.output = output;
+ p.quirks = xf86DDCDetectQuirks(scrn->scrnIndex,edid_mon, FALSE);
+ p.ret = FALSE;
+ xf86ForEachDetailedBlock(edid_mon,
+ handle_detailed_physical_size, &p);
+
+ /* if no mm size is available from a detailed timing, check the max size field */
+ if ((!output->mm_width || !output->mm_height) &&
+ (edid_mon->features.hsize && edid_mon->features.vsize))
+ {
+ output->mm_width = edid_mon->features.hsize * 10;
+ output->mm_height = edid_mon->features.vsize * 10;
+ }
+ }
+}
+
+/**
+ * Return the list of modes supported by the EDID information
+ * stored in 'output'
+ */
+DisplayModePtr
+xf86OutputGetEDIDModes (xf86OutputPtr output)
+{
+ ScrnInfoPtr scrn = output->scrn;
+ xf86MonPtr edid_mon = output->MonInfo;
+
+ if (!edid_mon)
+ return NULL;
+ return xf86DDCGetModes(scrn->scrnIndex, edid_mon);
+}
+
+/* maybe we should care about DDC1? meh. */
+xf86MonPtr
+xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus)
+{
+ ScrnInfoPtr scrn = output->scrn;
+ xf86MonPtr mon;
+
+ mon = xf86DoEEDID(scrn->scrnIndex, pDDCBus, TRUE);
+ if (mon)
+ xf86DDCApplyQuirks(scrn->scrnIndex, mon);
+
+ return mon;
+}
+
+static char *_xf86ConnectorNames[] = {
+ "None", "VGA", "DVI-I", "DVI-D",
+ "DVI-A", "Composite", "S-Video",
+ "Component", "LFP", "Proprietary",
+ "HDMI", "DisplayPort",
+ };
+char *
+xf86ConnectorGetName(xf86ConnectorType connector)
+{
+ return _xf86ConnectorNames[connector];
+}
+
+static void
+x86_crtc_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b)
+{
+ dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1;
+ dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2;
+ dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1;
+ dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2;
+
+ if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2)
+ dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;
+}
+
+static void
+x86_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box)
+{
+ if (crtc->enabled) {
+ crtc_box->x1 = crtc->x;
+ crtc_box->x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation);
+ crtc_box->y1 = crtc->y;
+ crtc_box->y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation);
+ } else
+ crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0;
+}
+
+static int
+xf86_crtc_box_area(BoxPtr box)
+{
+ return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1);
+}
+
+/*
+ * Return the crtc covering 'box'. If two crtcs cover a portion of
+ * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc
+ * with greater coverage
+ */
+
+static xf86CrtcPtr
+xf86_covering_crtc(ScrnInfoPtr pScrn,
+ BoxPtr box,
+ xf86CrtcPtr desired,
+ BoxPtr crtc_box_ret)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ xf86CrtcPtr crtc, best_crtc;
+ int coverage, best_coverage;
+ int c;
+ BoxRec crtc_box, cover_box;
+
+ best_crtc = NULL;
+ best_coverage = 0;
+ crtc_box_ret->x1 = 0;
+ crtc_box_ret->x2 = 0;
+ crtc_box_ret->y1 = 0;
+ crtc_box_ret->y2 = 0;
+ for (c = 0; c < xf86_config->num_crtc; c++) {
+ crtc = xf86_config->crtc[c];
+ x86_crtc_box(crtc, &crtc_box);
+ x86_crtc_box_intersect(&cover_box, &crtc_box, box);
+ coverage = xf86_crtc_box_area(&cover_box);
+ if (coverage && crtc == desired) {
+ *crtc_box_ret = crtc_box;
+ return crtc;
+ } else if (coverage > best_coverage) {
+ *crtc_box_ret = crtc_box;
+ best_crtc = crtc;
+ best_coverage = coverage;
+ }
+ }
+ return best_crtc;
+}
+
+/*
+ * For overlay video, compute the relevant CRTC and
+ * clip video to that.
+ *
+ * returning FALSE means there was a memory failure of some kind,
+ * not that the video shouldn't be displayed
+ */
+
+Bool
+xf86_crtc_clip_video_helper(ScrnInfoPtr pScrn,
+ xf86CrtcPtr *crtc_ret,
+ xf86CrtcPtr desired_crtc,
+ BoxPtr dst,
+ INT32 *xa,
+ INT32 *xb,
+ INT32 *ya,
+ INT32 *yb,
+ RegionPtr reg,
+ INT32 width,
+ INT32 height)
+{
+ Bool ret;
+ RegionRec crtc_region_local;
+ RegionPtr crtc_region = reg;
+
+ if (crtc_ret) {
+ BoxRec crtc_box;
+ xf86CrtcPtr crtc = xf86_covering_crtc(pScrn, dst,
+ desired_crtc,
+ &crtc_box);
+
+ if (crtc) {
+ RegionInit(&crtc_region_local, &crtc_box, 1);
+ crtc_region = &crtc_region_local;
+ RegionIntersect(crtc_region, crtc_region, reg);
+ }
+ *crtc_ret = crtc;
+ }
+
+ ret = xf86XVClipVideoHelper(dst, xa, xb, ya, yb,
+ crtc_region, width, height);
+
+ if (crtc_region != reg)
+ RegionUninit(&crtc_region_local);
+
+ return ret;
+}
+
+xf86_crtc_notify_proc_ptr
+xf86_wrap_crtc_notify (ScreenPtr screen, xf86_crtc_notify_proc_ptr new)
+{
+ if (xf86CrtcConfigPrivateIndex != -1)
+ {
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ xf86_crtc_notify_proc_ptr old;
+
+ old = config->xf86_crtc_notify;
+ config->xf86_crtc_notify = new;
+ return old;
+ }
+ return NULL;
+}
+
+void
+xf86_unwrap_crtc_notify(ScreenPtr screen, xf86_crtc_notify_proc_ptr old)
+{
+ if (xf86CrtcConfigPrivateIndex != -1)
+ {
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+
+ config->xf86_crtc_notify = old;
+ }
+}
+
+void
+xf86_crtc_notify(ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+
+ if (config->xf86_crtc_notify)
+ config->xf86_crtc_notify(screen);
+}
+
+Bool
+xf86_crtc_supports_gamma(ScrnInfoPtr pScrn)
+{
+ if (xf86CrtcConfigPrivateIndex != -1) {
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ xf86CrtcPtr crtc;
+
+ /* for multiple drivers loaded we need this */
+ if (!xf86_config)
+ return FALSE;
+ if (xf86_config->num_crtc == 0)
+ return FALSE;
+ crtc = xf86_config->crtc[0];
+
+ return crtc->funcs->gamma_set != NULL;
+ }
+
+ return FALSE;
+}
|