xserver-multidpi/hw/xfree86/common/xf86Config.c
2003-11-14 15:54:54 +00:00

3935 lines
114 KiB
C

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