/* * $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 #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. */ 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; idacSpeeds[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; idacSpeeds[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; idacSpeeds[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; jdacSpeeds[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; }