diff options
Diffstat (limited to 'hw/xfree86/common/xf86Config.c')
-rw-r--r-- | hw/xfree86/common/xf86Config.c | 3934 |
1 files changed, 3934 insertions, 0 deletions
diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c new file mode 100644 index 000000000..e523dd0fc --- /dev/null +++ b/hw/xfree86/common/xf86Config.c @@ -0,0 +1,3934 @@ +/* + * $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Config.c,v 3.113.2.17 1998/02/24 19:05:54 hohndel Exp $ + * + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Thomas Roell not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Roell makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS ROELL BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* $Xorg: xf86Config.c,v 1.3 2000/08/17 19:50:28 cpqbld Exp $ */ + +#ifndef X_NOT_STDC_ENV +#include <stdlib.h> +#else +extern double atof(); +extern char *getenv(); +#endif + +#define NEED_EVENTS 1 +#include "X.h" +#include "Xproto.h" +#include "Xmd.h" +#include "input.h" +#include "servermd.h" +#include "scrnintstr.h" + +#ifdef DPMSExtension +#include "opaque.h" +extern CARD32 DPMSStandbyTime; +extern CARD32 DPMSSuspendTime; +extern CARD32 DPMSOffTime; +#endif + +#define NO_COMPILER_H_EXTRAS +#include "xf86Procs.h" +#include "xf86_OSlib.h" + +#define INIT_CONFIG +#include "xf86_Config.h" + +#ifdef XKB +#include "inputstr.h" +#include "XKBsrv.h" +#endif + +#ifdef XF86SETUP +#include "xfsconf.h" +#endif + +#ifdef XINPUT +#include "xf86Xinput.h" + +#ifndef XF86SETUP +extern DeviceAssocRec mouse_assoc; +#endif +#endif + +#ifdef NEED_RETURN_VALUE +#define HANDLE_RETURN(xx) if (xx == RET_ERROR) return RET_ERROR +#else +#define HANDLE_RETURN(xx) xx +#endif + +#define CONFIG_BUF_LEN 1024 + +static FILE * configFile = NULL; +static int configStart = 0; /* start of the current token */ +static int configPos = 0; /* current readers position */ +static int configLineNo = 0; /* linenumber */ +static char *configBuf,*configRBuf; /* buffer for lines */ +static char *configPath; /* path to config file */ +static char *fontPath = NULL; /* font path */ +static char *modulePath = NULL; /* module path */ +static int pushToken = LOCK_TOKEN; +static LexRec val; /* global return value */ +static char DCerr; +static int scr_index = 0; + +#ifdef XF86SETUP +#define STATIC_OR_NOT +#else +#define STATIC_OR_NOT static +#endif +STATIC_OR_NOT int n_monitors = 0; +STATIC_OR_NOT MonPtr monitor_list = NULL; +STATIC_OR_NOT int n_devices = 0; +STATIC_OR_NOT GDevPtr device_list = NULL; + +static int screenno = -100; /* some little number ... */ + +extern char *defaultFontPath; +extern char *rgbPath; + +extern Bool xf86fpFlag, xf86coFlag, xf86sFlag; +extern Bool xf86ScreensOpen; + +extern int defaultColorVisualClass; +extern CARD32 defaultScreenSaverTime, ScreenSaverTime; + +char *xf86VisualNames[] = { + "StaticGray", + "GrayScale", + "StaticColor", + "PseudoColor", + "TrueColor", + "DirectColor" +}; + +static CONFIG_RETURN_TYPE configFilesSection( +#if NeedFunctionPrototypes + void +#endif +); +static CONFIG_RETURN_TYPE configServerFlagsSection( +#if NeedFunctionPrototypes + void +#endif +); +static CONFIG_RETURN_TYPE configKeyboardSection( +#if NeedFunctionPrototypes + void +#endif +); +static CONFIG_RETURN_TYPE configDeviceSection( +#if NeedFunctionPrototypes + void +#endif +); +static CONFIG_RETURN_TYPE configScreenSection( +#if NeedFunctionPrototypes + void +#endif +); +static CONFIG_RETURN_TYPE configDisplaySubsection( +#if NeedFunctionPrototypes + DispPtr disp +#endif +); +static CONFIG_RETURN_TYPE configMonitorSection( +#if NeedFunctionPrototypes + void +#endif +); +static CONFIG_RETURN_TYPE configDynamicModuleSection( +#if NeedFunctionPrototypes + void +#endif +); +static char *xf86DCSaveLine( +#if NeedFunctionPrototypes +char *, +int +#endif +); +static char *xf86DCOption( +#if NeedFunctionPrototypes +char *, +LexRec +#endif +); +static char * xf86DCConcatOption( +#if NeedFunctionPrototypes +char *, +char * +#endif +); +#ifndef XF86SETUP +static +#endif +CONFIG_RETURN_TYPE findConfigFile( +#if NeedFunctionPrototypes + char *filename, + FILE **fp +#endif +); +static int getScreenIndex( +#if NeedFunctionPrototypes + int token +#endif +); +static int getStringToken( +#if NeedFunctionPrototypes + SymTabRec tab[] +#endif +); +static CONFIG_RETURN_TYPE readVerboseMode( +#if NeedFunctionPrototypes + MonPtr monp +#endif +); +static Bool validateGraphicsToken( +#if NeedFunctionPrototypes + int *validTokens, + int token +#endif +); +extern char * xf86GetPathElem( +#if NeedFunctionPrototypes + char **pnt +#endif +); +static DisplayModePtr xf86PruneModes( +#if NeedFunctionPrototypes + MonPtr monp, + DisplayModePtr allmodes, + ScrnInfoPtr scrp, + Bool card +#endif +); +static char * xf86ValidateFontPath( +#if NeedFunctionPrototypes + char * /* path */ +#endif +); +#ifdef XINPUT +extern CONFIG_RETURN_TYPE xf86ConfigExtendedInputSection( +#if NeedFunctionPrototypes + LexPtr pval +#endif +); +#endif + +#ifdef XKB +extern char *XkbInitialMap; +#endif + +#define DIR_FILE "/fonts.dir" + +/* + * xf86GetPathElem -- + * Extract a single element from the font path string starting at + * pnt. The font path element will be returned, and pnt will be + * updated to point to the start of the next element, or set to + * NULL if there are no more. + */ +char * +xf86GetPathElem(pnt) + char **pnt; +{ + char *p1; + + p1 = *pnt; + *pnt = index(*pnt, ','); + if (*pnt != NULL) { + **pnt = '\0'; + *pnt += 1; + } + return(p1); +} + +/* + * StrToUL -- + * + * A portable, but restricted, version of strtoul(). It only understands + * hex, octal, and decimal. But it's good enough for our needs. + */ +unsigned int StrToUL(str) +char *str; +{ + int base = 10; + char *p = str; + unsigned int tot = 0; + + if (*p == '0') { + p++; + if (*p == 'x') { + p++; + base = 16; + } + else + base = 8; + } + while (*p) { + if ((*p >= '0') && (*p <= ((base == 8)?'7':'9'))) { + tot = tot * base + (*p - '0'); + } + else if ((base == 16) && (*p >= 'a') && (*p <= 'f')) { + tot = tot * base + 10 + (*p - 'a'); + } + else if ((base == 16) && (*p >= 'A') && (*p <= 'F')) { + tot = tot * base + 10 + (*p - 'A'); + } + else { + return(tot); + } + p++; + } + return(tot); +} + +/* + * xf86ValidateFontPath -- + * Validates the user-specified font path. Each element that + * begins with a '/' is checked to make sure the directory exists. + * If the directory exists, the existence of a file named 'fonts.dir' + * is checked. If either check fails, an error is printed and the + * element is removed from the font path. + */ +#define CHECK_TYPE(mode, type) ((S_IFMT & (mode)) == (type)) +static char * +xf86ValidateFontPath(path) + char *path; +{ + char *tmp_path, *out_pnt, *path_elem, *next, *p1, *dir_elem; + struct stat stat_buf; + int flag; + int dirlen; + + tmp_path = (char *)Xcalloc(strlen(path)+1); + out_pnt = tmp_path; + path_elem = NULL; + next = path; + while (next != NULL) { + path_elem = xf86GetPathElem(&next); +#ifndef __EMX__ + if (*path_elem == '/') { + dir_elem = (char *)Xcalloc(strlen(path_elem) + 1); + if ((p1 = strchr(path_elem, ':')) != 0) +#else + /* OS/2 must prepend X11ROOT */ + if (*path_elem == '/') { + path_elem = (char*)__XOS2RedirRoot(path_elem); + dir_elem = (char*)xcalloc(1, strlen(path_elem) + 1); + if (p1 = strchr(path_elem+2, ':')) +#endif + dirlen = p1 - path_elem; + else + dirlen = strlen(path_elem); + strncpy(dir_elem, path_elem, dirlen); + dir_elem[dirlen] = '\0'; + flag = stat(dir_elem, &stat_buf); + if (flag == 0) + if (!CHECK_TYPE(stat_buf.st_mode, S_IFDIR)) + flag = -1; + if (flag != 0) { + ErrorF("Warning: The directory \"%s\" does not exist.\n", dir_elem); + ErrorF(" Entry deleted from font path.\n"); + continue; + } + else { + p1 = (char *)xalloc(strlen(dir_elem)+strlen(DIR_FILE)+1); + strcpy(p1, dir_elem); + strcat(p1, DIR_FILE); + flag = stat(p1, &stat_buf); + if (flag == 0) + if (!CHECK_TYPE(stat_buf.st_mode, S_IFREG)) + flag = -1; +#ifndef __EMX__ + xfree(p1); +#endif + if (flag != 0) { + ErrorF("Warning: 'fonts.dir' not found (or not valid) in \"%s\".\n", + dir_elem); + ErrorF(" Entry deleted from font path.\n"); + ErrorF(" (Run 'mkfontdir' on \"%s\").\n", dir_elem); + continue; + } + } + xfree(dir_elem); + } + + /* + * Either an OK directory, or a font server name. So add it to + * the path. + */ + if (out_pnt != tmp_path) + *out_pnt++ = ','; + strcat(out_pnt, path_elem); + out_pnt += strlen(path_elem); + } + return(tmp_path); +} + +/* + * xf86GetToken -- + * Read next Token form the config file. Handle the global variable + * pushToken. + */ +int +xf86GetToken(tab) + SymTabRec tab[]; +{ + int c, i; + + /* + * First check whether pushToken has a different value than LOCK_TOKEN. + * In this case rBuf[] contains a valid STRING/TOKEN/NUMBER. But in the other + * case the next token must be read from the input. + */ + if (pushToken == EOF) return(EOF); + else if (pushToken == LOCK_TOKEN) + { + + c = configBuf[configPos]; + + /* + * Get start of next Token. EOF is handled, whitespaces & comments are + * skipped. + */ + do { + if (!c) { + if (fgets(configBuf,CONFIG_BUF_LEN-1,configFile) == NULL) + { + return( pushToken = EOF ); + } + configLineNo++; + configStart = configPos = 0; + } +#ifndef __EMX__ + while (((c=configBuf[configPos++])==' ') || ( c=='\t') || ( c=='\n')); +#else + while (((c=configBuf[configPos++])==' ') || ( c=='\t') || ( c=='\n') + || (c=='\r')); +#endif + if (c == '#') c = '\0'; + } while (!c); + + /* GJA -- handle '-' and ',' + * Be careful: "-hsync" is a keyword. + */ + if ( (c == ',') && !isalpha(configBuf[configPos]) ) { + configStart = configPos; return COMMA; + } else if ( (c == '-') && !isalpha(configBuf[configPos]) ) { + configStart = configPos; return DASH; + } + + configStart = configPos; + /* + * Numbers are returned immediately ... + */ + if (isdigit(c)) + { + int base; + + if (c == '0') + if ((configBuf[configPos] == 'x') || + (configBuf[configPos] == 'X')) + base = 16; + else + base = 8; + else + base = 10; + + configRBuf[0] = c; i = 1; + while (isdigit(c = configBuf[configPos++]) || + (c == '.') || (c == 'x') || + ((base == 16) && (((c >= 'a') && (c <= 'f')) || + ((c >= 'A') && (c <= 'F'))))) + configRBuf[i++] = c; + configPos--; /* GJA -- one too far */ + configRBuf[i] = '\0'; + val.num = StrToUL(configRBuf); + val.realnum = atof(configRBuf); + return(NUMBER); + } + + /* + * All Strings START with a \" ... + */ + else if (c == '\"') + { + i = -1; + do { + configRBuf[++i] = (c = configBuf[configPos++]); +#ifndef __EMX__ + } while ((c != '\"') && (c != '\n') && (c != '\0')); +#else + } while ((c != '\"') && (c != '\n') && (c != '\r') && (c != '\0')); +#endif + configRBuf[i] = '\0'; + val.str = (char *)xalloc(strlen(configRBuf) + 1); + strcpy(val.str, configRBuf); /* private copy ! */ + return(STRING); + } + + /* + * ... and now we MUST have a valid token. The search is + * handled later along with the pushed tokens. + */ + else + { + configRBuf[0] = c; + i = 0; + do { + configRBuf[++i] = (c = configBuf[configPos++]);; +#ifndef __EMX__ + } while ((c != ' ') && (c != '\t') && (c != '\n') && (c != '\0')); +#else + } while ((c != ' ') && (c != '\t') && (c != '\n') && (c != '\r') && (c != '\0') ); +#endif + configRBuf[i] = '\0'; i=0; + } + + } + else + { + + /* + * Here we deal with pushed tokens. Reinitialize pushToken again. If + * the pushed token was NUMBER || STRING return them again ... + */ + int temp = pushToken; + pushToken = LOCK_TOKEN; + + if (temp == COMMA || temp == DASH) return(temp); + if (temp == NUMBER || temp == STRING) return(temp); + } + + /* + * Joop, at last we have to lookup the token ... + */ + if (tab) + { + i = 0; + while (tab[i].token != -1) + if (StrCaseCmp(configRBuf,tab[i].name) == 0) + return(tab[i].token); + else + i++; + } + + return(ERROR_TOKEN); /* Error catcher */ +} + +/* + * xf86GetToken -- + * Lookup a string if it is actually a token in disguise. + */ +static int +getStringToken(tab) + SymTabRec tab[]; +{ + int i; + + for ( i = 0 ; tab[i].token != -1 ; i++ ) { + if ( ! StrCaseCmp(tab[i].name,val.str) ) return tab[i].token; + } + return(ERROR_TOKEN); +} + +/* + * getScreenIndex -- + * Given the screen token, returns the index in xf86Screens, or -1 if + * the screen type is not applicable to this server. + */ +static int +getScreenIndex(token) + int token; +{ + int i; + + for (i = 0; xf86ScreenNames[i] >= 0 && xf86ScreenNames[i] != token; i++) + ; + if (xf86ScreenNames[i] < 0) + return(-1); + else + return(i); +} + +/* + * validateGraphicsToken -- + * If token is a graphics token, check it is in the list of validTokens + * XXXX This needs modifying to work as it did with the old format + */ +static Bool +validateGraphicsToken(validTokens, token) + int *validTokens; + int token; +{ + int i; + + for (i = 0; ScreenTab[i].token >= 0 && ScreenTab[i].token != token; i++) + ; + if (ScreenTab[i].token < 0) + return(FALSE); /* Not a graphics token */ + + for (i = 0; validTokens[i] >= 0 && validTokens[i] != token; i++) + ; + return(validTokens[i] >= 0); +} + +/* + * xf86TokenToString -- + * returns the string corresponding to token + */ +char * +xf86TokenToString(table, token) + SymTabPtr table; + int token; +{ + int i; + + for (i = 0; table[i].token >= 0 && table[i].token != token; i++) + ; + if (table[i].token < 0) + return("unknown"); + else + return(table[i].name); +} + +/* + * xf86StringToToken -- + * returns the string corresponding to token + */ +int +xf86StringToToken(table, string) + SymTabPtr table; + char *string; +{ + int i; + + for (i = 0; table[i].token >= 0 && StrCaseCmp(string, table[i].name); i++) + ; + return(table[i].token); +} + +/* + * xf86ConfigError -- + * Print a READABLE ErrorMessage!!! All information that is + * interesting is printed. Even a pointer to the erroneous place is + * printed. Maybe our e-mail will be less :-) + */ +#ifdef XF86SETUP +int +XF86SetupXF86ConfigError(msg) +#else +void +xf86ConfigError(msg) +#endif + char *msg; +{ + int i,j; + + ErrorF( "\nConfig Error: %s:%d\n\n%s", configPath, configLineNo, configBuf); + for (i = 1, j = 1; i < configStart; i++, j++) + if (configBuf[i-1] != '\t') + ErrorF(" "); + else + do + ErrorF(" "); + while (((j++)%8) != 0); + for (i = configStart; i <= configPos; i++) ErrorF("^"); + ErrorF("\n%s\n", msg); +#ifdef NEED_RETURN_VALUE + return RET_ERROR; +#else + exit(-1); /* simple exit ... */ +#endif +} + +#ifndef XF86SETUP +void +xf86DeleteMode(infoptr, dispmp) +ScrnInfoPtr infoptr; +DisplayModePtr dispmp; +{ + if(infoptr->modes == dispmp) + infoptr->modes = dispmp->next; + + if(dispmp->next == dispmp) + FatalError("No valid modes found.\n"); + + ErrorF("%s %s: Removing mode \"%s\" from list of valid modes.\n", + XCONFIG_PROBED, infoptr->name, dispmp->name); + dispmp->prev->next = dispmp->next; + dispmp->next->prev = dispmp->prev; + + xfree(dispmp->name); + xfree(dispmp); +} +#endif + +/* + * findConfigFile -- + * Locate the XF86Config file. Abort if not found. + */ +#ifndef XF86SETUP +static +#endif +CONFIG_RETURN_TYPE +findConfigFile(filename, fp) + char *filename; + FILE **fp; +{ +#define configFile (*fp) +#define MAXPTRIES 6 + char *home = NULL; + char *xconfig = NULL; + char *xwinhome = NULL; + char *configPaths[MAXPTRIES]; + int pcount = 0, idx; + + /* + * First open if necessary the config file. + * If the -xf86config flag was used, use the name supplied there (root only). + * If $XF86CONFIG is a pathname, use it as the name of the config file (root) + * If $XF86CONFIG is set but doesn't contain a '/', append it to 'XF86Config' + * and search the standard places (root only). + * If $XF86CONFIG is not set, just search the standard places. + */ + while (!configFile) { + + /* + * configPaths[0] is used as a buffer for -xf86config + * and $XF86CONFIG if it contains a path + * configPaths[1...MAXPTRIES-1] is used to store the paths of each of + * the other attempts + */ + for (pcount = idx = 0; idx < MAXPTRIES; idx++) + configPaths[idx] = NULL; + + /* + * First check if the -xf86config option was used. + */ + configPaths[pcount] = (char *)xalloc(PATH_MAX); +#ifndef __EMX__ + if (getuid() == 0 && xf86ConfigFile[0]) +#else + if (xf86ConfigFile[0]) +#endif + { + strcpy(configPaths[pcount], xf86ConfigFile); + if ((configFile = fopen(configPaths[pcount], "r")) != 0) + break; + else + FatalError( + "Cannot read file \"%s\" specified by the -xf86config flag\n", + configPaths[pcount]); + } + /* + * Check if XF86CONFIG is set. + */ +#ifndef __EMX__ + if (getuid() == 0 + && (xconfig = getenv("XF86CONFIG")) != 0 + && index(xconfig, '/')) +#else + /* no root available, and filenames start with drive letter */ + if ((xconfig = getenv("XF86CONFIG")) != 0 + && isalpha(xconfig[0]) + && xconfig[1]==':') +#endif + { + strcpy(configPaths[pcount], xconfig); + if ((configFile = fopen(configPaths[pcount], "r")) != 0) + break; + else + FatalError( + "Cannot read file \"%s\" specified by XF86CONFIG variable\n", + configPaths[pcount]); + } + +#ifndef __EMX__ + /* + * ~/XF86Config ... + */ + if (getuid() == 0 && (home = getenv("HOME"))) { + configPaths[++pcount] = (char *)xalloc(PATH_MAX); + strcpy(configPaths[pcount],home); + strcat(configPaths[pcount],"/XF86Config"); + if (xconfig) strcat(configPaths[pcount],xconfig); + if ((configFile = fopen( configPaths[pcount], "r" )) != 0) break; + } + + /* + * /etc/XF86Config + */ + configPaths[++pcount] = (char *)xalloc(PATH_MAX); + strcpy(configPaths[pcount], "/etc/XF86Config"); + if (xconfig) strcat(configPaths[pcount],xconfig); + if ((configFile = fopen( configPaths[pcount], "r" )) != 0) break; + + /* + * $(LIBDIR)/XF86Config.<hostname> + */ + + configPaths[++pcount] = (char *)xalloc(PATH_MAX); + if (getuid() == 0 && (xwinhome = getenv("XWINHOME")) != NULL) + sprintf(configPaths[pcount], "%s/lib/X11/XF86Config", xwinhome); + else + strcpy(configPaths[pcount], SERVER_CONFIG_FILE); + if (getuid() == 0 && xconfig) strcat(configPaths[pcount],xconfig); + strcat(configPaths[pcount], "."); +#ifdef AMOEBA + { + extern char *XServerHostName; + + strcat(configPaths[pcount], XServerHostName); + } +#else + gethostname(configPaths[pcount]+strlen(configPaths[pcount]), + MAXHOSTNAMELEN); +#endif + if ((configFile = fopen( configPaths[pcount], "r" )) != 0) break; +#endif /* !__EMX__ */ + + /* + * $(LIBDIR)/XF86Config + */ + configPaths[++pcount] = (char *)xalloc(PATH_MAX); +#ifndef __EMX__ + if (getuid() == 0 && xwinhome) + sprintf(configPaths[pcount], "%s/lib/X11/XF86Config", xwinhome); + else + strcpy(configPaths[pcount], SERVER_CONFIG_FILE); + if (getuid() == 0 && xconfig) strcat(configPaths[pcount],xconfig); +#else + /* we explicitly forbid numerous config files everywhere for OS/2; + * users should consider them lucky to have one in a standard place + * and another one with the -xf86config option + */ + xwinhome = getenv("X11ROOT"); /* get drive letter */ + if (!xwinhome) FatalError("X11ROOT environment variable not set\n"); + strcpy(configPaths[pcount], __XOS2RedirRoot("/XFree86/lib/X11/XConfig")); +#endif + + if ((configFile = fopen( configPaths[pcount], "r" )) != 0) break; + + ErrorF("\nCould not find config file!\n"); + ErrorF("- Tried:\n"); + for (idx = 1; idx <= pcount; idx++) + if (configPaths[idx] != NULL) + ErrorF(" %s\n", configPaths[idx]); + FatalError("No config file found!\n%s", getuid() == 0 ? "" : + "Note, the X server no longer looks for XF86Config in $HOME"); + } + strcpy(filename, configPaths[pcount]); + if (xf86Verbose) { + ErrorF("XF86Config: %s\n", filename); + ErrorF("%s stands for supplied, %s stands for probed/default values\n", + XCONFIG_GIVEN, XCONFIG_PROBED); + } + for (idx = 0; idx <= pcount; idx++) + if (configPaths[idx] != NULL) + xfree(configPaths[idx]); +#undef configFile +#undef MAXPTRIES +#ifdef NEED_RETURN_VALUE + return RET_OKAY; +#endif +} + +static DisplayModePtr pNew, pLast; +static Bool graphFound = FALSE; + +/* + * xf86GetNearestClock -- + * Find closest clock to given frequency (in kHz). This assumes the + * number of clocks is greater than zero. + */ +int +xf86GetNearestClock(Screen, Frequency) + ScrnInfoPtr Screen; + int Frequency; +{ + int NearestClock = 0; + int MinimumGap = abs(Frequency - Screen->clock[0]); + int i; + for (i = 1; i < Screen->clocks; i++) + { + int Gap = abs(Frequency - Screen->clock[i]); + if (Gap < MinimumGap) + { + MinimumGap = Gap; + NearestClock = i; + } + } + return NearestClock; +} + +/* + * xf86Config -- + * Fill some internal structure with userdefined setups. Many internal + * Structs are initialized. The drivers are selected and initialized. + * if (! vtopen), XF86Config is read, but devices are not probed. + * if (vtopen), devices are probed (and modes resolved). + * The vtopen argument was added so that XF86Config information could be + * made available before the VT is opened. + */ +CONFIG_RETURN_TYPE +xf86Config (vtopen) + int vtopen; +{ + int token; + int i, j; +#if defined(SYSV) || defined(linux) + int xcpipe[2]; +#endif +#ifdef XINPUT + LocalDevicePtr local; +#endif + + if (!vtopen) + { + + OFLG_ZERO(&GenericXF86ConfigFlag); + configBuf = (char*)xalloc(CONFIG_BUF_LEN); + configRBuf = (char*)xalloc(CONFIG_BUF_LEN); + configPath = (char*)xalloc(PATH_MAX); + + configBuf[0] = '\0'; /* sanity ... */ + + /* + * Read the XF86Config file with the real uid to avoid security problems + * + * For SYSV we fork, and send the data back to the parent through a pipe + */ +#if defined(SYSV) || defined(linux) + if (getuid() != 0) { + if (pipe(xcpipe)) + FatalError("Pipe failed (%s)\n", strerror(errno)); + switch (fork()) { + case -1: + FatalError("Fork failed (%s)\n", strerror(errno)); + break; + case 0: /* child */ + close(xcpipe[0]); + setuid(getuid()); + HANDLE_RETURN(findConfigFile(configPath, &configFile)); + { + unsigned char pbuf[CONFIG_BUF_LEN]; + int nbytes; + + /* Pass the filename back as the first line */ + strcat(configPath, "\n"); + if (write(xcpipe[1], configPath, strlen(configPath)) < 0) + FatalError("Child error writing to pipe (%s)\n", strerror(errno)); + while ((nbytes = fread(pbuf, 1, CONFIG_BUF_LEN, configFile)) > 0) + if (write(xcpipe[1], pbuf, nbytes) < 0) + FatalError("Child error writing to pipe (%s)\n", strerror(errno)); + } + close(xcpipe[1]); + fclose(configFile); + exit(0); + break; + default: /* parent */ + close(xcpipe[1]); + configFile = (FILE *)fdopen(xcpipe[0], "r"); + if (fgets(configPath, PATH_MAX, configFile) == NULL) + FatalError("Error reading config file\n"); + configPath[strlen(configPath) - 1] = '\0'; + } + } + else { + HANDLE_RETURN(findConfigFile(configPath, &configFile)); + } +#else /* ! (SYSV || linux) */ + { +#ifndef __EMX__ /* in OS/2 we don't care about uids */ + int real_uid = getuid(); + + if (real_uid) { +#ifdef MINIX + setuid(getuid()); +#else +#if !defined(SVR4) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__FreeBSD__) + setruid(0); +#endif + seteuid(real_uid); +#endif /* MINIX */ + } +#endif /* __EMX__ */ + + HANDLE_RETURN(findConfigFile(configPath, &configFile)); +#if defined(MINIX) || defined(__EMX__) + /* no need to restore the uid to root */ +#else + if (real_uid) { + seteuid(0); +#if !defined(SVR4) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__FreeBSD__) + setruid(real_uid); +#endif + } +#endif /* MINIX */ + } +#endif /* SYSV || linux */ + xf86Info.sharedMonitor = FALSE; + xf86Info.kbdProc = NULL; + xf86Info.notrapSignals = FALSE; + xf86Info.caughtSignal = FALSE; + + /* Allocate mouse device */ +#if defined(XINPUT) && !defined(XF86SETUP) + local = mouse_assoc.device_allocate(); + xf86Info.mouseLocal = (pointer) local; + xf86Info.mouseDev = (MouseDevPtr) local->private; + xf86Info.mouseDev->mseProc = NULL; +#else + xf86Info.mouseDev = (MouseDevPtr) Xcalloc(sizeof(MouseDevRec)); +#endif + + while ((token = xf86GetToken(TopLevelTab)) != EOF) { + switch(token) { + case SECTION: + if (xf86GetToken(NULL) != STRING) + xf86ConfigError("section name string expected"); + if ( StrCaseCmp(val.str, "files") == 0 ) { + HANDLE_RETURN(configFilesSection()); + } else if ( StrCaseCmp(val.str, "serverflags") == 0 ) { + HANDLE_RETURN(configServerFlagsSection()); + } else if ( StrCaseCmp(val.str, "keyboard") == 0 ) { + HANDLE_RETURN(configKeyboardSection()); + } else if ( StrCaseCmp(val.str, "pointer") == 0 ) { + HANDLE_RETURN(configPointerSection(xf86Info.mouseDev, ENDSECTION, NULL)); + } else if ( StrCaseCmp(val.str, "device") == 0 ) { + HANDLE_RETURN(configDeviceSection()); + } else if ( StrCaseCmp(val.str, "monitor") == 0 ) { + HANDLE_RETURN(configMonitorSection()); + } else if ( StrCaseCmp(val.str, "screen") == 0 ) { + HANDLE_RETURN(configScreenSection()); +#ifdef XINPUT + } else if ( StrCaseCmp(val.str, "xinput") == 0 ) { + HANDLE_RETURN(xf86ConfigExtendedInputSection(&val)); +#endif + } else if ( StrCaseCmp(val.str, "module") == 0 ) { + HANDLE_RETURN(configDynamicModuleSection()); + } else { + xf86ConfigError("not a recognized section name"); + } + break; + } + } + + fclose(configFile); + xfree(configBuf); + xfree(configRBuf); + xfree(configPath); + + /* These aren't needed after the XF86Config file has been read */ +#ifndef XF86SETUP + if (monitor_list) + xfree(monitor_list); + if (device_list) + xfree(device_list); +#endif + if (modulePath) + xfree(modulePath); + +#if defined(SYSV) || defined(linux) + if (getuid() != 0) { + /* Wait for the child */ + wait(NULL); + } +#endif + + /* Try XF86Config FontPath first */ + if (!xf86fpFlag) + if (fontPath) { + char *f = xf86ValidateFontPath(fontPath); + if (*f) + defaultFontPath = f; + else + ErrorF( + "Warning: FontPath is completely invalid. Using compiled-in default.\n" + ); + xfree(fontPath); + fontPath = (char *)NULL; + } + else + ErrorF("Warning: No FontPath specified, using compiled-in default.\n"); + else /* Use fontpath specified with '-fp' */ + { + OFLG_CLR (XCONFIG_FONTPATH, &GenericXF86ConfigFlag); + if (fontPath) + { + xfree(fontPath); + fontPath = (char *)NULL; + } + } + if (!fontPath) { + /* xf86ValidateFontPath will write into it's arg, but defaultFontPath + could be static, so we make a copy. */ + char *f = (char *)xalloc(strlen(defaultFontPath) + 1); + f[0] = '\0'; + strcpy (f, defaultFontPath); + defaultFontPath = xf86ValidateFontPath(f); + xfree(f); + } + else + xfree(fontPath); + + /* If defaultFontPath is still empty, exit here */ + + if (! *defaultFontPath) + FatalError("No valid FontPath could be found\n"); + if (xf86Verbose) + ErrorF("%s FontPath set to \"%s\"\n", + OFLG_ISSET(XCONFIG_FONTPATH, &GenericXF86ConfigFlag) ? XCONFIG_GIVEN : + XCONFIG_PROBED, defaultFontPath); + + if (!xf86Info.kbdProc) + FatalError("You must specify a keyboard in XF86Config"); + if (!xf86Info.mouseDev->mseProc) + FatalError("You must specify a mouse in XF86Config"); + + if (!graphFound) + { + Bool needcomma = FALSE; + + ErrorF("\nYou must provide a \"Screen\" section in XF86Config for at\n"); + ErrorF("least one of the following graphics drivers: "); + for (i = 0; i < xf86MaxScreens; i++) + { + if (xf86Screens[i]) + { + ErrorF("%s%s", needcomma ? ", " : "", + xf86TokenToString(DriverTab, xf86ScreenNames[i])); + needcomma = TRUE; + } + } + ErrorF("\n"); + FatalError("No configured graphics devices"); + } + } +#ifndef XF86SETUP + else /* if (vtopen) */ + { + /* + * Probe all configured screens for letting them resolve their modes + */ + xf86ScreensOpen = TRUE; + for ( i=0; i < xf86MaxScreens; i++ ) + if (xf86Screens[i] && xf86Screens[i]->configured && + (xf86Screens[i]->configured = (xf86Screens[i]->Probe)())){ + /* if driver doesn't report error do it here */ + if(xf86DCGetToken(xf86Screens[i]->DCConfig,NULL,DeviceTab) != EOF){ + xf86DCConfigError("Unknown device section keyword"); + FatalError("\n"); + } + if(xf86Screens[i]->DCOptions){ + xf86DCGetOption(xf86Screens[i]->DCOptions,NULL); + FatalError("\n"); + } + xf86InitViewport(xf86Screens[i]); + } + + /* + * Now sort the drivers to match the order of the ScreenNumbers + * requested by the user. (sorry, slow bubble-sort here) + * Note, that after this sorting the first driver that is not configured + * can be used as last-mark for all configured ones. + */ + for ( j = 0; j < xf86MaxScreens-1; j++) + for ( i=0; i < xf86MaxScreens-j-1; i++ ) + if (!xf86Screens[i] || !xf86Screens[i]->configured || + (xf86Screens[i+1] && xf86Screens[i+1]->configured && + (xf86Screens[i+1]->tmpIndex < xf86Screens[i]->tmpIndex))) + { + ScrnInfoPtr temp = xf86Screens[i+1]; + xf86Screens[i+1] = xf86Screens[i]; + xf86Screens[i] = temp; + } + + } +#endif /* XF86SETUP */ + +#ifdef NEED_RETURN_VALUE + return RET_OKAY; +#endif +} + +static char* prependRoot(char *pathname) +{ +#ifndef __EMX__ + return pathname; +#else + /* XXXX caveat: multiple path components in line */ + return (char*)__XOS2RedirRoot(pathname); +#endif +} + +static CONFIG_RETURN_TYPE +configFilesSection() +{ + int token; + int i, j; + int k, l; + char *str; + + while ((token = xf86GetToken(FilesTab)) != ENDSECTION) { + switch (token) { + case FONTPATH: + OFLG_SET(XCONFIG_FONTPATH,&GenericXF86ConfigFlag); + if (xf86GetToken(NULL) != STRING) + xf86ConfigError("Font path component expected"); + j = FALSE; + str = prependRoot(val.str); + if (fontPath == NULL) + { + fontPath = (char *)xalloc(1); + fontPath[0] = '\0'; + i = strlen(str) + 1; + } + else + { + i = strlen(fontPath) + strlen(str) + 1; + if (fontPath[strlen(fontPath)-1] != ',') + { + i++; + j = TRUE; + } + } + fontPath = (char *)xrealloc(fontPath, i); + if (j) + strcat(fontPath, ","); + + strcat(fontPath, str); + xfree(val.str); + break; + + case RGBPATH: + OFLG_SET(XCONFIG_RGBPATH, &GenericXF86ConfigFlag); + if (xf86GetToken(NULL) != STRING) xf86ConfigError("RGB path expected"); + if (!xf86coFlag) + rgbPath = val.str; + break; + + case MODULEPATH: + OFLG_SET(XCONFIG_MODULEPATH, &GenericXF86ConfigFlag); + if (xf86GetToken(NULL) != STRING) + xf86ConfigError("Module path expected"); + l = FALSE; + str = prependRoot(val.str); + if (modulePath == NULL) { + modulePath = (char *)xalloc(1); + modulePath[0] = '\0'; + k = strlen(str) + 1; + } + else + { + k = strlen(modulePath) + strlen(str) + 1; + if (modulePath[strlen(modulePath)-1] != ',') + { + k++; + l = TRUE; + } + } + modulePath = (char *)xrealloc(modulePath, k); + if (l) + strcat(modulePath, ","); + + strcat(modulePath, str); + xfree(val.str); + break; + + case EOF: + FatalError("Unexpected EOF (missing EndSection?)"); + break; /* :-) */ + default: + xf86ConfigError("File section keyword expected"); + break; + } + } +#ifdef NEED_RETURN_VALUE + return RET_OKAY; +#endif +} + +static CONFIG_RETURN_TYPE +configServerFlagsSection() +{ + int token; + + xf86Info.dontZap = FALSE; + xf86Info.dontZoom = FALSE; + + while ((token = xf86GetToken(ServerFlagsTab)) != ENDSECTION) { + switch (token) { + case NOTRAPSIGNALS: + xf86Info.notrapSignals=TRUE; + break; + case DONTZAP: + xf86Info.dontZap = TRUE; + break; + case DONTZOOM: + xf86Info.dontZoom = TRUE; + break; +#ifdef XF86VIDMODE + case DISABLEVIDMODE: + xf86VidModeEnabled = FALSE; + break; + case ALLOWNONLOCAL: + xf86VidModeAllowNonLocal = TRUE; + break; +#endif +#ifdef XF86MISC + case DISABLEMODINDEV: + xf86MiscModInDevEnabled = FALSE; + break; + case MODINDEVALLOWNONLOCAL: + xf86MiscModInDevAllowNonLocal = TRUE; + break; +#endif + case ALLOWMOUSEOPENFAIL: + xf86AllowMouseOpenFail = TRUE; + break; + case PCIPROBE1: + xf86PCIFlags = PCIProbe1; + break; + case PCIPROBE2: + xf86PCIFlags = PCIProbe2; + break; + case PCIFORCECONFIG1: + xf86PCIFlags = PCIForceConfig1; + break; + case PCIFORCECONFIG2: + xf86PCIFlags = PCIForceConfig2; + break; + case EOF: + FatalError("Unexpected EOF (missing EndSection?)"); + break; /* :-) */ + default: + xf86ConfigError("Server flags section keyword expected"); + break; + } + } +#ifdef NEED_RETURN_VALUE + return RET_OKAY; +#endif +} + +static CONFIG_RETURN_TYPE +configKeyboardSection() +{ + int token, ntoken; + + /* Initialize defaults */ + xf86Info.serverNumLock = FALSE; + xf86Info.xleds = 0L; + xf86Info.kbdDelay = 500; + xf86Info.kbdRate = 30; + xf86Info.kbdProc = (DeviceProc)0; + xf86Info.vtinit = NULL; + xf86Info.vtSysreq = VT_SYSREQ_DEFAULT; + xf86Info.specialKeyMap = (int *)xalloc((RIGHTCTL - LEFTALT + 1) * + sizeof(int)); + xf86Info.specialKeyMap[LEFTALT - LEFTALT] = KM_META; + xf86Info.specialKeyMap[RIGHTALT - LEFTALT] = KM_META; + xf86Info.specialKeyMap[SCROLLLOCK - LEFTALT] = KM_COMPOSE; + xf86Info.specialKeyMap[RIGHTCTL - LEFTALT] = KM_CONTROL; +#if defined(SVR4) && defined(i386) && !defined(PC98) + xf86Info.panix106 = FALSE; +#endif +#ifdef XKB + xf86Info.xkbkeymap = NULL; + xf86Info.xkbtypes = "default"; +#ifndef PC98 + xf86Info.xkbcompat = "default"; + xf86Info.xkbkeycodes = "xfree86"; + xf86Info.xkbsymbols = "us(pc101)"; + xf86Info.xkbgeometry = "pc"; +#else + xf86Info.xkbcompat = "pc98"; + xf86Info.xkbkeycodes = "xfree98"; + xf86Info.xkbsymbols = "nec/jp(pc98)"; + xf86Info.xkbgeometry = "nec(pc98)"; +#endif + xf86Info.xkbcomponents_specified = False; + xf86Info.xkbrules = "xfree86"; + xf86Info.xkbmodel = NULL; + xf86Info.xkblayout = NULL; + xf86Info.xkbvariant = NULL; + xf86Info.xkboptions = NULL; +#endif + + while ((token = xf86GetToken(KeyboardTab)) != ENDSECTION) { + switch (token) { + case KPROTOCOL: + if (xf86GetToken(NULL) != STRING) + xf86ConfigError("Keyboard protocol name expected"); + if ( StrCaseCmp(val.str,"standard") == 0 ) { + xf86Info.kbdProc = xf86KbdProc; +#ifdef AMOEBA + xf86Info.kbdEvents = NULL; +#else + xf86Info.kbdEvents = xf86KbdEvents; +#endif + } else if ( StrCaseCmp(val.str,"xqueue") == 0 ) { +#ifdef XQUEUE + xf86Info.kbdProc = xf86XqueKbdProc; + xf86Info.kbdEvents = xf86XqueEvents; + xf86Info.mouseDev->xqueSema = 0; + if (xf86Verbose) + ErrorF("%s Xqueue selected for keyboard input\n", + XCONFIG_GIVEN); +#endif + } else { + xf86ConfigError("Not a valid keyboard protocol name"); + } + break; + case AUTOREPEAT: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Autorepeat delay expected"); + xf86Info.kbdDelay = val.num; + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Autorepeat rate expected"); + xf86Info.kbdRate = val.num; + break; + case SERVERNUM: + xf86Info.serverNumLock = TRUE; + break; + + case XLEDS: + while ((token= xf86GetToken(NULL)) == NUMBER) + xf86Info.xleds |= 1L << (val.num-1); + pushToken = token; + break; + case LEFTALT: + case RIGHTALT: + case SCROLLLOCK: + case RIGHTCTL: + ntoken = xf86GetToken(KeyMapTab); + if ((ntoken == EOF) || (ntoken == STRING) || (ntoken == NUMBER)) + xf86ConfigError("KeyMap type token expected"); + else { + switch(ntoken) { + case KM_META: + case KM_COMPOSE: + case KM_MODESHIFT: + case KM_MODELOCK: + case KM_SCROLLLOCK: + case KM_CONTROL: + xf86Info.specialKeyMap[token - LEFTALT] = ntoken; + break; + default: + xf86ConfigError("Illegal KeyMap type"); + break; + } + } + break; + case VTINIT: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("VTInit string expected"); + xf86Info.vtinit = val.str; + if (xf86Verbose) + ErrorF("%s VTInit: \"%s\"\n", XCONFIG_GIVEN, val.str); + break; + + case VTSYSREQ: +#ifdef USE_VT_SYSREQ + xf86Info.vtSysreq = TRUE; + if (xf86Verbose && !VT_SYSREQ_DEFAULT) + ErrorF("%s VTSysReq enabled\n", XCONFIG_GIVEN); +#else + xf86ConfigError("VTSysReq not supported on this OS"); +#endif + break; + +#ifdef XKB + case XKBDISABLE: + noXkbExtension = TRUE; + if (xf86Verbose) + ErrorF("%s XKB: disabled\n", XCONFIG_GIVEN); + break; + + case XKBKEYMAP: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("XKBKeymap string expected"); + xf86Info.xkbkeymap = val.str; + if (xf86Verbose && !XkbInitialMap) + ErrorF("%s XKB: keymap: \"%s\" (overrides other XKB settings)\n", + XCONFIG_GIVEN, val.str); + break; + + case XKBCOMPAT: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("XKBCompat string expected"); + xf86Info.xkbcompat = val.str; + xf86Info.xkbcomponents_specified = True; + if (xf86Verbose && !XkbInitialMap) + ErrorF("%s XKB: compat: \"%s\"\n", XCONFIG_GIVEN, val.str); + break; + + case XKBTYPES: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("XKBTypes string expected"); + xf86Info.xkbtypes = val.str; + xf86Info.xkbcomponents_specified = True; + if (xf86Verbose && !XkbInitialMap) + ErrorF("%s XKB: types: \"%s\"\n", XCONFIG_GIVEN, val.str); + break; + + case XKBKEYCODES: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("XKBKeycodes string expected"); + xf86Info.xkbkeycodes = val.str; + xf86Info.xkbcomponents_specified = True; + if (xf86Verbose && !XkbInitialMap) + ErrorF("%s XKB: keycodes: \"%s\"\n", XCONFIG_GIVEN, val.str); + break; + + case XKBGEOMETRY: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("XKBGeometry string expected"); + xf86Info.xkbgeometry = val.str; + xf86Info.xkbcomponents_specified = True; + if (xf86Verbose && !XkbInitialMap) + ErrorF("%s XKB: geometry: \"%s\"\n", XCONFIG_GIVEN, val.str); + break; + + case XKBSYMBOLS: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("XKBSymbols string expected"); + xf86Info.xkbsymbols = val.str; + xf86Info.xkbcomponents_specified = True; + if (xf86Verbose && !XkbInitialMap) + ErrorF("%s XKB: symbols: \"%s\"\n", XCONFIG_GIVEN, val.str); + break; + + case XKBRULES: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("XKBRules string expected"); + xf86Info.xkbrules = val.str; + if (xf86Verbose && !XkbInitialMap) + ErrorF("%s XKB: rules: \"%s\"\n", XCONFIG_GIVEN, val.str); + break; + + case XKBMODEL: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("XKBModel string expected"); + xf86Info.xkbmodel = val.str; + if (xf86Verbose && !XkbInitialMap) + ErrorF("%s XKB: model: \"%s\"\n", XCONFIG_GIVEN, val.str); + break; + + case XKBLAYOUT: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("XKBLayout string expected"); + xf86Info.xkblayout = val.str; + if (xf86Verbose && !XkbInitialMap) + ErrorF("%s XKB: layout: \"%s\"\n", XCONFIG_GIVEN, val.str); + break; + + case XKBVARIANT: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("XKBVariant string expected"); + xf86Info.xkbvariant = val.str; + if (xf86Verbose && !XkbInitialMap) + ErrorF("%s XKB: variant: \"%s\"\n", XCONFIG_GIVEN, val.str); + break; + + case XKBOPTIONS: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("XKBOptions string expected"); + xf86Info.xkboptions = val.str; + if (xf86Verbose && !XkbInitialMap) + ErrorF("%s XKB: options: \"%s\"\n", XCONFIG_GIVEN, val.str); + break; +#endif +#if defined(SVR4) && defined(i386) && !defined(PC98) + case PANIX106: + xf86Info.panix106 = TRUE; + if (xf86Verbose) + ErrorF("%s PANIX106: enabled\n", XCONFIG_GIVEN); + break; +#endif + + case EOF: + FatalError("Unexpected EOF (missing EndSection?)"); + break; /* :-) */ + + default: + xf86ConfigError("Keyboard section keyword expected"); + break; + } + } + if (xf86Info.kbdProc == (DeviceProc)0) + { + xf86ConfigError("No keyboard device given"); + } +#ifdef NEED_RETURN_VALUE + return RET_OKAY; +#endif +} + +CONFIG_RETURN_TYPE +configPointerSection(MouseDevPtr mouse_dev, + int end_tag, + char **devicename) /* used by extended device */ +{ + int token; + int mtoken; + int i; + char *mouseType = "unknown"; + + /* Set defaults */ + mouse_dev->baudRate = 1200; + mouse_dev->oldBaudRate = -1; + mouse_dev->sampleRate = 0; + mouse_dev->resolution = 0; + mouse_dev->buttons = MSE_DFLTBUTTONS; + mouse_dev->emulate3Buttons = FALSE; + mouse_dev->emulate3Timeout = 50; + mouse_dev->chordMiddle = FALSE; + mouse_dev->mouseFlags = 0; + mouse_dev->mseProc = (DeviceProc)0; + mouse_dev->mseDevice = NULL; + mouse_dev->mseType = -1; + mouse_dev->mseModel = 0; + mouse_dev->negativeZ = 0; + mouse_dev->positiveZ = 0; + + while ((token = xf86GetToken(PointerTab)) != end_tag) { + switch (token) { + + case PROTOCOL: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("Mouse name expected"); +#if defined(USE_OSMOUSE) || defined(OSMOUSE_ONLY) + if ( StrCaseCmp(val.str,"osmouse") == 0 ) { + if (xf86Verbose) + ErrorF("%s OsMouse selected for mouse input\n", XCONFIG_GIVEN); + /* + * allow an option to be passed to the OsMouse routines + */ + if ((i = xf86GetToken(NULL)) != ERROR_TOKEN) + xf86OsMouseOption(i, (pointer) &val); + else + pushToken = i; + mouse_dev->mseProc = xf86OsMouseProc; + mouse_dev->mseEvents = (void(*)(MouseDevPtr))xf86OsMouseEvents; + break; + } +#endif +#ifdef XQUEUE + if ( StrCaseCmp(val.str,"xqueue") == 0 ) { + mouse_dev->mseProc = xf86XqueMseProc; + mouse_dev->mseEvents = (void(*)(MouseDevPtr))xf86XqueEvents; + mouse_dev->xqueSema = 0; + if (xf86Verbose) + ErrorF("%s Xqueue selected for mouse input\n", + XCONFIG_GIVEN); + break; + } +#endif + +#ifndef OSMOUSE_ONLY +#if defined(MACH) || defined(AMOEBA) + mouseType = (char *) xalloc (strlen (val.str) + 1); + strcpy (mouseType, val.str); +#else + mouseType = (char *)strdup(val.str); /* GJA -- should we free this? */ +#endif + mtoken = getStringToken(MouseTab); /* Which mouse? */ +#ifdef AMOEBA + mouse_dev->mseProc = xf86MseProc; + mouse_dev->mseEvents = NULL; +#else + mouse_dev->mseProc = xf86MseProc; + mouse_dev->mseEvents = xf86MseEvents; +#endif + mouse_dev->mseType = mtoken - MICROSOFT; + if (!xf86MouseSupported(mouse_dev->mseType)) + { + xf86ConfigError("Mouse type not supported by this OS"); + } +#else /* OSMOUSE_ONLY */ + xf86ConfigError("Mouse type not supported by this OS"); +#endif /* OSMOUSE_ONLY */ + +#ifdef MACH386 + /* Don't need to specify the device for MACH -- should always be this */ + mouse_dev->mseDevice = "/dev/mouse"; +#endif + break; +#ifndef OSMOUSE_ONLY + case PDEVICE: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("Mouse device expected"); + mouse_dev->mseDevice = val.str; + break; + case BAUDRATE: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Baudrate expected"); + if (mouse_dev->mseType + MICROSOFT == LOGIMAN) + { + /* + * XXXX This should be extended to other mouse types -- most + * support only 1200. Should also disallow baudrate for bus mice + */ + /* Moan if illegal baud rate! [CHRIS-211092] */ + if ((val.num != 1200) && (val.num != 9600)) + xf86ConfigError("Only 1200 or 9600 Baud are supported by MouseMan"); + } + else if (val.num%1200 != 0 || val.num < 1200 || val.num > 9600) + xf86ConfigError("Baud rate must be one of 1200, 2400, 4800, or 9600"); + mouse_dev->baudRate = val.num; + break; + + case SAMPLERATE: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Sample rate expected"); +#if 0 + if (mouse_dev->mseType + MICROSOFT == LOGIMAN) + { + /* XXXX Most mice don't allow this */ + /* Moan about illegal sample rate! [CHRIS-211092] */ + xf86ConfigError("Selection of sample rate is not supported by MouseMan"); + } +#endif + mouse_dev->sampleRate = val.num; + break; + + case PRESOLUTION: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Resolution expected"); + if (val.num <= 0) + xf86ConfigError("Resolution must be a positive value"); + mouse_dev->resolution = val.num; + break; +#endif /* OSMOUSE_ONLY */ + case EMULATE3: + if (mouse_dev->chordMiddle) + xf86ConfigError("Can't use Emulate3Buttons with ChordMiddle"); + mouse_dev->emulate3Buttons = TRUE; + break; + + case EM3TIMEOUT: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("3 button emulation timeout expected"); + mouse_dev->emulate3Timeout = val.num; + break; + +#ifndef OSMOUSE_ONLY + case CHORDMIDDLE: + if (mouse_dev->mseType + MICROSOFT == MICROSOFT || + mouse_dev->mseType + MICROSOFT == LOGIMAN) + { + if (mouse_dev->emulate3Buttons) + xf86ConfigError("Can't use ChordMiddle with Emulate3Buttons"); + mouse_dev->chordMiddle = TRUE; + } + else + xf86ConfigError("ChordMiddle is only supported for Microsoft and MouseMan"); + break; + + case CLEARDTR: +#ifdef CLEARDTR_SUPPORT + if (mouse_dev->mseType + MICROSOFT == MOUSESYS) + mouse_dev->mouseFlags |= MF_CLEAR_DTR; + else + xf86ConfigError("ClearDTR only supported for MouseSystems mouse"); +#else + xf86ConfigError("ClearDTR not supported on this OS"); +#endif + break; + case CLEARRTS: +#ifdef CLEARDTR_SUPPORT + if (mouse_dev->mseType + MICROSOFT == MOUSESYS) + mouse_dev->mouseFlags |= MF_CLEAR_RTS; + else + xf86ConfigError("ClearRTS only supported for MouseSystems mouse"); +#else + xf86ConfigError("ClearRTS not supported on this OS"); +#endif + break; +#endif /* OSMOUSE_ONLY */ + + case DEVICE_NAME: + if (!devicename) /* not called for an extended device */ + xf86ConfigError("Pointer section keyword expected"); + + if (xf86GetToken(NULL) != STRING) + xf86ConfigError("Option string expected"); + *devicename = strdup(val.str); + break; + +#ifndef XF86SETUP +#ifdef XINPUT + case ALWAYSCORE: + xf86AlwaysCore(mouse_dev->local, TRUE); + break; +#endif +#endif + + case ZAXISMAPPING: + switch (xf86GetToken(ZMapTab)) { + case NUMBER: + if (val.num <= 0 || val.num > MSE_MAXBUTTONS) + xf86ConfigError("Button number (1..12) expected"); + mouse_dev->negativeZ = 1 << (val.num - 1); + if (xf86GetToken(NULL) != NUMBER || + val.num <= 0 || val.num > MSE_MAXBUTTONS) + xf86ConfigError("Button number (1..12) expected"); + mouse_dev->positiveZ = 1 << (val.num - 1); + break; + case XAXIS: + mouse_dev->negativeZ = mouse_dev->positiveZ = MSE_MAPTOX; + break; + case YAXIS: + mouse_dev->negativeZ = mouse_dev->positiveZ = MSE_MAPTOY; + break; + default: + xf86ConfigError("Button number (1..12), X or Y expected"); + } + break; + + case PBUTTONS: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Number of buttons (1..12) expected"); + if (val.num <= 0 || val.num > MSE_MAXBUTTONS) + xf86ConfigError("Number of buttons must be a positive value (1..12)"); + mouse_dev->buttons = val.num; + break; + + case EOF: + FatalError("Unexpected EOF (missing EndSection?)"); + break; /* :-) */ + + default: + xf86ConfigError("Pointer section keyword expected"); + break; + } + + } + /* Print log and make sanity checks */ + + if (mouse_dev->mseProc == (DeviceProc)0) + { + xf86ConfigError("No mouse protocol given"); + } + + /* + * if mseProc is set and mseType isn't, then using Xqueue or OSmouse. + * Otherwise, a mouse device is required. + */ + if (mouse_dev->mseType >= 0 && !mouse_dev->mseDevice) + { + xf86ConfigError("No mouse device given"); + } + + switch (mouse_dev->negativeZ) { + case 0: /* none */ + case MSE_MAPTOX: + case MSE_MAPTOY: + break; + default: /* buttons */ + for (i = 0; mouse_dev->negativeZ != (1 << i); ++i) + ; + if (i + 1 > mouse_dev->buttons) + mouse_dev->buttons = i + 1; + for (i = 0; mouse_dev->positiveZ != (1 << i); ++i) + ; + if (i + 1 > mouse_dev->buttons) + mouse_dev->buttons = i + 1; + break; + } + + if (xf86Verbose && mouse_dev->mseType >= 0) + { + Bool formatFlag = FALSE; + ErrorF("%s Mouse: type: %s, device: %s", + XCONFIG_GIVEN, mouseType, mouse_dev->mseDevice); + if (mouse_dev->mseType != P_BM + && mouse_dev->mseType != P_PS2 + && mouse_dev->mseType != P_IMPS2 + && mouse_dev->mseType != P_THINKINGPS2 + && mouse_dev->mseType != P_MMANPLUSPS2 + && mouse_dev->mseType != P_GLIDEPOINTPS2 + && mouse_dev->mseType != P_NETPS2 + && mouse_dev->mseType != P_NETSCROLLPS2 + && mouse_dev->mseType != P_SYSMOUSE) + { + formatFlag = TRUE; + ErrorF(", baudrate: %d", mouse_dev->baudRate); + } + if (mouse_dev->sampleRate) + { + ErrorF(formatFlag ? "\n%s Mouse: samplerate: %d" : "%ssamplerate: %d", + formatFlag ? XCONFIG_GIVEN : ", ", mouse_dev->sampleRate); + formatFlag = !formatFlag; + } + if (mouse_dev->resolution) + { + ErrorF(formatFlag ? "\n%s Mouse: resolution: %d" : "%sresolution: %d", + formatFlag ? XCONFIG_GIVEN : ", ", mouse_dev->resolution); + formatFlag = !formatFlag; + } + ErrorF(formatFlag ? "\n%s Mouse: buttons: %d" : "%sbuttons: %d", + formatFlag ? XCONFIG_GIVEN : ", ", mouse_dev->buttons); + formatFlag = !formatFlag; + if (mouse_dev->emulate3Buttons) + { + ErrorF(formatFlag ? "\n%s Mouse: 3 button emulation (timeout: %dms)" : + "%s3 button emulation (timeout: %dms)", + formatFlag ? XCONFIG_GIVEN : ", ", mouse_dev->emulate3Timeout); + formatFlag = !formatFlag; + } + if (mouse_dev->chordMiddle) + ErrorF(formatFlag ? "\n%s Mouse: Chorded middle button" : + "%sChorded middle button", + formatFlag ? XCONFIG_GIVEN : ", "); + ErrorF("\n"); + + switch (mouse_dev->negativeZ) { + case 0: /* none */ + break; + case MSE_MAPTOX: + ErrorF("%s Mouse: zaxismapping: X\n", XCONFIG_GIVEN); + break; + case MSE_MAPTOY: + ErrorF("%s Mouse: zaxismapping: Y\n", XCONFIG_GIVEN); + break; + default: /* buttons */ + for (i = 0; mouse_dev->negativeZ != (1 << i); ++i) + ; + ErrorF("%s Mouse: zaxismapping: (-)%d", XCONFIG_GIVEN, i + 1); + for (i = 0; mouse_dev->positiveZ != (1 << i); ++i) + ; + ErrorF(" (+)%d\n", i + 1); + break; + } + } +#ifdef NEED_RETURN_VALUE + return RET_OKAY; +#endif +} + +static CONFIG_RETURN_TYPE +configDeviceSection() +{ + int token; + int i; + GDevPtr devp; + + /* Allocate one more device */ + if ( device_list == NULL ) { + device_list = (GDevPtr) xalloc(sizeof(GDevRec)); + } else { + device_list = (GDevPtr) xrealloc(device_list, + (n_devices+1) * sizeof(GDevRec)); + } + devp = &(device_list[n_devices]); /* Point to the last device */ + n_devices++; + + /* Pre-init the newly created device */ + devp->identifier = NULL; + devp->board = NULL; + devp->vendor = NULL; + devp->chipset = NULL; + devp->ramdac = NULL; + for (i=0; i<MAXDACSPEEDS; i++) + devp->dacSpeeds[i] = 0; + OFLG_ZERO(&(devp->options)); + OFLG_ZERO(&(devp->xconfigFlag)); + devp->videoRam = 0; + devp->speedup = SPEEDUP_DEFAULT; + OFLG_ZERO(&(devp->clockOptions)); + devp->clocks = 0; + devp->clockprog = NULL; + devp->textClockValue = -1; + /* GJA -- We initialize the following fields to known values. + * If later on we find they contain different values, + * they might be interesting to print. + */ + devp->IObase = 0; + devp->DACbase = 0; + devp->COPbase = 0; + devp->POSbase = 0; + devp->instance = 0; + devp->BIOSbase = 0; + devp->VGAbase = 0; + devp->MemBase = 0; + devp->s3Madjust = 0; + devp->s3Nadjust = 0; + devp->s3MClk = 0; + devp->chipID = 0; + devp->chipRev = 0; + devp->s3RefClk = 0; + devp->s3BlankDelay = -1; + devp->DCConfig = NULL; + devp->DCOptions = NULL; + devp->MemClk = 0; + devp->LCDClk = 0; + + while ((token = xf86GetToken(DeviceTab)) != ENDSECTION) { + devp->DCConfig = xf86DCSaveLine(devp->DCConfig, token); + switch (token) { + + case IDENTIFIER: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("identifier name expected"); + devp->identifier = val.str; + break; + + case VENDOR: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("vendor name expected"); + devp->vendor = val.str; + break; + + case BOARD: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("board name expected"); + devp->board = val.str; + break; + + case CHIPSET: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("Chipset string expected"); + devp->chipset = val.str; + OFLG_SET(XCONFIG_CHIPSET,&(devp->xconfigFlag)); + break; + + case RAMDAC: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("RAMDAC string expected"); + devp->ramdac = val.str; + OFLG_SET(XCONFIG_RAMDAC,&(devp->xconfigFlag)); + break; + + case DACSPEED: + for (i=0; i<MAXDACSPEEDS; i++) + devp->dacSpeeds[i] = 0; + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("DAC speed(s) expected"); + else { + devp->dacSpeeds[0] = (int)(val.realnum * 1000.0 + 0.5); + for(i=1; i<MAXDACSPEEDS; i++) { + if (xf86GetToken(NULL) == NUMBER) + devp->dacSpeeds[i] = (int)(val.realnum * 1000.0 + 0.5); + else { + pushToken = token; + break; + } + } + } + OFLG_SET(XCONFIG_DACSPEED,&(devp->xconfigFlag)); + break; + + case CLOCKCHIP: + /* Only allow one Clock string */ + if (OFLG_ISSET(CLOCK_OPTION_PROGRAMABLE, &(devp->clockOptions))) + { + xf86ConfigError("Only one Clock chip may be specified."); + break; + } + if (devp->clocks == 0) + { + if (xf86GetToken(NULL) != STRING) xf86ConfigError("Option string expected"); + i = 0; + while (xf86_ClockOptionTab[i].token != -1) + { + if (StrCaseCmp(val.str, xf86_ClockOptionTab[i].name) == 0) + { + OFLG_SET(CLOCK_OPTION_PROGRAMABLE, &(devp->clockOptions)); + OFLG_SET(xf86_ClockOptionTab[i].token, + &(devp->clockOptions)); + break; + } + i++; + } + if (xf86_ClockOptionTab[i].token == -1) { + xf86ConfigError("Unknown clock chip"); + break; + } + } + else + { + xf86ConfigError("Clocks previously specified by value"); + } + break; + + case CLOCKS: + OFLG_SET(XCONFIG_CLOCKS,&(devp->xconfigFlag)); + if ((token = xf86GetToken(NULL)) == STRING) + { + xf86ConfigError("Use ClockChip to specify a programmable clock"); + break; + } + if (OFLG_ISSET(CLOCK_OPTION_PROGRAMABLE, &(devp->clockOptions))) + { + xf86ConfigError("Clock previously specified as programmable"); + break; + } + for (i = devp->clocks; token == NUMBER && i < MAXCLOCKS; i++) { + devp->clock[i] = (int)(val.realnum * 1000.0 + 0.5); + token = xf86GetToken(NULL); + } + + devp->clocks = i; + pushToken = token; + break; + + case OPTION: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("Option string expected"); + i = 0; + while (xf86_OptionTab[i].token != -1) + { + if (StrCaseCmp(val.str, xf86_OptionTab[i].name) == 0) + { + OFLG_SET(xf86_OptionTab[i].token, &(devp->options)); + break; + } + i++; + } + if (xf86_OptionTab[i].token == -1) + /*xf86ConfigError("Unknown option string");*/ + devp->DCOptions = xf86DCOption(devp->DCOptions,val); + break; + + case VIDEORAM: + OFLG_SET(XCONFIG_VIDEORAM,&(devp->xconfigFlag)); + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Video RAM size expected"); + devp->videoRam = val.num; + break; + + case SPEEDUP: + OFLG_SET(XCONFIG_SPEEDUP,&(devp->xconfigFlag)); + if ((token = xf86GetToken(NULL)) == STRING) + if (!strcmp(val.str,"all")) + devp->speedup = SPEEDUP_ALL; + else + if (!strcmp(val.str,"best")) + devp->speedup = SPEEDUP_BEST; + else + if (!strcmp(val.str,"none")) + devp->speedup = 0; + else + xf86ConfigError("Unrecognised SpeedUp option"); + else + { + pushToken = token; + if ((token = xf86GetToken(NULL)) == NUMBER) + devp->speedup = val.num; + else + { + pushToken = token; + devp->speedup = SPEEDUP_ALL; + } + } + break; + + case NOSPEEDUP: + OFLG_SET(XCONFIG_SPEEDUP,&(devp->xconfigFlag)); + devp->speedup = 0; + break; + + case CLOCKPROG: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("ClockProg string expected"); + if (val.str[0] != '/') + FatalError("Full pathname must be given for ClockProg \"%s\"\n", + val.str); + if (access(val.str, X_OK) < 0) + { + if (access(val.str, F_OK) < 0) + FatalError("ClockProg \"%s\" does not exist\n", val.str); + else + FatalError("ClockProg \"%s\" is not executable\n", val.str); + } + { + struct stat stat_buf; + stat(val.str, &stat_buf); + if (!CHECK_TYPE(stat_buf.st_mode, S_IFREG)) + FatalError("ClockProg \"%s\" is not a regular file\n", val.str); + } + devp->clockprog = val.str; + if (xf86GetToken(NULL) == NUMBER) + { + devp->textClockValue = (int)(val.realnum * 1000.0 + 0.5); + } + else + { + pushToken = token; + } + break; + + case BIOSBASE: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("BIOS base address expected"); + devp->BIOSbase = val.num; + OFLG_SET(XCONFIG_BIOSBASE, &(devp->xconfigFlag)); + break; + + case MEMBASE: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Memory base address expected"); + devp->MemBase = val.num; + OFLG_SET(XCONFIG_MEMBASE, &(devp->xconfigFlag)); + break; + + case IOBASE: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Direct access register I/O base address expected"); + devp->IObase = val.num; + OFLG_SET(XCONFIG_IOBASE, &(devp->xconfigFlag)); + break; + + case DACBASE: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("DAC base I/O address expected"); + devp->DACbase = val.num; + OFLG_SET(XCONFIG_DACBASE, &(devp->xconfigFlag)); + break; + + case COPBASE: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Coprocessor base memory address expected"); + devp->COPbase = val.num; + OFLG_SET(XCONFIG_COPBASE, &(devp->xconfigFlag)); + break; + + case POSBASE: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("POS base address expected"); + devp->POSbase = val.num; + OFLG_SET(XCONFIG_POSBASE, &(devp->xconfigFlag)); + break; + + case INSTANCE: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Video adapter instance number expected"); + devp->instance = val.num; + OFLG_SET(XCONFIG_INSTANCE, &(devp->xconfigFlag)); + break; + + case S3MNADJUST: + if ((token = xf86GetToken(NULL)) == DASH) { /* negative number */ + token = xf86GetToken(NULL); + val.num = -val.num; + } + if (token != NUMBER || val.num<-31 || val.num>31) + xf86ConfigError("M adjust (max. 31) expected"); + devp->s3Madjust = val.num; + + if ((token = xf86GetToken(NULL)) == DASH) { /* negative number */ + token = xf86GetToken(NULL); + val.num = -val.num; + } + if (token == NUMBER) { + if (val.num<-255 || val.num>255) + xf86ConfigError("N adjust (max. 255) expected"); + else + devp->s3Nadjust = val.num; + } + else pushToken = token; + break; + + case S3MCLK: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("MCLK value in MHz expected"); + devp->s3MClk = (int)(val.realnum * 1000.0 + 0.5); + break; + + case MEMCLOCK: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Memory Clock value in MHz expected"); + devp->MemClk = (int)(val.realnum * 1000.0 + 0.5); + OFLG_SET(XCONFIG_MEMCLOCK,&(devp->xconfigFlag)); + break; + + case LCDCLOCK: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("LCD Clock value in MHz expected"); + devp->LCDClk = (int)(val.realnum * 1000.0 + 0.5); + OFLG_SET(XCONFIG_LCDCLOCK,&(devp->xconfigFlag)); + break; + + case CHIPID: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("ChipID expected"); + devp->chipID = val.num; + break; + + case CHIPREV: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("ChipRev expected"); + devp->chipRev = val.num; + break; + + case VGABASEADDR: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("VGA aperature base address expected"); + devp->VGAbase = val.num; + OFLG_SET(XCONFIG_VGABASE, &(devp->xconfigFlag)); + break; + + case S3REFCLK: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("RefCLK value in MHz expected"); + devp->s3RefClk = (int)(val.realnum * 1000.0 + 0.5); + break; + + case S3BLANKDELAY: + if (xf86GetToken(NULL) != NUMBER || val.num>7) + xf86ConfigError("number(s) 0..7 expected"); + devp->s3BlankDelay = val.num; + if ((token=xf86GetToken(NULL)) == NUMBER) { + if (val.num>7) xf86ConfigError("number2 0..7 expected"); + devp->s3BlankDelay |= val.num<<4; + } + else pushToken = token; + break; + + case TEXTCLOCKFRQ: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Text clock expected"); + devp->textClockValue = (int)(val.realnum * 1000.0 + 0.5); + break; + + case EOF: + FatalError("Unexpected EOF (missing EndSection?)"); + break; /* :-) */ + default: + if(DCerr) + xf86ConfigError("Device section keyword expected"); + break; + } + } +#ifdef NEED_RETURN_VALUE + return RET_OKAY; +#endif +} + +static CONFIG_RETURN_TYPE +configMonitorSection() +{ + int token; + int i; + MonPtr monp; + float multiplier; + + /* Allocate one more monitor */ + if ( monitor_list == NULL ) { + monitor_list = (MonPtr) xalloc(sizeof(MonRec)); + } else { + monitor_list = (MonPtr) xrealloc(monitor_list, + (n_monitors+1) * sizeof(MonRec)); + } + monp = &(monitor_list[n_monitors]); /* Point to the new monitor */ + monp->Modes = 0; + monp->Last = 0; + monp->n_hsync = 0; + monp->n_vrefresh = 0; + n_monitors++; + + while ((token = xf86GetToken(MonitorTab)) != ENDSECTION) { + switch (token) { + case IDENTIFIER: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("identifier name expected"); + monp->id = val.str; + break; + case VENDOR: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("vendor name expected"); + monp->vendor = val.str; + break; + case MODEL: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("model name expected"); + monp->model = val.str; + break; + case MODE: + readVerboseMode(monp); + break; + case MODELINE: + token = xf86GetToken(NULL); + pNew = (DisplayModePtr)xalloc(sizeof(DisplayModeRec)); + + if (monp->Last) + monp->Last->next = pNew; + else + monp->Modes = pNew; + + if (token == STRING) + { + pNew->name = val.str; + if ((token = xf86GetToken(NULL)) != NUMBER) + FatalError("Dotclock expected"); + } + else if (monp->Last) + { +#if defined(MACH) || defined(AMOEBA) + pNew->name = (char *) xalloc (strlen (monp->Last->name) + 1); + strcpy (pNew->name, monp->Last->name); +#else + pNew->name = (char *)strdup(monp->Last->name); +#endif + } + else + xf86ConfigError("Mode name expected"); + + pNew->next = NULL; + pNew->prev = NULL; + pNew->Flags = 0; + pNew->Clock = (int)(val.realnum * 1000.0 + 0.5); + pNew->CrtcHAdjusted = FALSE; + pNew->CrtcVAdjusted = FALSE; + pNew->CrtcHSkew = pNew->HSkew = 0; + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcHDisplay = pNew->HDisplay = val.num; + else xf86ConfigError("Horizontal display expected"); + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcHSyncStart = pNew->HSyncStart = val.num; + else xf86ConfigError("Horizontal sync start expected"); + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcHSyncEnd = pNew->HSyncEnd = val.num; + else xf86ConfigError("Horizontal sync end expected"); + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcHTotal = pNew->HTotal = val.num; + else xf86ConfigError("Horizontal total expected"); + + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcVDisplay = pNew->VDisplay = val.num; + else xf86ConfigError("Vertical display expected"); + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcVSyncStart = pNew->VSyncStart = val.num; + else xf86ConfigError("Vertical sync start expected"); + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcVSyncEnd = pNew->VSyncEnd = val.num; + else xf86ConfigError("Vertical sync end expected"); + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcVTotal = pNew->VTotal = val.num; + else xf86ConfigError("Vertical total expected"); + + token = xf86GetToken(TimingTab); + while ( (token == TT_INTERLACE) || (token == TT_PHSYNC) || + (token == TT_NHSYNC) || (token == TT_PVSYNC) || + (token == TT_NVSYNC) || (token == TT_CSYNC) || + (token == TT_PCSYNC) || (token == TT_NCSYNC) || + (token == TT_DBLSCAN) || (token == TT_HSKEW) ) + { + switch(token) { + + case TT_INTERLACE: pNew->Flags |= V_INTERLACE; break; + case TT_PHSYNC: pNew->Flags |= V_PHSYNC; break; + case TT_NHSYNC: pNew->Flags |= V_NHSYNC; break; + case TT_PVSYNC: pNew->Flags |= V_PVSYNC; break; + case TT_NVSYNC: pNew->Flags |= V_NVSYNC; break; + case TT_CSYNC: pNew->Flags |= V_CSYNC; break; + case TT_PCSYNC: pNew->Flags |= V_PCSYNC; break; + case TT_NCSYNC: pNew->Flags |= V_NCSYNC; break; + case TT_DBLSCAN: pNew->Flags |= V_DBLSCAN; break; + case TT_HSKEW: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Horizontal skew expected"); + pNew->CrtcHSkew = pNew->HSkew = val.num; + pNew->Flags |= V_HSKEW; + break; + default: + xf86ConfigError("bug found in config reader"); break; + } + token = xf86GetToken(TimingTab); + } + pushToken = token; + monp->Last = pNew; /* GJA */ + break; + case BANDWIDTH: + /* This should be completely removed at some point */ + if ((token = xf86GetToken(NULL)) != NUMBER) + xf86ConfigError("Bandwidth number expected"); +#if 0 + monp->bandwidth = val.realnum; + /* Handle optional scaler */ + token = xf86GetToken(UnitTab); + switch ( token ) { + case HRZ: multiplier = 1.0e-6; break; + case KHZ: multiplier = 1.0e-3; break; + case MHZ: multiplier = 1.0; break; + default: multiplier = 1.0; pushToken = token; + } + monp->bandwidth *= multiplier; +#endif + break; + case HORIZSYNC: + if ((token = xf86GetToken(NULL)) != NUMBER) + xf86ConfigError("Horizontal sync value expected"); + monp->hsync[monp->n_hsync].lo = val.realnum; + if ((token = xf86GetToken(NULL)) == DASH) { + if ((token = xf86GetToken(NULL)) != NUMBER) + xf86ConfigError("Upperbound for horizontal sync value expected"); + monp->hsync[monp->n_hsync].hi = val.realnum; + } else { + pushToken = token; + monp->hsync[monp->n_hsync].hi = monp->hsync[monp->n_hsync].lo; + } + monp->n_hsync++; + while ( (token = xf86GetToken(NULL)) == COMMA ) { + if ( monp->n_hsync == MAX_HSYNC ) + xf86ConfigError("Sorry. Too many horizontal sync intervals."); + + if ((token = xf86GetToken(NULL)) != NUMBER) + xf86ConfigError("Horizontal sync value expected"); + monp->hsync[monp->n_hsync].lo = val.realnum; + if ((token = xf86GetToken(NULL)) == DASH) { + if ((token = xf86GetToken(NULL)) != NUMBER) + xf86ConfigError("Upperbound for horizontal sync value expected"); + monp->hsync[monp->n_hsync].hi = val.realnum; + } else { + pushToken = token; + monp->hsync[monp->n_hsync].hi = monp->hsync[monp->n_hsync].lo; + } + monp->n_hsync++; + } + pushToken = token; + /* Handle optional scaler */ + token = xf86GetToken(UnitTab); + switch ( token ) { + case HRZ: multiplier = 1.0e-3; break; + case KHZ: multiplier = 1.0; break; + case MHZ: multiplier = 1.0e3; break; + default: multiplier = 1.0; pushToken = token; + } + for ( i = 0 ; i < monp->n_hsync ; i++ ) { + monp->hsync[i].hi *= multiplier; + monp->hsync[i].lo *= multiplier; + } + break; + case VERTREFRESH: + if ((token = xf86GetToken(NULL)) != NUMBER) + xf86ConfigError("Vertical refresh value expected"); + monp->vrefresh[monp->n_vrefresh].lo = val.realnum; + if ((token = xf86GetToken(NULL)) == DASH) { + if ((token = xf86GetToken(NULL)) != NUMBER) + xf86ConfigError("Upperbound for vertical refresh value expected"); + monp->vrefresh[monp->n_vrefresh].hi = val.realnum; + } else { + monp->vrefresh[monp->n_vrefresh].hi = + monp->vrefresh[monp->n_vrefresh].lo; + pushToken = token; + } + monp->n_vrefresh++; + while ( (token = xf86GetToken(NULL)) == COMMA ) { + if ( monp->n_vrefresh == MAX_HSYNC ) + xf86ConfigError("Sorry. Too many vertical refresh intervals."); + + if ((token = xf86GetToken(NULL)) != NUMBER) + xf86ConfigError("Vertical refresh value expected"); + monp->vrefresh[monp->n_vrefresh].lo = val.realnum; + if ((token = xf86GetToken(NULL)) == DASH) { + if ((token = xf86GetToken(NULL)) != NUMBER) + xf86ConfigError("Upperbound for vertical refresh value expected"); + monp->vrefresh[monp->n_vrefresh].hi = val.realnum; + } else { + monp->vrefresh[monp->n_vrefresh].hi = + monp->vrefresh[monp->n_vrefresh].lo; + pushToken = token; + } + monp->n_vrefresh++; + } + pushToken = token; + /* Handle optional scaler */ + token = xf86GetToken(UnitTab); + switch ( token ) { + case HRZ: multiplier = 1.0; break; + case KHZ: multiplier = 1.0e3; break; + case MHZ: multiplier = 1.0e6; break; + default: multiplier = 1.0; pushToken = token; + } + for ( i = 0 ; i < monp->n_vrefresh ; i++ ) { + monp->vrefresh[i].hi *= multiplier; + monp->vrefresh[i].lo *= multiplier; + } + break; + case GAMMA: { + char *msg = "gamma correction value(s) expected\n either one value or three r/g/b values with 0.1 <= gamma <= 10"; + if ((token = xf86GetToken(NULL)) != NUMBER || val.realnum<0.1 || val.realnum>10) + xf86ConfigError(msg); + else { + xf86rGamma = xf86gGamma = xf86bGamma = 1.0 / val.realnum; + if ((token = xf86GetToken(NULL)) == NUMBER) { + if (val.realnum<0.1 || val.realnum>10) xf86ConfigError(msg); + else { + xf86gGamma = 1.0 / val.realnum; + if ((token = xf86GetToken(NULL)) != NUMBER || val.realnum<0.1 || val.realnum>10) + xf86ConfigError(msg); + else { + xf86bGamma = 1.0 / val.realnum; + } + } + } + else pushToken = token; + } + break; + } + case EOF: + FatalError("Unexpected EOF. Missing EndSection?"); + break; /* :-) */ + + default: + xf86ConfigError("Monitor section keyword expected"); + break; + } + } +#ifdef NEED_RETURN_VALUE + return RET_OKAY; +#endif +} + +static CONFIG_RETURN_TYPE +configDynamicModuleSection() +{ + int token; + + while ((token = xf86GetToken(ModuleTab)) != ENDSECTION) { + switch (token) { + case LOAD: + if (xf86GetToken(NULL) != STRING) + xf86ConfigError("Dynamic module expected"); + else { +#ifdef DYNAMIC_MODULE + if (!modulePath) { + static Bool firstTime = TRUE; + + modulePath = (char*)Xcalloc(strlen(DEFAULT_MODULE_PATH)+1); + strcpy(modulePath, DEFAULT_MODULE_PATH); + + if (xf86Verbose && firstTime) { + ErrorF("%s no ModulePath specified using default: %s\n", + XCONFIG_PROBED, DEFAULT_MODULE_PATH); + firstTime = FALSE; + } + } + xf86LoadModule(val.str, modulePath); +#else + ErrorF("Dynamic modules not supported. \"%s\" not loaded\n", + val.str); +#endif + } + break; + + case EOF: + FatalError("Unexpected EOF. Missing EndSection?"); + break; /* :-) */ + + default: + xf86ConfigError("Module section keyword expected"); + break; + } + } +#ifdef NEED_RETURN_VALUE + return RET_OKAY; +#endif +} + +static CONFIG_RETURN_TYPE +readVerboseMode(monp) +MonPtr monp; +{ + int token, token2; + int had_dotclock = 0, had_htimings = 0, had_vtimings = 0; + + pNew = (DisplayModePtr)xalloc(sizeof(DisplayModeRec)); + pNew->next = NULL; + pNew->prev = NULL; + pNew->Flags = 0; + pNew->HDisplay = pNew->VDisplay = 0; /* Uninitialized */ + pNew->CrtcHAdjusted = pNew->CrtcVAdjusted = FALSE; + pNew->CrtcHSkew = pNew->HSkew = 0; + + if (monp->Last) + monp->Last->next = pNew; + else + monp->Modes = pNew; + monp->Last = pNew; + + if ( xf86GetToken(NULL) != STRING ) { + FatalError("Mode name expected"); + } + pNew->name = val.str; + while ((token = xf86GetToken(ModeTab)) != ENDMODE) { + switch (token) { + case DOTCLOCK: + if ((token = xf86GetToken(NULL)) != NUMBER) { + FatalError("Dotclock expected"); + } + pNew->Clock = (int)(val.realnum * 1000.0 + 0.5); + had_dotclock = 1; + break; + case HTIMINGS: + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcHDisplay = pNew->HDisplay = val.num; + else xf86ConfigError("Horizontal display expected"); + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcHSyncStart = pNew->HSyncStart = val.num; + else xf86ConfigError("Horizontal sync start expected"); + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcHSyncEnd = pNew->HSyncEnd = val.num; + else xf86ConfigError("Horizontal sync end expected"); + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcHTotal = pNew->HTotal = val.num; + else xf86ConfigError("Horizontal total expected"); + had_htimings = 1; + break; + case VTIMINGS: + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcVDisplay = pNew->VDisplay = val.num; + else xf86ConfigError("Vertical display expected"); + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcVSyncStart = pNew->VSyncStart = val.num; + else xf86ConfigError("Vertical sync start expected"); + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcVSyncEnd = pNew->VSyncEnd = val.num; + else xf86ConfigError("Vertical sync end expected"); + + if (xf86GetToken(NULL) == NUMBER) + pNew->CrtcVTotal = pNew->VTotal = val.num; + else xf86ConfigError("Vertical total expected"); + had_vtimings = 1; + break; + case FLAGS: + token = xf86GetToken(NULL); + if (token != STRING) + xf86ConfigError("Flag string expected. Note: flags must be in \"\""); + while ( token == STRING ) { + token2 = getStringToken(TimingTab); + switch(token2) { + case TT_INTERLACE: pNew->Flags |= V_INTERLACE; break; + case TT_PHSYNC: pNew->Flags |= V_PHSYNC; break; + case TT_NHSYNC: pNew->Flags |= V_NHSYNC; break; + case TT_PVSYNC: pNew->Flags |= V_PVSYNC; break; + case TT_NVSYNC: pNew->Flags |= V_NVSYNC; break; + case TT_CSYNC: pNew->Flags |= V_CSYNC; break; + case TT_PCSYNC: pNew->Flags |= V_PCSYNC; break; + case TT_NCSYNC: pNew->Flags |= V_NCSYNC; break; + case TT_DBLSCAN: pNew->Flags |= V_DBLSCAN; break; + default: + xf86ConfigError("Unknown flag string"); break; + } + token = xf86GetToken(NULL); + } + pushToken = token; + break; + case HSKEW: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Horizontal skew expected"); + pNew->Flags |= V_HSKEW; + pNew->CrtcHSkew = pNew->HSkew = val.num; + break; + } + } + if ( !had_dotclock ) xf86ConfigError("the dotclock is missing"); + if ( !had_htimings ) xf86ConfigError("the horizontal timings are missing"); + if ( !had_vtimings ) xf86ConfigError("the vertical timings are missing"); +#ifdef NEED_RETURN_VALUE + return RET_OKAY; +#endif +} + +static Bool dummy; + +#ifdef XF86SETUP +int xf86setup_scrn_ndisps[8]; +DispPtr xf86setup_scrn_displays[8]; +#endif + +static CONFIG_RETURN_TYPE +configScreenSection() +{ + int i, j; + int driverno; + int had_monitor = 0, had_device = 0; + int dispIndex = 0; + int numDisps = 0; + DispPtr dispList = NULL; + DispPtr dispp; + + int token; + ScrnInfoPtr screen = NULL; + int textClockValue = -1; + + token = xf86GetToken(ScreenTab); + if ( token != DRIVER ) + xf86ConfigError("The screen section must begin with the 'driver' line"); + + if (xf86GetToken(NULL) != STRING) xf86ConfigError("Driver name expected"); + driverno = getStringToken(DriverTab); + switch ( driverno ) { + case SVGA: + case VGA2: + case MONO: + case VGA16: + case ACCEL: + case FBDEV: + break; + default: + xf86ConfigError("Not a recognized driver name"); + } + scr_index = getScreenIndex(driverno); + + dummy = scr_index < 0 || !xf86Screens[scr_index]; + if (dummy) + screen = (ScrnInfoPtr)xalloc(sizeof(ScrnInfoRec)); + else + { + screen = xf86Screens[scr_index]; + screen->configured = TRUE; + screen->tmpIndex = screenno++; + screen->scrnIndex = scr_index; /* scrnIndex must not be changed */ + screen->frameX0 = -1; + screen->frameY0 = -1; + screen->virtualX = -1; + screen->virtualY = -1; + screen->defaultVisual = -1; + screen->modes = NULL; + screen->width = 240; + screen->height = 180; + screen->bankedMono = FALSE; + screen->textclock = -1; + screen->blackColour.red = 0; + screen->blackColour.green = 0; + screen->blackColour.blue = 0; + screen->whiteColour.red = 0x3F; + screen->whiteColour.green = 0x3F; + screen->whiteColour.blue = 0x3F; + } + screen->clocks = 0; + + while ((token = xf86GetToken(ScreenTab)) != ENDSECTION) { + switch (token) { + + case DEFBPP: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Default color depth expected"); + screen->depth = val.num; + break; + + case SCREENNO: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Screen number expected"); + screen->tmpIndex = val.num; + break; + + case SUBSECTION: + if ((xf86GetToken(NULL) != STRING) || (StrCaseCmp(val.str, "display") != 0)) { + xf86ConfigError("You must say \"Display\" here"); + } + if (dispList == NULL) { + dispList = (DispPtr)xalloc(sizeof(DispRec)); + } else { + dispList = (DispPtr)xrealloc(dispList, + (numDisps + 1) * sizeof(DispRec)); + } + dispp = dispList + numDisps; + numDisps++; + dispp->depth = -1; + dispp->weight.red = dispp->weight.green = dispp->weight.blue = 0; + dispp->frameX0 = -1; + dispp->frameY0 = -1; + dispp->virtualX = -1; + dispp->virtualY = -1; + dispp->modes = NULL; + dispp->whiteColour.red = dispp->whiteColour.green = + dispp->whiteColour.blue = 0x3F; + dispp->blackColour.red = dispp->blackColour.green = + dispp->blackColour.blue = 0; + dispp->defaultVisual = -1; + OFLG_ZERO(&(dispp->options)); + OFLG_ZERO(&(dispp->xconfigFlag)); + dispp->DCOptions = NULL; + + configDisplaySubsection(dispp); + break; + + case EOF: + FatalError("Unexpected EOF (missing EndSection?)"); + break; /* :-) */ + + case MDEVICE: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("Device name expected"); + for ( i = 0 ; i < n_devices ; i++ ) { + if ( strcmp(device_list[i].identifier,val.str) == 0 ) { + /* Copy back */ + if (!dummy && xf86Verbose) { + ErrorF("%s %s: Graphics device ID: \"%s\"\n", + XCONFIG_GIVEN, screen->name, device_list[i].identifier); + } + screen->clocks = device_list[i].clocks; + for ( j = 0 ; j < MAXCLOCKS ; j++ ) { + screen->clock[j] = device_list[i].clock[j]; + } + screen->chipset = device_list[i].chipset; + screen->ramdac = device_list[i].ramdac; + for (j=0; j<MAXDACSPEEDS; j++) + screen->dacSpeeds[j] = device_list[i].dacSpeeds[j]; + screen->dacSpeedBpp = 0; + screen->options = device_list[i].options; + screen->clockOptions = device_list[i].clockOptions; + screen->xconfigFlag = device_list[i].xconfigFlag; + screen->videoRam = device_list[i].videoRam; + screen->speedup = device_list[i].speedup; + screen->clockprog = device_list[i].clockprog; + textClockValue = device_list[i].textClockValue; + if (OFLG_ISSET(XCONFIG_BIOSBASE, &screen->xconfigFlag)) + screen->BIOSbase = device_list[i].BIOSbase; + if (OFLG_ISSET(XCONFIG_MEMBASE, &screen->xconfigFlag)) + screen->MemBase = device_list[i].MemBase; + if (OFLG_ISSET(XCONFIG_IOBASE, &screen->xconfigFlag)) + screen->IObase = device_list[i].IObase; + if (OFLG_ISSET(XCONFIG_DACBASE, &screen->xconfigFlag)) + screen->DACbase = device_list[i].DACbase; + if (OFLG_ISSET(XCONFIG_COPBASE, &screen->xconfigFlag)) + screen->COPbase = device_list[i].COPbase; + if (OFLG_ISSET(XCONFIG_POSBASE, &screen->xconfigFlag)) + screen->POSbase = device_list[i].POSbase; + if (OFLG_ISSET(XCONFIG_INSTANCE, &screen->xconfigFlag)) + screen->instance = device_list[i].instance; + screen->s3Madjust = device_list[i].s3Madjust; + screen->s3Nadjust = device_list[i].s3Nadjust; + screen->s3MClk = device_list[i].s3MClk; + screen->MemClk = device_list[i].MemClk; + screen->LCDClk = device_list[i].LCDClk; + screen->chipID = device_list[i].chipID; + screen->chipRev = device_list[i].chipRev; + screen->s3RefClk = device_list[i].s3RefClk; + screen->s3BlankDelay = device_list[i].s3BlankDelay; + screen->textClockFreq = device_list[i].textClockValue; + if (OFLG_ISSET(XCONFIG_VGABASE, &screen->xconfigFlag)) + screen->VGAbase = device_list[i].VGAbase; + screen->DCConfig = device_list[i].DCConfig; + screen->DCOptions = device_list[i].DCOptions; +#ifdef XF86SETUP + screen->device = (void *) &device_list[i]; +#endif + break; + } + } + if ( i == n_devices ) { /* Exhausted the device list */ + xf86ConfigError("Not a declared device"); + } + had_device = 1; + break; + + case MONITOR: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("Monitor name expected"); + for ( i = 0 ; i < n_monitors ; i++ ) { + if ( strcmp(monitor_list[i].id,val.str) == 0 ) { + if (!dummy && xf86Verbose) { + ErrorF("%s %s: Monitor ID: \"%s\"\n", + XCONFIG_GIVEN, screen->name, monitor_list[i].id); + } + if (!dummy) { + monitor_list[i].Modes = xf86PruneModes(&monitor_list[i], + monitor_list[i].Modes, + screen, FALSE); + screen->monitor = (MonPtr)xalloc(sizeof(MonRec)); + memcpy(screen->monitor, &monitor_list[i], sizeof(MonRec)); + } + break; + } + } + if ( i == n_monitors ) { /* Exhausted the monitor list */ + xf86ConfigError("Not a declared monitor"); + } + had_monitor = 1; + break; + + case BLANKTIME: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Screensaver blank time expected"); + if (!dummy && !xf86sFlag) + defaultScreenSaverTime = ScreenSaverTime = val.num * MILLI_PER_MIN; + break; + + case STANDBYTIME: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Screensaver standby time expected"); +#ifdef DPMSExtension + if (!dummy) + DPMSStandbyTime = val.num * MILLI_PER_MIN; +#endif + break; + + case SUSPENDTIME: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Screensaver suspend time expected"); +#ifdef DPMSExtension + if (!dummy) + DPMSSuspendTime = val.num * MILLI_PER_MIN; +#endif + break; + + case OFFTIME: + if (xf86GetToken(NULL) != NUMBER) + xf86ConfigError("Screensaver off time expected"); +#ifdef DPMSExtension + if (!dummy) + DPMSOffTime = val.num * MILLI_PER_MIN; +#endif + break; + + default: + if (!dummy && !validateGraphicsToken(screen->validTokens, token)) + { + xf86ConfigError("Screen section keyword expected"); + } + break; + } + } + + if (!dummy) { + if (dispList == NULL) { + FatalError( + "A \"Display\" subsection is required in each \"Screen\" section\n"); + } else { + /* Work out which if any Display subsection to use based on depth */ + if (xf86bpp < 0) { + /* + * no -bpp option given, so take depth if only one Display subsection + * Don't do this for VGA2 and VGA16 where it makes no sense, and only + * causes problems + */ + if (numDisps == 1) { +#ifndef XF86SETUP + if (dispList[0].depth > 0 + && !(driverno >= VGA2 && driverno <= VGA16)) { + xf86bpp = dispList[0].depth; + } +#endif + dispIndex = 0; + } else { + xf86bpp = screen->depth; + /* Look for a section which matches the driver's default depth */ + for (dispIndex = 0; dispIndex < numDisps; dispIndex++) { + if (dispList[dispIndex].depth == screen->depth) + break; + } + if (dispIndex == numDisps) { + /* No match. This time, allow 15/16 and 24/32 to match */ + for (dispIndex = 0; dispIndex < numDisps; dispIndex++) { + if ((screen->depth == 15 && dispList[dispIndex].depth == 16) || + (screen->depth == 16 && dispList[dispIndex].depth == 15) || + (screen->depth == 24 && dispList[dispIndex].depth == 32) || + (screen->depth == 32 && dispList[dispIndex].depth == 24)) + break; + } + } + if (dispIndex == numDisps) { + /* Still no match, so exit */ + FatalError("No \"Display\" subsection for default depth %d\n", + screen->depth); + } + } + } else { + /* xf86bpp is set */ + if (numDisps == 1 && dispList[0].depth < 0) { + /* one Display subsection, no depth set, so use it */ + /* XXXX Maybe should only do this when xf86bpp == default depth?? */ + dispIndex = 0; + } else { + /* find Display subsection matching xf86bpp */ + for (dispIndex = 0; dispIndex < numDisps; dispIndex++) { + if (dispList[dispIndex].depth == xf86bpp) + break; + } + if (dispIndex == numDisps) { +#if 0 + /* No match. This time, allow 15/16 and 24/32 to match */ + for (dispIndex = 0; dispIndex < numDisps; dispIndex++) { + if ((xf86bpp == 15 && dispList[dispIndex].depth == 16) || + (xf86bpp == 16 && dispList[dispIndex].depth == 15) || + (xf86bpp == 24 && dispList[dispIndex].depth == 32) || + (xf86bpp == 32 && dispList[dispIndex].depth == 24)) + break; +#else + /* No match. This time, allow 15/16 to match */ + for (dispIndex = 0; dispIndex < numDisps; dispIndex++) { + if ((xf86bpp == 15 && dispList[dispIndex].depth == 16) || + (xf86bpp == 16 && dispList[dispIndex].depth == 15)) + break; +#endif + } + } + if (dispIndex == numDisps) { + if (!(driverno >= VGA2 && driverno <= VGA16)) { + /* Still no match, so exit */ + FatalError("No \"Display\" subsection for -bpp depth %d\n", + xf86bpp); + } + else + dispIndex = 0; + } + } + } + /* Now copy the info across to the screen rec */ + dispp = dispList + dispIndex; + if (xf86bpp > 0) screen->depth = xf86bpp; + else if (dispp->depth > 0) screen->depth = dispp->depth; + if (xf86weight.red || xf86weight.green || xf86weight.blue) + screen->weight = xf86weight; + else if (dispp->weight.red > 0) { + screen->weight = dispp->weight; + xf86weight = dispp->weight; + } + screen->frameX0 = dispp->frameX0; + screen->frameY0 = dispp->frameY0; + screen->virtualX = dispp->virtualX; + screen->virtualY = dispp->virtualY; + screen->modes = dispp->modes; + screen->whiteColour = dispp->whiteColour; + screen->blackColour = dispp->blackColour; + screen->defaultVisual = dispp->defaultVisual; + /* Add any new options that might be set */ + for (i = 0; i < MAX_OFLAGS; i++) { + if (OFLG_ISSET(i, &(dispp->options))) + OFLG_SET(i, &(screen->options)); + if (OFLG_ISSET(i, &(dispp->xconfigFlag))) + OFLG_SET(i, &(screen->xconfigFlag)); + } + screen->DCOptions = xf86DCConcatOption(screen->DCOptions,dispp->DCOptions); +#ifdef XF86SETUP + xf86setup_scrn_ndisps[driverno-SVGA] = numDisps; + xf86setup_scrn_displays[driverno-SVGA] = dispList; +#else + /* Don't need them any more */ + xfree(dispList); +#endif + } + + /* Maybe these should be FatalError() instead? */ + if ( !had_monitor ) { + xf86ConfigError("A screen must specify a monitor"); + } + if ( !had_device ) { + xf86ConfigError("A screen must specify a device"); + } + } + + /* Check for information that must be specified in XF86Config */ + if (scr_index >= 0 && xf86Screens[scr_index]) + { + ScrnInfoPtr driver = xf86Screens[scr_index]; + + graphFound = TRUE; + + if (driver->clockprog && !driver->clocks) + { + if (!OFLG_ISSET(CLOCK_OPTION_PROGRAMABLE, &(screen->clockOptions))){ + ErrorF("%s: No clock line specified: assuming programmable clocks\n"); + OFLG_SET(CLOCK_OPTION_PROGRAMABLE, &(screen->clockOptions));} + driver->textclock = textClockValue; + } + + /* Find the Index of the Text Clock for the ClockProg */ + if (driver->clockprog && textClockValue > 0 + && !OFLG_ISSET(CLOCK_OPTION_PROGRAMABLE, &(screen->clockOptions))) + { + driver->textclock = xf86GetNearestClock(driver, textClockValue); + if (abs(textClockValue - driver->clock[driver->textclock]) > + CLOCK_TOLERANCE) + FatalError( + "There is no defined dot-clock matching the text clock\n"); + if (xf86Verbose) + ErrorF("%s %s: text clock = %7.3f, clock used = %7.3f\n", + XCONFIG_GIVEN, + driver->name, textClockValue / 1000.0, + driver->clock[driver->textclock] / 1000.0); + } + if (xf86Verbose && driver->defaultVisual > 0) { + char *visualname; + switch (driver->defaultVisual) { + case StaticGray: + case GrayScale: + case StaticColor: + case PseudoColor: + case TrueColor: + case DirectColor: + visualname = xf86VisualNames[driver->defaultVisual]; + break; + default: + xf86ConfigError("unknown visual type"); + } + ErrorF("%s %s: Default visual: %s\n", XCONFIG_GIVEN, driver->name, + visualname); + } + if (defaultColorVisualClass < 0) + defaultColorVisualClass = driver->defaultVisual; + + /* GJA --Moved these from the device code. Had to reorganize it + * a bit. + */ + if (xf86Verbose) { + if (OFLG_ISSET(XCONFIG_IOBASE, &driver->xconfigFlag)) + ErrorF("%s %s: Direct Access Register I/O Base Address: %x\n", + XCONFIG_GIVEN, driver->name, driver->IObase); + + if (OFLG_ISSET(XCONFIG_DACBASE, &driver->xconfigFlag)) + ErrorF("%s %s: DAC Base I/O Address: %x\n", + XCONFIG_GIVEN, driver->name, driver->DACbase); + + if (OFLG_ISSET(XCONFIG_COPBASE, &driver->xconfigFlag)) + ErrorF("%s %s: Coprocessor Base Memory Address: %x\n", + XCONFIG_GIVEN, driver->name, driver->COPbase); + + if (OFLG_ISSET(XCONFIG_POSBASE, &driver->xconfigFlag)) + ErrorF("%s %s: POS Base Address: %x\n", XCONFIG_GIVEN, driver->name, + driver->POSbase); + + if (OFLG_ISSET(XCONFIG_BIOSBASE, &driver->xconfigFlag)) + ErrorF("%s %s: BIOS Base Address: %x\n", XCONFIG_GIVEN, driver->name, + driver->BIOSbase); + + if (OFLG_ISSET(XCONFIG_MEMBASE, &driver->xconfigFlag)) + ErrorF("%s %s: Memory Base Address: %x\n", XCONFIG_GIVEN, + driver->name, driver->MemBase); + + if (OFLG_ISSET(XCONFIG_VGABASE, &driver->xconfigFlag)) + ErrorF("%s %s: VGA Aperture Base Address: %x\n", XCONFIG_GIVEN, + driver->name, driver->VGAbase); + + /* Print clock program */ + if ( driver->clockprog ) { + ErrorF("%s %s: ClockProg: \"%s\"", XCONFIG_GIVEN, driver->name, + driver->clockprog); + if ( textClockValue ) + ErrorF(", Text Clock: %7.3f\n", textClockValue / 1000.0); + ErrorF("\n"); + } + } + } +#ifdef NEED_RETURN_VALUE + return RET_OKAY; +#endif +} + +static CONFIG_RETURN_TYPE +configDisplaySubsection(disp) +DispPtr disp; +{ + int token; + int i; + + while ((token = xf86GetToken(DisplayTab)) != ENDSUBSECTION) { + switch (token) { + case DEPTH: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Display depth expected"); + disp->depth = val.num; + break; + + case WEIGHT: + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Display weight expected"); + if (val.num > 9) { + disp->weight.red = (val.num / 100) % 10; + disp->weight.green = (val.num / 10) % 10; + disp->weight.blue = val.num % 10; + } else { + disp->weight.red = val.num; + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Display weight expected"); + disp->weight.green = val.num; + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Display weight expected"); + disp->weight.blue = val.num; + } + break; + + case VIEWPORT: + OFLG_SET(XCONFIG_VIEWPORT,&(disp->xconfigFlag)); + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Viewport X expected"); + disp->frameX0 = val.num; + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Viewport Y expected"); + disp->frameY0 = val.num; + break; + + case VIRTUAL: + OFLG_SET(XCONFIG_VIRTUAL,&(disp->xconfigFlag)); + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Virtual X expected"); + disp->virtualX = val.num; + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Virtual Y expected"); + disp->virtualY = val.num; + break; + + case MODES: + for (pLast=NULL; (token = xf86GetToken(NULL)) == STRING; pLast = pNew) + { + pNew = (DisplayModePtr)xalloc(sizeof(DisplayModeRec)); + pNew->name = val.str; + pNew->PrivSize = 0; + pNew->Private = NULL; + + if (pLast) + { + pLast->next = pNew; + pNew->prev = pLast; + } + else + disp->modes = pNew; + } + /* Make sure at least one mode was present */ + if (!pLast) + xf86ConfigError("Mode name expected"); + pNew->next = disp->modes; + disp->modes->prev = pLast; + pushToken = token; + break; + + case BLACK: + case WHITE: + { + unsigned char rgb[3]; + int ii; + + for (ii = 0; ii < 3; ii++) + { + if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("RGB value expected"); + rgb[ii] = val.num & 0x3F; + } + if (token == BLACK) + { + disp->blackColour.red = rgb[0]; + disp->blackColour.green = rgb[1]; + disp->blackColour.blue = rgb[2]; + } + else + { + disp->whiteColour.red = rgb[0]; + disp->whiteColour.green = rgb[1]; + disp->whiteColour.blue = rgb[2]; + } + } + break; + + case VISUAL: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("Visual name expected"); + token = getStringToken(VisualTab); + if (!dummy && disp->defaultVisual >= 0) + xf86ConfigError("Only one default visual may be specified"); + disp->defaultVisual = token - STATICGRAY; + break; + + case OPTION: + if (xf86GetToken(NULL) != STRING) xf86ConfigError("Option string expected"); + i = 0; + while (xf86_OptionTab[i].token != -1) + { + if (StrCaseCmp(val.str, xf86_OptionTab[i].name) == 0) + { + OFLG_SET(xf86_OptionTab[i].token, &(disp->options)); + break; + } + i++; + } + if (xf86_OptionTab[i].token == -1) + disp->DCOptions = xf86DCOption(disp->DCOptions,val); + break; + + /* The following should really go in the S3 server */ + case INVERTVCLK: + case BLANKDELAY: + case EARLYSC: + { + DisplayModePtr p = disp->modes; + if (xf86GetToken(NULL) != STRING) xf86ConfigError("Mode name expected"); + if (disp->modes == NULL) + xf86ConfigError("This must be after the Modes line"); + { + Bool found = FALSE; + int opt; + INT32 value; + char *mode_string = (char *)xalloc(strlen(val.str)+1); + strcpy(mode_string,val.str); + + switch (token) { + default: /* pacify compiler (uninitialized opt, value) */ + case INVERTVCLK: + if (xf86GetToken(NULL) != NUMBER || val.num < 0 || val.num > 1) + xf86ConfigError("0 or 1 expected"); + opt = S3_INVERT_VCLK; + value = val.num; + break; + + case BLANKDELAY: + if (xf86GetToken(NULL) != NUMBER || val.num < 0 || val.num > 7) + xf86ConfigError("number(s) 0..7 expected"); + opt = S3_BLANK_DELAY; + value = val.num; + if ((token=xf86GetToken(NULL)) == NUMBER) { + if (val.num < 0 || val.num > 7) + xf86ConfigError("number2 0..7 expected"); + value |= val.num << 4; + } + else pushToken = token; + break; + + case EARLYSC: + if (xf86GetToken(NULL) != NUMBER || val.num < 0 || val.num > 1) + xf86ConfigError("0 or 1 expected"); + opt = S3_EARLY_SC; + value = val.num; + break; + } + + do { + if (strcmp(p->name, mode_string) == 0 + || strcmp("*", mode_string) == 0) { + found = TRUE; + if (!p->PrivSize || !p->Private) { + p->PrivSize = S3_MODEPRIV_SIZE; + p->Private = (INT32 *)Xcalloc(sizeof(INT32) * S3_MODEPRIV_SIZE); + p->Private[0] = 0; + } + p->Private[0] |= (1 << opt); + p->Private[opt] = value; + } + p = p->next; + } while (p != disp->modes); + if (!found) xf86ConfigError("No mode of that name in the Modes line"); + xfree(mode_string); + } + } + break; + + + case EOF: + FatalError("Unexpected EOF (missing EndSubSection)"); + break; /* :-) */ + + default: + xf86ConfigError("Display subsection keyword expected"); + break; + } + } +#ifdef NEED_RETURN_VALUE + return RET_OKAY; +#endif +} + +Bool +xf86LookupMode(target, driver, flags) + DisplayModePtr target; + ScrnInfoPtr driver; + int flags; +{ + DisplayModePtr p; + DisplayModePtr best_mode = NULL; + int i, j, k, Gap; + int Minimum_Gap = CLOCK_TOLERANCE + 1; + Bool found_mode = FALSE; + Bool clock_too_high = FALSE; + static Bool first_time = TRUE; + double refresh, bestRefresh = 0.0; + + if (first_time) + { + ErrorF("%s %s: Maximum allowed dot-clock: %1.3f MHz\n", XCONFIG_PROBED, + driver->name, driver->maxClock / 1000.0); + first_time = FALSE; + /* + * First time through, cull modes which are not valid for the + * card/driver. + */ + driver->monitor->Modes = xf86PruneModes(NULL, driver->monitor->Modes, + driver, TRUE); + } + + if (xf86BestRefresh && !(flags & LOOKUP_FORCE_DEFAULT)) + flags |= LOOKUP_BEST_REFRESH; + + for (p = driver->monitor->Modes; p != NULL; p = p->next) /* scan list */ + { + if (!strcmp(p->name, target->name)) /* names equal ? */ + { + /* First check if the driver objects to the mode */ + if ((driver->ValidMode)(p, xf86Verbose, MODE_USED) != MODE_OK) + { + ErrorF("%s %s: Mode \"%s\" rejected by driver. Deleted.\n", + XCONFIG_PROBED,driver->name, target->name ); + break; + } + + if ((flags & LOOKUP_NO_INTERLACED) && (p->Flags & V_INTERLACE)) + { + continue; + } + + if ((OFLG_ISSET(CLOCK_OPTION_PROGRAMABLE, &(driver->clockOptions))) && + !OFLG_ISSET(OPTION_NO_PROGRAM_CLOCKS, &(driver->options))) + { + if (driver->clocks == 0) + { + /* this we know */ + driver->clock[0] = 25175; /* 25.175Mhz */ + driver->clock[1] = 28322; /* 28.322MHz */ + driver->clocks = 2; + } + + if ((p->Clock / 1000) > (driver->maxClock / 1000)) + clock_too_high = TRUE; + else + { + /* We fill in the the programmable clocks as we go */ + for (i=0; i < driver->clocks; i++) + if (driver->clock[i] == p->Clock) + break; + + if (i >= MAXCLOCKS) + { + ErrorF("%s %s: Too many programmable clocks used (limit %d)!\n", + XCONFIG_PROBED, driver->name, MAXCLOCKS); + return FALSE; + } + + if (i == driver->clocks) + { + driver->clock[i] = p->Clock; + driver->clocks++; + } + + + if (flags & LOOKUP_BEST_REFRESH) + { + refresh = p->Clock * 1000.0 / p->HTotal / p->VTotal; + if (p->Flags & V_INTERLACE) + { + refresh *= 2; + refresh /= INTERLACE_REFRESH_WEIGHT; + } + else if (p->Flags & V_DBLSCAN) + { + refresh /= 2; + } + if (refresh > bestRefresh) + { + best_mode = p; + bestRefresh = refresh; + target->Clock = i; + } + } + else + { + target->Clock = i; + best_mode = p; + } + } + } + else + { + /* + * go look if any of the clocks in the list matches the one in + * the mode (j=1), or if a better match exists when the clocks + * in the list are divided by 2 (j=2) + */ + if (OFLG_ISSET(OPTION_CLKDIV2, &(driver->options))) + k=2; + else + k=1; + for (j=1 ; j<=k ; j++) + { + i = xf86GetNearestClock(driver, p->Clock*j); + if (flags & LOOKUP_BEST_REFRESH) + { + if ( ((driver->clock[i]/j) / 1000) > (driver->maxClock / 1000) ) + clock_too_high = TRUE; + else + { + refresh = p->Clock * 1000.0 / p->HTotal / p->VTotal; + if (p->Flags & V_INTERLACE) + { + refresh *= 2; + refresh /= INTERLACE_REFRESH_WEIGHT; + } + else if (p->Flags & V_DBLSCAN) + { + refresh /= 2; + } + if (refresh > bestRefresh) + { + target->Clock = i; + if (j==2) p->Flags |= V_CLKDIV2; + best_mode = p; + bestRefresh = refresh; + } + } + } + else + { + Gap = abs( p->Clock - (driver->clock[i]/j) ); + if (Gap < Minimum_Gap) + { + if ( ((driver->clock[i]/j) / 1000) > (driver->maxClock / 1000) ) + clock_too_high = TRUE; + else + { + target->Clock = i; + if (j==2) p->Flags |= V_CLKDIV2; + best_mode = p; + Minimum_Gap = Gap; + } + } + } + } + } + found_mode = TRUE; + } + } + + if (best_mode != NULL) + { + target->HDisplay = best_mode->HDisplay; + target->HSyncStart = best_mode->HSyncStart; + target->HSyncEnd = best_mode->HSyncEnd; + target->HTotal = best_mode->HTotal; + target->HSkew = best_mode->HSkew; + target->VDisplay = best_mode->VDisplay; + target->VSyncStart = best_mode->VSyncStart; + target->VSyncEnd = best_mode->VSyncEnd; + target->VTotal = best_mode->VTotal; + target->Flags = best_mode->Flags; + target->CrtcHDisplay = best_mode->CrtcHDisplay; + target->CrtcHSyncStart = best_mode->CrtcHSyncStart; + target->CrtcHSyncEnd = best_mode->CrtcHSyncEnd; + target->CrtcHTotal = best_mode->CrtcHTotal; + target->CrtcHSkew = best_mode->CrtcHSkew; + target->CrtcVDisplay = best_mode->CrtcVDisplay; + target->CrtcVSyncStart = best_mode->CrtcVSyncStart; + target->CrtcVSyncEnd = best_mode->CrtcVSyncEnd; + target->CrtcVTotal = best_mode->CrtcVTotal; + target->CrtcHAdjusted = best_mode->CrtcHAdjusted; + target->CrtcVAdjusted = best_mode->CrtcVAdjusted; + if (target->Flags & V_DBLSCAN) + { + target->CrtcVDisplay *= 2; + target->CrtcVSyncStart *= 2; + target->CrtcVSyncEnd *= 2; + target->CrtcVTotal *= 2; + target->CrtcVAdjusted = TRUE; + } + +#if 0 + /* I'm not sure if this is the best place for this in the + * new XF86Config organization. - SRA + */ + if (found_mode) + if ((driver->ValidMode)(target, xf86Verbose, MODE_USED) != MODE_OK) + { + ErrorF("%s %s: Unable to support mode \"%s\"\n", + XCONFIG_GIVEN,driver->name, target->name ); + return(FALSE); + } +#endif + + if (xf86Verbose) + { + ErrorF("%s %s: Mode \"%s\": mode clock = %7.3f", + XCONFIG_GIVEN, driver->name, target->name, + best_mode->Clock / 1000.0); + if (!OFLG_ISSET(CLOCK_OPTION_PROGRAMABLE, &(driver->clockOptions)) || + OFLG_ISSET(OPTION_NO_PROGRAM_CLOCKS, &(driver->options))) { + ErrorF(", clock used = %7.3f", driver->clock[target->Clock] / 1000.0); + if (target->Flags & V_CLKDIV2) + ErrorF("/2"); + } + ErrorF("\n"); + } + } + else if (!found_mode) + ErrorF("%s %s: There is no mode definition named \"%s\"\n", + XCONFIG_PROBED, driver->name, target->name); + else if (clock_too_high) + ErrorF("%s %s: Clock for mode \"%s\" %s\n\tLimit is %7.3f MHz\n", + XCONFIG_PROBED, driver->name, target->name, + "is too high for the configured hardware.", + driver->maxClock / 1000.0); + else + ErrorF("%s %s: There is no defined dot-clock matching mode \"%s\"\n", + XCONFIG_PROBED, driver->name, target->name); + + return (best_mode != NULL); +} + +void +xf86VerifyOptions(allowedOptions, driver) + OFlagSet *allowedOptions; + ScrnInfoPtr driver; +{ + int j; + + for (j=0; xf86_OptionTab[j].token >= 0; j++) + if ((OFLG_ISSET(xf86_OptionTab[j].token, &driver->options))) + if (OFLG_ISSET(xf86_OptionTab[j].token, allowedOptions)) + { + if (xf86Verbose) + ErrorF("%s %s: Option \"%s\"\n", XCONFIG_GIVEN, + driver->name, xf86_OptionTab[j].name); + } + else + ErrorF("%s %s: Option flag \"%s\" is not defined for this driver\n", + XCONFIG_GIVEN, driver->name, xf86_OptionTab[j].name); +} + +/* Note: (To keep me [GJA] from getting confused) + * We have two mode-related datastructures: + * 1. A doubly linked mode name list, with ends marked by self-pointers. + * 2. A doubly linked mode structure list. + * We are operating here on the second structure. + * Initially this is just singly linked. + */ +static DisplayModePtr +xf86PruneModes(monp, allmodes, scrp, card) + MonPtr monp; /* Monitor specification */ + DisplayModePtr allmodes; /* List to be pruned */ + ScrnInfoPtr scrp; + Bool card; /* TRUE => do driver validity check */ +{ + DisplayModePtr dispmp; /* To walk the list */ + DisplayModePtr olddispmp; /* The one being freed. */ + DisplayModePtr remainder; /* The first one retained. */ + + dispmp = allmodes; + + /* The first modes to be deleted require that the pointer to the + * mode list is updated. Also, they have no predecessor in the list. + */ + while (dispmp && + (card ? + ((scrp->ValidMode)(dispmp, xf86Verbose, MODE_SUGGESTED) + != MODE_OK) : + (xf86CheckMode(scrp, dispmp, monp, xf86Verbose) != MODE_OK))) { + olddispmp = dispmp; + dispmp = dispmp->next; + xfree(olddispmp->name); + xfree(olddispmp); + } + /* Now we either have a mode that fits, or no mode at all */ + if ( ! dispmp ) { /* No mode at all */ + return NULL; + } + remainder = dispmp; + while ( dispmp->next ) { + if (card ? + ((scrp->ValidMode)(dispmp->next,xf86Verbose,MODE_SUGGESTED) + != MODE_OK) : + (xf86CheckMode(scrp, dispmp->next, monp, xf86Verbose) != + MODE_OK)) { + olddispmp = dispmp->next; + dispmp->next = dispmp->next->next; + xfree(olddispmp->name); + xfree(olddispmp); + } else { + dispmp = dispmp->next; + } + } + return remainder; /* Return pointer to {the first / the list } */ +} + +/* + * Return MODE_OK if the mode pointed to by dispmp agrees with all constraints + * we can make up for the monitor pointed to by monp. + */ +int +xf86CheckMode(scrp, dispmp, monp, verbose) + ScrnInfoPtr scrp; + DisplayModePtr dispmp; + MonPtr monp; + Bool verbose; +{ + int i; + float dotclock, hsyncfreq, vrefreshrate; + char *scrname = scrp->name; + + /* Sanity checks */ + if ((0 >= dispmp->HDisplay) || + (dispmp->HDisplay > dispmp->HSyncStart) || + (dispmp->HSyncStart >= dispmp->HSyncEnd) || + (dispmp->HSyncEnd >= dispmp->HTotal)) + { + ErrorF( + "%s %s: Invalid horizontal timing for mode \"%s\". Deleted.\n", + XCONFIG_PROBED, scrname, dispmp->name); + return MODE_HSYNC; + } + + if ((0 >= dispmp->VDisplay) || + (dispmp->VDisplay > dispmp->VSyncStart) || + (dispmp->VSyncStart >= dispmp->VSyncEnd) || + (dispmp->VSyncEnd >= dispmp->VTotal)) + { + ErrorF( + "%s %s: Invalid vertical timing for mode \"%s\". Deleted.\n", + XCONFIG_PROBED, scrname, dispmp->name); + return MODE_VSYNC; + } + + /* Deal with the dispmp->Clock being a frequency or index */ + if (dispmp->Clock > MAXCLOCKS) { + dotclock = (float)dispmp->Clock; + } else { + dotclock = (float)scrp->clock[dispmp->Clock]; + } + hsyncfreq = dotclock / (float)(dispmp->HTotal); + for ( i = 0 ; i < monp->n_hsync ; i++ ) + if ( (hsyncfreq > 0.999 * monp->hsync[i].lo) && + (hsyncfreq < 1.001 * monp->hsync[i].hi) ) + break; /* In range. */ + + /* Now see whether we ran out of sync frequencies */ + if ( i == monp->n_hsync ) { + if (verbose) { + ErrorF( + "%s %s: Mode \"%s\" needs hsync freq of %.2f kHz. Deleted.\n", + XCONFIG_PROBED, scrname, dispmp->name, hsyncfreq); + } + return MODE_HSYNC; + } + + vrefreshrate = dotclock * 1000.0 / + ((float)(dispmp->HTotal) * (float)(dispmp->VTotal)) ; + if ( dispmp->Flags & V_INTERLACE ) vrefreshrate *= 2.0; + if ( dispmp->Flags & V_DBLSCAN ) vrefreshrate /= 2.0; + for ( i = 0 ; i < monp->n_vrefresh ; i++ ) + if ( (vrefreshrate > 0.999 * monp->vrefresh[i].lo) && + (vrefreshrate < 1.001 * monp->vrefresh[i].hi) ) + break; /* In range. */ + + /* Now see whether we ran out of refresh rates */ + if ( i == monp->n_vrefresh ) { + if (verbose) { + ErrorF( + "%s %s: Mode \"%s\" needs vert refresh rate of %.2f Hz. Deleted.\n", + XCONFIG_PROBED, scrname, dispmp->name, vrefreshrate); + } + return MODE_VSYNC; + } + + /* Interlaced modes should have an odd VTotal */ + if (dispmp->Flags & V_INTERLACE) + dispmp->CrtcVTotal = dispmp->VTotal |= 1; + + /* Passed every test. */ + return MODE_OK; +} + +/* + * Save entire line from config file in memory area, if memory area + * does not exist allocate it. Set DCerr according to value of token. + * Return address of memory area. + */ +static char *xf86DCSaveLine(DCPointer,token) + char *DCPointer; + int token; +{ + static int len = 0; /* length of memory area where to store strings */ + static int pos = 0; /* current position */ + char *currpointer; /* pointer to current position in memory area */ + static int currline; /* lineno of line currently interpreted */ + int addlen; /* len to add to pos */ + + if(DCPointer == NULL){ /* initialize */ + DCPointer = (char *)xalloc(4096); /* initial size 4kB */ + len = 4096; + strcpy(DCPointer,configPath); + pos = strlen(DCPointer) + 1; + currline = -1; /* no line yet */ + } + + if(configLineNo != currline) /* new line */ + { + currline = configLineNo; + addlen = strlen(configBuf) + 1 + sizeof(int); /* string + lineno */ + while ( (pos + addlen) >= len ){ /* not enough space? */ + DCPointer = (char *)xrealloc(DCPointer, (len + 4096)); + len += 4096; + } + currpointer = DCPointer + pos; /* find current position */ + memcpy(currpointer, &currline, sizeof(int)); /* Grrr unaligned ints.. */ + strcpy((currpointer + sizeof(int)),configBuf); /* store complete line*/ + pos += addlen; /* goto end */ + currpointer += addlen; + *(currpointer) = EOF; /* mark end */ + } + switch(token){ + case STRING: + case DASH: + case NUMBER: + case COMMA: + break; + case ERROR_TOKEN: /* if unknown token unset DCerr to ignore it */ + DCerr = 0; /* and subsequent STRING, DASH, NUMBER, COMMA */ + break; + default: /* set to complain if a valid token is */ + DCerr = 1; /* followed by an unwanted STRING etc. */ + } + return(DCPointer); +} + +/* + * Store any unknown Option strings (contained in val.str) + * in a memory are pointed to by pointer. If it doesn't + * exist allocate it and return a pointer pointing to it + */ + +static char * +xf86DCOption(DCPointer, val) + char *DCPointer; + LexRec val; +{ + static int len = 0; + static int pos = 0; + int addlen; + char *currpointer; /* current position */ + + if (DCPointer == NULL){ /* First time: initialize */ + DCPointer = (char *)xalloc(4096); /* allocate enough space */ + strcpy(DCPointer,configPath); + pos = strlen(DCPointer) + 1; + len = 4096; /* and total length */ + } + + addlen = sizeof(int) + strlen(val.str) + 1; /* token, lineno */ + while( (pos + addlen) >= len ){ /* reallocate if not enough */ + DCPointer = (char *)xrealloc(DCPointer, (len + 4096)); + len += 4096; + } + currpointer = DCPointer + pos; + *(int *)currpointer=configLineNo; + strcpy(currpointer + sizeof(int),val.str); /* store string */ + pos += addlen; + *(currpointer + addlen) = EOF; /* mark end */ + return(DCPointer); +} + +static char +* xf86DCConcatOption(Pointer1, Pointer2) +char *Pointer1; +char *Pointer2; +{ + int s1 = 0; + int s2 = 0; + int s3; + char *ptmp; + + if(Pointer1) + while(*(Pointer1 + s1) != EOF){s1++;} + else if (Pointer2) + return Pointer2; + else return NULL; + if(Pointer2) + while(*(Pointer2 + s2) != EOF){s2++;} + else if (Pointer1) + return Pointer1; + else return NULL; + s3 = strlen(Pointer2) + 1; + s2 -= s3; + + Pointer1 = (char *)xrealloc(Pointer1,s1+s2+1); + ptmp = Pointer1 + s1; + Pointer2 += s3; + do{ + *ptmp = *Pointer2; + *ptmp++; + *Pointer2++; + } while(s2--); + return Pointer1; +} + |