1/*
2 * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Except as contained in this notice, the name of the copyright holder(s)
23 * and author(s) shall not be used in advertising or otherwise to promote
24 * the sale, use or other dealings in this Software without prior written
25 * authorization from the copyright holder(s) and author(s).
26 */
27
28/*
29 * Authors: Dirk Hohndel <hohndel@XFree86.Org>
30 *          David Dawes <dawes@XFree86.Org>
31 *          ... and others
32 *
33 * This file includes the helper functions that the server provides for
34 * different drivers.
35 */
36
37#ifdef HAVE_XORG_CONFIG_H
38#include <xorg-config.h>
39#endif
40
41#include <X11/X.h>
42#include "os.h"
43#include "servermd.h"
44#include "pixmapstr.h"
45#include "windowstr.h"
46#include "propertyst.h"
47#include "gcstruct.h"
48#include "loaderProcs.h"
49#include "xf86.h"
50#include "xf86Priv.h"
51#include "xf86_OSlib.h"
52#include "micmap.h"
53#include "xf86DDC.h"
54#include "xf86Xinput.h"
55#include "xf86InPriv.h"
56#include "mivalidate.h"
57#include "xf86Crtc.h"
58
59/* For xf86GetClocks */
60#if defined(CSRG_BASED) || defined(__GNU__)
61#define HAS_SETPRIORITY
62#include <sys/resource.h>
63#endif
64
65static int xf86ScrnInfoPrivateCount = 0;
66
67
68/* Add a pointer to a new DriverRec to xf86DriverList */
69
70void
71xf86AddDriver(DriverPtr driver, pointer module, int flags)
72{
73    /* Don't add null entries */
74    if (!driver)
75	return;
76
77    if (xf86DriverList == NULL)
78	xf86NumDrivers = 0;
79
80    xf86NumDrivers++;
81    xf86DriverList = xnfrealloc(xf86DriverList,
82				xf86NumDrivers * sizeof(DriverPtr));
83    xf86DriverList[xf86NumDrivers - 1] = xnfalloc(sizeof(DriverRec));
84    if (flags & HaveDriverFuncs)
85	*xf86DriverList[xf86NumDrivers - 1] = *driver;
86    else {
87	(void) memset( xf86DriverList[xf86NumDrivers - 1], 0,
88		       sizeof( DriverRec ) );
89	(void) memcpy( xf86DriverList[xf86NumDrivers - 1], driver,
90		       sizeof(DriverRec1));
91
92    }
93    xf86DriverList[xf86NumDrivers - 1]->module = module;
94    xf86DriverList[xf86NumDrivers - 1]->refCount = 0;
95}
96
97void
98xf86DeleteDriver(int drvIndex)
99{
100    if (xf86DriverList[drvIndex]
101	&& (!xf86DriverHasEntities(xf86DriverList[drvIndex]))) {
102	if (xf86DriverList[drvIndex]->module)
103	    UnloadModule(xf86DriverList[drvIndex]->module);
104	free(xf86DriverList[drvIndex]);
105	xf86DriverList[drvIndex] = NULL;
106    }
107}
108
109/* Add a pointer to a new InputDriverRec to xf86InputDriverList */
110
111void
112xf86AddInputDriver(InputDriverPtr driver, pointer module, int flags)
113{
114    /* Don't add null entries */
115    if (!driver)
116	return;
117
118    if (xf86InputDriverList == NULL)
119	xf86NumInputDrivers = 0;
120
121    xf86NumInputDrivers++;
122    xf86InputDriverList = xnfrealloc(xf86InputDriverList,
123				xf86NumInputDrivers * sizeof(InputDriverPtr));
124    xf86InputDriverList[xf86NumInputDrivers - 1] =
125				xnfalloc(sizeof(InputDriverRec));
126    *xf86InputDriverList[xf86NumInputDrivers - 1] = *driver;
127    xf86InputDriverList[xf86NumInputDrivers - 1]->module = module;
128}
129
130void
131xf86DeleteInputDriver(int drvIndex)
132{
133    if (xf86InputDriverList[drvIndex] && xf86InputDriverList[drvIndex]->module)
134	UnloadModule(xf86InputDriverList[drvIndex]->module);
135    free(xf86InputDriverList[drvIndex]);
136    xf86InputDriverList[drvIndex] = NULL;
137}
138
139InputDriverPtr
140xf86LookupInputDriver(const char *name)
141{
142    int i;
143
144    for (i = 0; i < xf86NumInputDrivers; i++) {
145       if (xf86InputDriverList[i] && xf86InputDriverList[i]->driverName &&
146           xf86NameCmp(name, xf86InputDriverList[i]->driverName) == 0)
147           return xf86InputDriverList[i];
148    }
149    return NULL;
150}
151
152InputInfoPtr
153xf86LookupInput(const char *name)
154{
155    InputInfoPtr p;
156
157    for (p = xf86InputDevs; p != NULL; p = p->next) {
158        if (strcmp(name, p->name) == 0)
159            return p;
160    }
161
162    return NULL;
163}
164
165/* Allocate a new ScrnInfoRec in xf86Screens */
166
167ScrnInfoPtr
168xf86AllocateScreen(DriverPtr drv, int flags)
169{
170    int i;
171
172    if (xf86Screens == NULL)
173	xf86NumScreens = 0;
174
175    i = xf86NumScreens++;
176    xf86Screens = xnfrealloc(xf86Screens, xf86NumScreens * sizeof(ScrnInfoPtr));
177    xf86Screens[i] = xnfcalloc(sizeof(ScrnInfoRec), 1);
178    xf86Screens[i]->scrnIndex = i;	/* Changes when a screen is removed */
179    xf86Screens[i]->origIndex = i;	/* This never changes */
180    xf86Screens[i]->privates = xnfcalloc(sizeof(DevUnion),
181					 xf86ScrnInfoPrivateCount);
182    /*
183     * EnableDisableFBAccess now gets initialized in InitOutput()
184     * xf86Screens[i]->EnableDisableFBAccess = xf86EnableDisableFBAccess;
185     */
186
187    xf86Screens[i]->drv = drv;
188    drv->refCount++;
189    xf86Screens[i]->module = DuplicateModule(drv->module, NULL);
190
191    xf86Screens[i]->DriverFunc = drv->driverFunc;
192
193    return xf86Screens[i];
194}
195
196
197/*
198 * Remove an entry from xf86Screens.  Ideally it should free all allocated
199 * data.  To do this properly may require a driver hook.
200 */
201
202void
203xf86DeleteScreen(int scrnIndex, int flags)
204{
205    ScrnInfoPtr pScrn;
206    int i;
207
208    /* First check if the screen is valid */
209    if (xf86NumScreens == 0 || xf86Screens == NULL)
210	return;
211
212    if (scrnIndex > xf86NumScreens - 1)
213	return;
214
215    if (!(pScrn = xf86Screens[scrnIndex]))
216	return;
217
218    /* If a FreeScreen function is defined, call it here */
219    if (pScrn->FreeScreen != NULL)
220	pScrn->FreeScreen(scrnIndex, 0);
221
222    while (pScrn->modes)
223	xf86DeleteMode(&pScrn->modes, pScrn->modes);
224
225    while (pScrn->modePool)
226	xf86DeleteMode(&pScrn->modePool, pScrn->modePool);
227
228    xf86OptionListFree(pScrn->options);
229
230    if (pScrn->module)
231	UnloadModule(pScrn->module);
232
233    if (pScrn->drv)
234	pScrn->drv->refCount--;
235
236    free(pScrn->privates);
237
238    xf86ClearEntityListForScreen(scrnIndex);
239
240    free(pScrn);
241
242    /* Move the other entries down, updating their scrnIndex fields */
243
244    xf86NumScreens--;
245
246    for (i = scrnIndex; i < xf86NumScreens; i++) {
247	xf86Screens[i] = xf86Screens[i + 1];
248	xf86Screens[i]->scrnIndex = i;
249	/* Also need to take care of the screen layout settings */
250    }
251}
252
253/*
254 * Allocate a private in ScrnInfoRec.
255 */
256
257int
258xf86AllocateScrnInfoPrivateIndex(void)
259{
260    int idx, i;
261    ScrnInfoPtr pScr;
262    DevUnion *nprivs;
263
264    idx = xf86ScrnInfoPrivateCount++;
265    for (i = 0; i < xf86NumScreens; i++) {
266	pScr = xf86Screens[i];
267	nprivs = xnfrealloc(pScr->privates,
268			    xf86ScrnInfoPrivateCount * sizeof(DevUnion));
269	/* Zero the new private */
270	memset(&nprivs[idx], 0, sizeof(DevUnion));
271	pScr->privates = nprivs;
272    }
273    return idx;
274}
275
276Bool
277xf86AddPixFormat(ScrnInfoPtr pScrn, int depth, int bpp, int pad)
278{
279    int i;
280
281    if (pScrn->numFormats >= MAXFORMATS)
282	return FALSE;
283
284    if (bpp <= 0) {
285	if (depth == 1)
286	    bpp = 1;
287	else if (depth <= 8)
288	    bpp = 8;
289	else if (depth <= 16)
290	    bpp = 16;
291	else if (depth <= 32)
292	    bpp = 32;
293	else
294	    return FALSE;
295    }
296    if (pad <= 0)
297	pad = BITMAP_SCANLINE_PAD;
298
299    i = pScrn->numFormats++;
300    pScrn->formats[i].depth = depth;
301    pScrn->formats[i].bitsPerPixel = bpp;
302    pScrn->formats[i].scanlinePad = pad;
303    return TRUE;
304}
305
306/*
307 * Set the depth we are using based on (in the following order of preference):
308 *  - values given on the command line
309 *  - values given in the config file
310 *  - values provided by the driver
311 *  - an overall default when nothing else is given
312 *
313 * Also find a Display subsection matching the depth/bpp found.
314 *
315 * Sets the following ScrnInfoRec fields:
316 *     bitsPerPixel, pixmap24, depth, display, imageByteOrder,
317 *     bitmapScanlinePad, bitmapScanlineUnit, bitmapBitOrder, numFormats,
318 *     formats, fbFormat.
319 */
320
321/* Can the screen handle 24 bpp pixmaps */
322#define DO_PIX24(f) ((f & Support24bppFb) || \
323		     ((f & Support32bppFb) && (f & SupportConvert24to32)))
324
325/* Can the screen handle 32 bpp pixmaps */
326#define DO_PIX32(f) ((f & Support32bppFb) || \
327		     ((f & Support24bppFb) && (f & SupportConvert32to24)))
328
329/* Does the screen prefer 32bpp fb for 24bpp pixmaps */
330#define CHOOSE32FOR24(f) ((f & Support32bppFb) && (f & SupportConvert24to32) \
331			  && (f & PreferConvert24to32))
332
333/* Does the screen prefer 24bpp fb for 32bpp pixmaps */
334#define CHOOSE24FOR32(f) ((f & Support24bppFb) && (f & SupportConvert32to24) \
335			  && (f & PreferConvert32to24))
336
337/* Can the screen handle 32bpp pixmaps for 24bpp fb */
338#define DO_PIX32FOR24(f) ((f & Support24bppFb) && (f & SupportConvert32to24))
339
340/* Can the screen handle 24bpp pixmaps for 32bpp fb */
341#define DO_PIX24FOR32(f) ((f & Support32bppFb) && (f & SupportConvert24to32))
342
343#ifndef GLOBAL_DEFAULT_DEPTH
344#define GLOBAL_DEFAULT_DEPTH 24
345#endif
346
347Bool
348xf86SetDepthBpp(ScrnInfoPtr scrp, int depth, int dummy, int fbbpp,
349		int depth24flags)
350{
351    int i;
352    DispPtr disp;
353    Pix24Flags pix24 = xf86Info.pixmap24;
354    Bool nomatch = FALSE;
355
356    scrp->bitsPerPixel = -1;
357    scrp->depth = -1;
358    scrp->pixmap24 = Pix24DontCare;
359    scrp->bitsPerPixelFrom = X_DEFAULT;
360    scrp->depthFrom = X_DEFAULT;
361
362    if (xf86FbBpp > 0) {
363	scrp->bitsPerPixel = xf86FbBpp;
364	scrp->bitsPerPixelFrom = X_CMDLINE;
365    }
366
367    if (xf86Depth > 0) {
368	scrp->depth = xf86Depth;
369	scrp->depthFrom = X_CMDLINE;
370    }
371
372    if (xf86FbBpp < 0 && xf86Depth < 0) {
373	if (scrp->confScreen->defaultfbbpp > 0) {
374	    scrp->bitsPerPixel = scrp->confScreen->defaultfbbpp;
375	    scrp->bitsPerPixelFrom = X_CONFIG;
376	}
377	if (scrp->confScreen->defaultdepth > 0) {
378	    scrp->depth = scrp->confScreen->defaultdepth;
379	    scrp->depthFrom = X_CONFIG;
380	}
381
382	if (scrp->confScreen->defaultfbbpp <= 0 &&
383	    scrp->confScreen->defaultdepth <= 0) {
384	    /*
385	     * Check for DefaultDepth and DefaultFbBpp options in the
386	     * Device sections.
387	     */
388	    int i;
389	    GDevPtr device;
390	    Bool found = FALSE;
391
392	    for (i = 0; i < scrp->numEntities; i++) {
393		device = xf86GetDevFromEntity(scrp->entityList[i],
394					      scrp->entityInstanceList[i]);
395		if (device && device->options) {
396		    if (xf86FindOption(device->options, "DefaultDepth")) {
397			scrp->depth = xf86SetIntOption(device->options,
398						       "DefaultDepth", -1);
399			scrp->depthFrom = X_CONFIG;
400			found = TRUE;
401		    }
402		    if (xf86FindOption(device->options, "DefaultFbBpp")) {
403			scrp->bitsPerPixel = xf86SetIntOption(device->options,
404							      "DefaultFbBpp",
405							      -1);
406			scrp->bitsPerPixelFrom = X_CONFIG;
407			found = TRUE;
408		    }
409		}
410		if (found)
411		    break;
412	    }
413	}
414    }
415
416    /* If none of these is set, pick a default */
417    if (scrp->bitsPerPixel < 0 && scrp->depth < 0) {
418        if (fbbpp > 0 || depth > 0) {
419	    if (fbbpp > 0)
420		scrp->bitsPerPixel = fbbpp;
421	    if (depth > 0)
422		scrp->depth = depth;
423	} else {
424	    scrp->depth = GLOBAL_DEFAULT_DEPTH;
425	}
426    }
427
428    /* If any are not given, determine a default for the others */
429
430    if (scrp->bitsPerPixel < 0) {
431	/* The depth must be set */
432	if (scrp->depth > -1) {
433	    if (scrp->depth == 1)
434		scrp->bitsPerPixel = 1;
435	    else if (scrp->depth <= 4)
436		scrp->bitsPerPixel = 4;
437	    else if (scrp->depth <= 8)
438		scrp->bitsPerPixel = 8;
439	    else if (scrp->depth <= 16)
440		scrp->bitsPerPixel = 16;
441	    else if (scrp->depth <= 24) {
442		/*
443		 * Figure out if a choice is possible based on the depth24
444		 * and pix24 flags.
445		 */
446		/* Check pix24 first */
447		if (pix24 != Pix24DontCare) {
448		    if (pix24 == Pix24Use32) {
449			if (DO_PIX32(depth24flags)) {
450			    if (CHOOSE24FOR32(depth24flags))
451				scrp->bitsPerPixel = 24;
452			    else
453				scrp->bitsPerPixel = 32;
454			} else {
455			    nomatch = TRUE;
456			}
457		    } else if (pix24 == Pix24Use24) {
458			if (DO_PIX24(depth24flags)) {
459			    if (CHOOSE32FOR24(depth24flags))
460				scrp->bitsPerPixel = 32;
461			    else
462				scrp->bitsPerPixel = 24;
463			} else {
464			    nomatch = TRUE;
465			}
466		    }
467		} else {
468		    if (DO_PIX32(depth24flags)) {
469			if (CHOOSE24FOR32(depth24flags))
470			    scrp->bitsPerPixel = 24;
471			else
472			    scrp->bitsPerPixel = 32;
473		    } else if (DO_PIX24(depth24flags)) {
474			if (CHOOSE32FOR24(depth24flags))
475			    scrp->bitsPerPixel = 32;
476			else
477			    scrp->bitsPerPixel = 24;
478		    }
479		}
480	    } else if (scrp->depth <= 32)
481		scrp->bitsPerPixel = 32;
482	    else {
483		xf86DrvMsg(scrp->scrnIndex, X_ERROR,
484			   "Specified depth (%d) is greater than 32\n",
485			   scrp->depth);
486		return FALSE;
487	    }
488	} else {
489	    xf86DrvMsg(scrp->scrnIndex, X_ERROR,
490			"xf86SetDepthBpp: internal error: depth and fbbpp"
491			" are both not set\n");
492	    return FALSE;
493	}
494	if (scrp->bitsPerPixel < 0) {
495	    if (nomatch)
496		xf86DrvMsg(scrp->scrnIndex, X_ERROR,
497			"Driver can't support depth 24 pixmap format (%d)\n",
498			PIX24TOBPP(pix24));
499	    else if ((depth24flags & (Support24bppFb | Support32bppFb)) ==
500		     NoDepth24Support)
501		xf86DrvMsg(scrp->scrnIndex, X_ERROR,
502			"Driver can't support depth 24\n");
503	    else
504		xf86DrvMsg(scrp->scrnIndex, X_ERROR,
505			"Can't find fbbpp for depth 24\n");
506	    return FALSE;
507	}
508	scrp->bitsPerPixelFrom = X_PROBED;
509    }
510
511    if (scrp->depth <= 0) {
512	/* bitsPerPixel is already set */
513	switch (scrp->bitsPerPixel) {
514	case 32:
515	    scrp->depth = 24;
516	    break;
517	default:
518	    /* 1, 4, 8, 16 and 24 */
519	    scrp->depth = scrp->bitsPerPixel;
520	    break;
521	}
522	scrp->depthFrom = X_PROBED;
523    }
524
525    /* Sanity checks */
526    if (scrp->depth < 1 || scrp->depth > 32) {
527	xf86DrvMsg(scrp->scrnIndex, X_ERROR,
528		   "Specified depth (%d) is not in the range 1-32\n",
529		    scrp->depth);
530	return FALSE;
531    }
532    switch (scrp->bitsPerPixel) {
533    case 1:
534    case 4:
535    case 8:
536    case 16:
537    case 24:
538    case 32:
539	break;
540    default:
541	xf86DrvMsg(scrp->scrnIndex, X_ERROR,
542		   "Specified fbbpp (%d) is not a permitted value\n",
543		   scrp->bitsPerPixel);
544	return FALSE;
545    }
546    if (scrp->depth > scrp->bitsPerPixel) {
547	xf86DrvMsg(scrp->scrnIndex, X_ERROR,
548		   "Specified depth (%d) is greater than the fbbpp (%d)\n",
549		   scrp->depth, scrp->bitsPerPixel);
550	return FALSE;
551    }
552
553    /* set scrp->pixmap24 if the driver isn't flexible */
554    if (scrp->bitsPerPixel == 24 && !DO_PIX32FOR24(depth24flags)) {
555	scrp->pixmap24 = Pix24Use24;
556    }
557    if (scrp->bitsPerPixel == 32 && !DO_PIX24FOR32(depth24flags)) {
558	scrp->pixmap24 = Pix24Use32;
559    }
560
561    /*
562     * Find the Display subsection matching the depth/fbbpp and initialise
563     * scrp->display with it.
564     */
565    for (i = 0, disp = scrp->confScreen->displays;
566	 i < scrp->confScreen->numdisplays; i++, disp++) {
567	if ((disp->depth == scrp->depth && disp->fbbpp == scrp->bitsPerPixel)
568	    || (disp->depth == scrp->depth && disp->fbbpp <= 0)
569	    || (disp->fbbpp == scrp->bitsPerPixel && disp->depth <= 0)) {
570	    scrp->display = disp;
571	    break;
572	}
573    }
574
575    /*
576     * If an exact match can't be found, see if there is one with no
577     * depth or fbbpp specified.
578     */
579    if (i == scrp->confScreen->numdisplays) {
580	for (i = 0, disp = scrp->confScreen->displays;
581	     i < scrp->confScreen->numdisplays; i++, disp++) {
582	    if (disp->depth <= 0 && disp->fbbpp <= 0) {
583		scrp->display = disp;
584		break;
585	    }
586	}
587    }
588
589    /*
590     * If all else fails, create a default one.
591     */
592    if (i == scrp->confScreen->numdisplays) {
593	scrp->confScreen->numdisplays++;
594	scrp->confScreen->displays =
595		xnfrealloc(scrp->confScreen->displays,
596			   scrp->confScreen->numdisplays * sizeof(DispRec));
597	xf86DrvMsg(scrp->scrnIndex, X_INFO,
598		   "Creating default Display subsection in Screen section\n"
599		   "\t\"%s\" for depth/fbbpp %d/%d\n",
600		   scrp->confScreen->id, scrp->depth, scrp->bitsPerPixel);
601	memset(&scrp->confScreen->displays[i], 0, sizeof(DispRec));
602	scrp->confScreen->displays[i].blackColour.red = -1;
603	scrp->confScreen->displays[i].blackColour.green = -1;
604	scrp->confScreen->displays[i].blackColour.blue = -1;
605	scrp->confScreen->displays[i].whiteColour.red = -1;
606	scrp->confScreen->displays[i].whiteColour.green = -1;
607	scrp->confScreen->displays[i].whiteColour.blue = -1;
608	scrp->confScreen->displays[i].defaultVisual = -1;
609	scrp->confScreen->displays[i].modes = xnfalloc(sizeof(char *));
610	scrp->confScreen->displays[i].modes[0] = NULL;
611	scrp->confScreen->displays[i].depth = depth;
612	scrp->confScreen->displays[i].fbbpp = fbbpp;
613	scrp->display = &scrp->confScreen->displays[i];
614    }
615
616    /*
617     * Setup defaults for the display-wide attributes the framebuffer will
618     * need.  These defaults should eventually be set globally, and not
619     * dependent on the screens.
620     */
621    scrp->imageByteOrder = IMAGE_BYTE_ORDER;
622    scrp->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
623    if (scrp->depth < 8) {
624	/* Planar modes need these settings */
625	scrp->bitmapScanlineUnit = 8;
626	scrp->bitmapBitOrder = MSBFirst;
627    } else {
628	scrp->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
629	scrp->bitmapBitOrder = BITMAP_BIT_ORDER;
630    }
631
632    /*
633     * If an unusual depth is required, add it to scrp->formats.  The formats
634     * for the common depths are handled globally in InitOutput
635     */
636    switch (scrp->depth) {
637    case 1:
638    case 4:
639    case 8:
640    case 15:
641    case 16:
642    case 24:
643	/* Common depths.  Nothing to do for them */
644	break;
645    default:
646	if (!xf86AddPixFormat(scrp, scrp->depth, 0, 0)) {
647	    xf86DrvMsg(scrp->scrnIndex, X_ERROR,
648		       "Can't add pixmap format for depth %d\n", scrp->depth);
649	    return FALSE;
650	}
651    }
652
653    /* Initialise the framebuffer format for this screen */
654    scrp->fbFormat.depth = scrp->depth;
655    scrp->fbFormat.bitsPerPixel = scrp->bitsPerPixel;
656    scrp->fbFormat.scanlinePad = BITMAP_SCANLINE_PAD;
657
658    return TRUE;
659}
660
661/*
662 * Print out the selected depth and bpp.
663 */
664void
665xf86PrintDepthBpp(ScrnInfoPtr scrp)
666{
667    xf86DrvMsg(scrp->scrnIndex, scrp->depthFrom, "Depth %d, ", scrp->depth);
668    xf86Msg(scrp->bitsPerPixelFrom, "framebuffer bpp %d\n", scrp->bitsPerPixel);
669}
670
671/*
672 * xf86SetWeight sets scrp->weight, scrp->mask, scrp->offset, and for depths
673 * greater than MAX_PSEUDO_DEPTH also scrp->rgbBits.
674 */
675Bool
676xf86SetWeight(ScrnInfoPtr scrp, rgb weight, rgb mask)
677{
678    MessageType weightFrom = X_DEFAULT;
679
680    scrp->weight.red = 0;
681    scrp->weight.green = 0;
682    scrp->weight.blue = 0;
683
684    if (xf86Weight.red > 0 && xf86Weight.green > 0 && xf86Weight.blue > 0) {
685	scrp->weight = xf86Weight;
686	weightFrom = X_CMDLINE;
687    } else if (scrp->display->weight.red > 0 && scrp->display->weight.green > 0
688	       && scrp->display->weight.blue > 0) {
689	scrp->weight = scrp->display->weight;
690	weightFrom = X_CONFIG;
691    } else if (weight.red > 0 && weight.green > 0 && weight.blue > 0) {
692	scrp->weight = weight;
693    } else {
694	switch (scrp->depth) {
695	case 1:
696	case 4:
697	case 8:
698	    scrp->weight.red = scrp->weight.green =
699		scrp->weight.blue = scrp->rgbBits;
700	    break;
701	case 15:
702	    scrp->weight.red = scrp->weight.green = scrp->weight.blue = 5;
703	    break;
704	case 16:
705	    scrp->weight.red = scrp->weight.blue = 5;
706	    scrp->weight.green = 6;
707	    break;
708	case 18:
709	    scrp->weight.red = scrp->weight.green = scrp->weight.blue = 6;
710	    break;
711	case 24:
712	    scrp->weight.red = scrp->weight.green = scrp->weight.blue = 8;
713	    break;
714	case 30:
715	    scrp->weight.red = scrp->weight.green = scrp->weight.blue = 10;
716	    break;
717	}
718    }
719
720    if (scrp->weight.red)
721	xf86DrvMsg(scrp->scrnIndex, weightFrom, "RGB weight %d%d%d\n",
722		   (int)scrp->weight.red, (int)scrp->weight.green,
723		   (int)scrp->weight.blue);
724
725    if (scrp->depth > MAX_PSEUDO_DEPTH &&
726	(scrp->depth != scrp->weight.red + scrp->weight.green +
727			scrp->weight.blue)) {
728	xf86DrvMsg(scrp->scrnIndex, X_ERROR,
729		   "Weight given (%d%d%d) is inconsistent with the "
730		   "depth (%d)\n",
731		   (int)scrp->weight.red, (int)scrp->weight.green,
732		   (int)scrp->weight.blue, scrp->depth);
733	return FALSE;
734    }
735    if (scrp->depth > MAX_PSEUDO_DEPTH && scrp->weight.red) {
736	/*
737	 * XXX Does this even mean anything for TrueColor visuals?
738	 * If not, we shouldn't even be setting it here.  However, this
739	 * matches the behaviour of 3.x versions of XFree86.
740	 */
741	scrp->rgbBits = scrp->weight.red;
742	if (scrp->weight.green > scrp->rgbBits)
743	    scrp->rgbBits = scrp->weight.green;
744	if (scrp->weight.blue > scrp->rgbBits)
745	    scrp->rgbBits = scrp->weight.blue;
746    }
747
748    /* Set the mask and offsets */
749    if (mask.red == 0 || mask.green == 0 || mask.blue == 0) {
750	/* Default to a setting common to PC hardware */
751	scrp->offset.red = scrp->weight.green + scrp->weight.blue;
752	scrp->offset.green = scrp->weight.blue;
753	scrp->offset.blue = 0;
754	scrp->mask.red = ((1 << scrp->weight.red) - 1) << scrp->offset.red;
755	scrp->mask.green = ((1 << scrp->weight.green) - 1)
756				<< scrp->offset.green;
757	scrp->mask.blue = (1 << scrp->weight.blue) - 1;
758    } else {
759	/* Initialise to the values passed */
760	scrp->mask.red = mask.red;
761	scrp->mask.green = mask.green;
762	scrp->mask.blue = mask.blue;
763	scrp->offset.red = ffs(mask.red);
764	scrp->offset.green = ffs(mask.green);
765	scrp->offset.blue = ffs(mask.blue);
766    }
767    return TRUE;
768}
769
770Bool
771xf86SetDefaultVisual(ScrnInfoPtr scrp, int visual)
772{
773    MessageType visualFrom = X_DEFAULT;
774
775    if (defaultColorVisualClass >= 0) {
776	scrp->defaultVisual = defaultColorVisualClass;
777	visualFrom = X_CMDLINE;
778    } else if (scrp->display->defaultVisual >= 0) {
779	scrp->defaultVisual = scrp->display->defaultVisual;
780	visualFrom = X_CONFIG;
781    } else if (visual >= 0) {
782	scrp->defaultVisual = visual;
783    } else {
784	if (scrp->depth == 1)
785	    scrp->defaultVisual = StaticGray;
786	else if (scrp->depth == 4)
787	    scrp->defaultVisual = StaticColor;
788	else if (scrp->depth <= MAX_PSEUDO_DEPTH)
789	    scrp->defaultVisual = PseudoColor;
790	else
791	    scrp->defaultVisual = TrueColor;
792    }
793    switch (scrp->defaultVisual) {
794    case StaticGray:
795    case GrayScale:
796    case StaticColor:
797    case PseudoColor:
798    case TrueColor:
799    case DirectColor:
800	xf86DrvMsg(scrp->scrnIndex, visualFrom, "Default visual is %s\n",
801		   xf86VisualNames[scrp->defaultVisual]);
802	    return TRUE;
803    default:
804
805	xf86DrvMsg(scrp->scrnIndex, X_ERROR,
806		   "Invalid default visual class (%d)\n", scrp->defaultVisual);
807	return FALSE;
808    }
809}
810
811#define TEST_GAMMA(g) \
812	(g).red > GAMMA_ZERO || (g).green > GAMMA_ZERO || (g).blue > GAMMA_ZERO
813
814#define SET_GAMMA(g) \
815	(g) > GAMMA_ZERO ? (g) : 1.0
816
817Bool
818xf86SetGamma(ScrnInfoPtr scrp, Gamma gamma)
819{
820    MessageType from = X_DEFAULT;
821#if 0
822    xf86MonPtr DDC = (xf86MonPtr)(scrp->monitor->DDC);
823#endif
824    if (TEST_GAMMA(xf86Gamma)) {
825	from = X_CMDLINE;
826	scrp->gamma.red = SET_GAMMA(xf86Gamma.red);
827	scrp->gamma.green = SET_GAMMA(xf86Gamma.green);
828	scrp->gamma.blue = SET_GAMMA(xf86Gamma.blue);
829    } else if (TEST_GAMMA(scrp->monitor->gamma)) {
830	from = X_CONFIG;
831	scrp->gamma.red = SET_GAMMA(scrp->monitor->gamma.red);
832	scrp->gamma.green = SET_GAMMA(scrp->monitor->gamma.green);
833	scrp->gamma.blue = SET_GAMMA(scrp->monitor->gamma.blue);
834#if 0
835    } else if ( DDC && DDC->features.gamma > GAMMA_ZERO ) {
836        from = X_PROBED;
837	scrp->gamma.red = SET_GAMMA(DDC->features.gamma);
838	scrp->gamma.green = SET_GAMMA(DDC->features.gamma);
839	scrp->gamma.blue = SET_GAMMA(DDC->features.gamma);
840	/* EDID structure version 2 gives optional seperate red, green & blue gamma values
841	 * in bytes 0x57-0x59 */
842#endif
843    } else if (TEST_GAMMA(gamma)) {
844	scrp->gamma.red = SET_GAMMA(gamma.red);
845	scrp->gamma.green = SET_GAMMA(gamma.green);
846	scrp->gamma.blue = SET_GAMMA(gamma.blue);
847    } else {
848	scrp->gamma.red = 1.0;
849	scrp->gamma.green = 1.0;
850	scrp->gamma.blue = 1.0;
851    }
852    /* Pretend we succeeded if we support better a gamma system.
853     * This avoids a confusing message.
854     */
855    if (xf86_crtc_supports_gamma(scrp))
856	return TRUE;
857    xf86DrvMsg(scrp->scrnIndex, from,
858	       "Using gamma correction (%.1f, %.1f, %.1f)\n",
859	       scrp->gamma.red, scrp->gamma.green, scrp->gamma.blue);
860
861    return TRUE;
862}
863
864#undef TEST_GAMMA
865#undef SET_GAMMA
866
867
868/*
869 * Set the DPI from the command line option.  XXX should allow it to be
870 * calculated from the widthmm/heightmm values.
871 */
872
873#undef MMPERINCH
874#define MMPERINCH 25.4
875
876void
877xf86SetDpi(ScrnInfoPtr pScrn, int x, int y)
878{
879    MessageType from = X_DEFAULT;
880    xf86MonPtr DDC = (xf86MonPtr)(pScrn->monitor->DDC);
881    int ddcWidthmm, ddcHeightmm;
882    int widthErr, heightErr;
883
884    /* XXX Maybe there is no need for widthmm/heightmm in ScrnInfoRec */
885    pScrn->widthmm = pScrn->monitor->widthmm;
886    pScrn->heightmm = pScrn->monitor->heightmm;
887
888    if (DDC && (DDC->features.hsize > 0 && DDC->features.vsize > 0) ) {
889      /* DDC gives display size in mm for individual modes,
890       * but cm for monitor
891       */
892      ddcWidthmm = DDC->features.hsize * 10; /* 10mm in 1cm */
893      ddcHeightmm = DDC->features.vsize * 10; /* 10mm in 1cm */
894    } else {
895      ddcWidthmm = ddcHeightmm = 0;
896    }
897
898    if (monitorResolution > 0) {
899	pScrn->xDpi = monitorResolution;
900	pScrn->yDpi = monitorResolution;
901	from = X_CMDLINE;
902    } else if (pScrn->widthmm > 0 || pScrn->heightmm > 0) {
903	from = X_CONFIG;
904	if (pScrn->widthmm > 0) {
905	   pScrn->xDpi =
906		(int)((double)pScrn->virtualX * MMPERINCH / pScrn->widthmm);
907	}
908	if (pScrn->heightmm > 0) {
909	   pScrn->yDpi =
910		(int)((double)pScrn->virtualY * MMPERINCH / pScrn->heightmm);
911	}
912	if (pScrn->xDpi > 0 && pScrn->yDpi <= 0)
913	    pScrn->yDpi = pScrn->xDpi;
914	if (pScrn->yDpi > 0 && pScrn->xDpi <= 0)
915	    pScrn->xDpi = pScrn->yDpi;
916	xf86DrvMsg(pScrn->scrnIndex, from, "Display dimensions: (%d, %d) mm\n",
917		   pScrn->widthmm, pScrn->heightmm);
918
919	/* Warn if config and probe disagree about display size */
920	if ( ddcWidthmm && ddcHeightmm ) {
921	  if (pScrn->widthmm > 0) {
922	    widthErr  = abs(ddcWidthmm  - pScrn->widthmm);
923	  } else {
924	    widthErr  = 0;
925	  }
926	  if (pScrn->heightmm > 0) {
927	    heightErr = abs(ddcHeightmm - pScrn->heightmm);
928	  } else {
929	    heightErr = 0;
930	  }
931	  if (widthErr>10 || heightErr>10) {
932	    /* Should include config file name for monitor here */
933	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
934		       "Probed monitor is %dx%d mm, using Displaysize %dx%d mm\n",
935		       ddcWidthmm,ddcHeightmm, pScrn->widthmm,pScrn->heightmm);
936	  }
937	}
938    } else if ( ddcWidthmm && ddcHeightmm ) {
939	from = X_PROBED;
940	xf86DrvMsg(pScrn->scrnIndex, from, "Display dimensions: (%d, %d) mm\n",
941		   ddcWidthmm, ddcHeightmm );
942	pScrn->widthmm = ddcWidthmm;
943	pScrn->heightmm = ddcHeightmm;
944	if (pScrn->widthmm > 0) {
945	   pScrn->xDpi =
946		(int)((double)pScrn->virtualX * MMPERINCH / pScrn->widthmm);
947	}
948	if (pScrn->heightmm > 0) {
949	   pScrn->yDpi =
950		(int)((double)pScrn->virtualY * MMPERINCH / pScrn->heightmm);
951	}
952	if (pScrn->xDpi > 0 && pScrn->yDpi <= 0)
953	    pScrn->yDpi = pScrn->xDpi;
954	if (pScrn->yDpi > 0 && pScrn->xDpi <= 0)
955	    pScrn->xDpi = pScrn->yDpi;
956    } else {
957	if (x > 0)
958	    pScrn->xDpi = x;
959	else
960	    pScrn->xDpi = DEFAULT_DPI;
961	if (y > 0)
962	    pScrn->yDpi = y;
963	else
964	    pScrn->yDpi = DEFAULT_DPI;
965    }
966    xf86DrvMsg(pScrn->scrnIndex, from, "DPI set to (%d, %d)\n",
967	       pScrn->xDpi, pScrn->yDpi);
968}
969
970#undef MMPERINCH
971
972
973void
974xf86SetBlackWhitePixels(ScreenPtr pScreen)
975{
976    if (xf86FlipPixels) {
977	pScreen->whitePixel = 0;
978	pScreen->blackPixel = 1;
979    } else {
980	pScreen->whitePixel = 1;
981	pScreen->blackPixel = 0;
982    }
983}
984
985/*
986 * xf86SetRootClip --
987 *	Enable or disable rendering to the screen by
988 *	setting the root clip list and revalidating
989 *	all of the windows
990 */
991
992static void
993xf86SetRootClip (ScreenPtr pScreen, Bool enable)
994{
995    WindowPtr	pWin = pScreen->root;
996    WindowPtr	pChild;
997    Bool	WasViewable = (Bool)(pWin->viewable);
998    Bool	anyMarked = FALSE;
999    WindowPtr   pLayerWin;
1000    BoxRec	box;
1001
1002    if (WasViewable)
1003    {
1004	for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
1005	{
1006	    (void) (*pScreen->MarkOverlappedWindows)(pChild,
1007						     pChild,
1008						     &pLayerWin);
1009	}
1010	(*pScreen->MarkWindow) (pWin);
1011	anyMarked = TRUE;
1012	if (pWin->valdata)
1013	{
1014	    if (HasBorder (pWin))
1015	    {
1016		RegionPtr	borderVisible;
1017
1018		borderVisible = RegionCreate(NullBox, 1);
1019		RegionSubtract(borderVisible,
1020				&pWin->borderClip, &pWin->winSize);
1021		pWin->valdata->before.borderVisible = borderVisible;
1022	    }
1023	    pWin->valdata->before.resized = TRUE;
1024	}
1025    }
1026
1027    /*
1028     * Use REGION_BREAK to avoid optimizations in ValidateTree
1029     * that assume the root borderClip can't change well, normally
1030     * it doesn't...)
1031     */
1032    if (enable)
1033    {
1034	box.x1 = 0;
1035	box.y1 = 0;
1036	box.x2 = pScreen->width;
1037	box.y2 = pScreen->height;
1038	RegionInit(&pWin->winSize, &box, 1);
1039	RegionInit(&pWin->borderSize, &box, 1);
1040	if (WasViewable)
1041	    RegionReset(&pWin->borderClip, &box);
1042	pWin->drawable.width = pScreen->width;
1043	pWin->drawable.height = pScreen->height;
1044        RegionBreak(&pWin->clipList);
1045    }
1046    else
1047    {
1048	RegionEmpty(&pWin->borderClip);
1049	RegionBreak(&pWin->clipList);
1050    }
1051
1052    ResizeChildrenWinSize (pWin, 0, 0, 0, 0);
1053
1054    if (WasViewable)
1055    {
1056	if (pWin->firstChild)
1057	{
1058	    anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin->firstChild,
1059							   pWin->firstChild,
1060							   (WindowPtr *)NULL);
1061	}
1062	else
1063	{
1064	    (*pScreen->MarkWindow) (pWin);
1065	    anyMarked = TRUE;
1066	}
1067
1068
1069	if (anyMarked)
1070	    (*pScreen->ValidateTree)(pWin, NullWindow, VTOther);
1071    }
1072
1073    if (WasViewable)
1074    {
1075	if (anyMarked)
1076	    (*pScreen->HandleExposures)(pWin);
1077	if (anyMarked && pScreen->PostValidateTree)
1078	    (*pScreen->PostValidateTree)(pWin, NullWindow, VTOther);
1079    }
1080    if (pWin->realized)
1081	WindowsRestructured ();
1082    FlushAllOutput ();
1083}
1084
1085/*
1086 * Function to enable/disable access to the frame buffer
1087 *
1088 * This is used when VT switching and when entering/leaving DGA direct mode.
1089 *
1090 * This has been rewritten again to eliminate the saved pixmap.  The
1091 * devPrivate field in the screen pixmap is set to NULL to catch code
1092 * accidentally referencing the frame buffer while the X server is not
1093 * supposed to touch it.
1094 *
1095 * Here, we exchange the pixmap private data, rather than the pixmaps
1096 * themselves to avoid having to find and change any references to the screen
1097 * pixmap such as GC's, window privates etc.  This also means that this code
1098 * does not need to know exactly how the pixmap pixels are accessed.  Further,
1099 * this exchange is >not< done through the screen's ModifyPixmapHeader()
1100 * vector.  This means the called frame buffer code layers can determine
1101 * whether they are switched in or out by keeping track of the root pixmap's
1102 * private data, and therefore don't need to access pScrnInfo->vtSema.
1103 */
1104void
1105xf86EnableDisableFBAccess(int scrnIndex, Bool enable)
1106{
1107    ScrnInfoPtr pScrnInfo = xf86Screens[scrnIndex];
1108    ScreenPtr pScreen = pScrnInfo->pScreen;
1109    PixmapPtr pspix;
1110
1111    pspix = (*pScreen->GetScreenPixmap) (pScreen);
1112    if (enable)
1113    {
1114	/*
1115	 * Restore all of the clip lists on the screen
1116	 */
1117	if (!xf86Resetting)
1118	    xf86SetRootClip (pScreen, TRUE);
1119
1120    }
1121    else
1122    {
1123	/*
1124	 * Empty all of the clip lists on the screen
1125	 */
1126	xf86SetRootClip (pScreen, FALSE);
1127    }
1128}
1129
1130/* Print driver messages in the standard format */
1131
1132#undef PREFIX_SIZE
1133#define PREFIX_SIZE 14
1134
1135void
1136xf86VDrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format,
1137		va_list args)
1138{
1139    char *tmpFormat;
1140
1141    /* Prefix the scrnIndex name to the format string. */
1142    if (scrnIndex >= 0 && scrnIndex < xf86NumScreens &&
1143	xf86Screens[scrnIndex]->name) {
1144	tmpFormat = malloc(strlen(format) +
1145			   strlen(xf86Screens[scrnIndex]->name) +
1146			   PREFIX_SIZE + 1);
1147	if (!tmpFormat)
1148	    return;
1149
1150	snprintf(tmpFormat, PREFIX_SIZE + 1, "%s(%d): ",
1151		 xf86Screens[scrnIndex]->name, scrnIndex);
1152
1153	strcat(tmpFormat, format);
1154	LogVMessageVerb(type, verb, tmpFormat, args);
1155	free(tmpFormat);
1156    } else
1157	LogVMessageVerb(type, verb, format, args);
1158}
1159#undef PREFIX_SIZE
1160
1161/* Print driver messages, with verbose level specified directly */
1162void
1163xf86DrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format,
1164	       ...)
1165{
1166    va_list ap;
1167
1168    va_start(ap, format);
1169    xf86VDrvMsgVerb(scrnIndex, type, verb, format, ap);
1170    va_end(ap);
1171}
1172
1173/* Print driver messages, with verbose level of 1 (default) */
1174void
1175xf86DrvMsg(int scrnIndex, MessageType type, const char *format, ...)
1176{
1177    va_list ap;
1178
1179    va_start(ap, format);
1180    xf86VDrvMsgVerb(scrnIndex, type, 1, format, ap);
1181    va_end(ap);
1182}
1183
1184/* Print input driver messages in the standard format of
1185   <driver>: <device name>: <message> */
1186void
1187xf86VIDrvMsgVerb(InputInfoPtr dev, MessageType type, int verb, const char *format,
1188		 va_list args)
1189{
1190    char *msg;
1191
1192    if (asprintf(&msg, "%s: %s: %s", dev->drv->driverName, dev->name, format)
1193	== -1) {
1194	LogVMessageVerb(type, verb, "%s", args);
1195    } else {
1196	LogVMessageVerb(type, verb, msg, args);
1197	free(msg);
1198    }
1199}
1200
1201/* Print input driver message, with verbose level specified directly */
1202void
1203xf86IDrvMsgVerb(InputInfoPtr dev, MessageType type, int verb, const char *format,
1204	       ...)
1205{
1206    va_list ap;
1207
1208    va_start(ap, format);
1209    xf86VIDrvMsgVerb(dev, type, verb, format, ap);
1210    va_end(ap);
1211}
1212
1213/* Print input driver messages, with verbose level of 1 (default) */
1214void
1215xf86IDrvMsg(InputInfoPtr dev, MessageType type, const char *format, ...)
1216{
1217    va_list ap;
1218
1219    va_start(ap, format);
1220    xf86VIDrvMsgVerb(dev, type, 1, format, ap);
1221    va_end(ap);
1222}
1223
1224
1225/* Print non-driver messages with verbose level specified directly */
1226void
1227xf86MsgVerb(MessageType type, int verb, const char *format, ...)
1228{
1229    va_list ap;
1230
1231    va_start(ap, format);
1232    LogVMessageVerb(type, verb, format, ap);
1233    va_end(ap);
1234}
1235
1236/* Print non-driver messages with verbose level of 1 (default) */
1237void
1238xf86Msg(MessageType type, const char *format, ...)
1239{
1240    va_list ap;
1241
1242    va_start(ap, format);
1243    LogVMessageVerb(type, 1, format, ap);
1244    va_end(ap);
1245}
1246
1247/* Just like ErrorF, but with the verbose level checked */
1248void
1249xf86ErrorFVerb(int verb, const char *format, ...)
1250{
1251    va_list ap;
1252
1253    va_start(ap, format);
1254    if (xf86Verbose >= verb || xf86LogVerbose >= verb)
1255	LogVWrite(verb, format, ap);
1256    va_end(ap);
1257}
1258
1259/* Like xf86ErrorFVerb, but with an implied verbose level of 1 */
1260void
1261xf86ErrorF(const char *format, ...)
1262{
1263    va_list ap;
1264
1265    va_start(ap, format);
1266    if (xf86Verbose >= 1 || xf86LogVerbose >= 1)
1267	LogVWrite(1, format, ap);
1268    va_end(ap);
1269}
1270
1271
1272void
1273xf86LogInit(void)
1274{
1275    char *lf = NULL;
1276
1277#define LOGSUFFIX ".log"
1278#define LOGOLDSUFFIX ".old"
1279
1280    /* Get the log file name */
1281    if (xf86LogFileFrom == X_DEFAULT) {
1282	/* Append the display number and ".log" */
1283	if (asprintf(&lf, "%s%%s" LOGSUFFIX, xf86LogFile) == -1)
1284	    FatalError("Cannot allocate space for the log file name\n");
1285	xf86LogFile = lf;
1286    }
1287
1288    xf86LogFile = LogInit(xf86LogFile, LOGOLDSUFFIX);
1289    xf86LogFileWasOpened = TRUE;
1290
1291    xf86SetVerbosity(xf86Verbose);
1292    xf86SetLogVerbosity(xf86LogVerbose);
1293
1294#undef LOGSUFFIX
1295#undef LOGOLDSUFFIX
1296
1297    free(lf);
1298}
1299
1300void
1301xf86CloseLog(void)
1302{
1303    LogClose();
1304}
1305
1306
1307/*
1308 * Drivers can use these for using their own SymTabRecs.
1309 */
1310
1311const char *
1312xf86TokenToString(SymTabPtr table, int token)
1313{
1314    int i;
1315
1316    for (i = 0; table[i].token >= 0 && table[i].token != token; i++)
1317	;
1318
1319    if (table[i].token < 0)
1320	return NULL;
1321    else
1322	return table[i].name;
1323}
1324
1325int
1326xf86StringToToken(SymTabPtr table, const char *string)
1327{
1328    int i;
1329
1330    if (string == NULL)
1331	return -1;
1332
1333    for (i = 0; table[i].token >= 0 && xf86NameCmp(string, table[i].name); i++)
1334	;
1335
1336    return table[i].token;
1337}
1338
1339/*
1340 * helper to display the clocks found on a card
1341 */
1342void
1343xf86ShowClocks(ScrnInfoPtr scrp, MessageType from)
1344{
1345    int j;
1346
1347    xf86DrvMsg(scrp->scrnIndex, from, "Pixel clocks available:");
1348    for (j=0; j < scrp->numClocks; j++) {
1349	if ((j % 4) == 0) {
1350	    xf86ErrorF("\n");
1351	    xf86DrvMsg(scrp->scrnIndex, from, "pixel clocks:");
1352	}
1353	xf86ErrorF(" %7.3f", (double)scrp->clock[j] / 1000.0);
1354    }
1355    xf86ErrorF("\n");
1356}
1357
1358
1359/*
1360 * This prints out the driver identify message, including the names of
1361 * the supported chipsets.
1362 *
1363 * XXX This makes assumptions about the line width, etc.  Maybe we could
1364 * use a more general "pretty print" function for messages.
1365 */
1366void
1367xf86PrintChipsets(const char *drvname, const char *drvmsg, SymTabPtr chips)
1368{
1369    int len, i;
1370
1371    len = 6 + strlen(drvname) + 2 + strlen(drvmsg) + 2;
1372    xf86Msg(X_INFO, "%s: %s:", drvname, drvmsg);
1373    for (i = 0; chips[i].name != NULL; i++) {
1374	if (i != 0) {
1375	    xf86ErrorF(",");
1376	    len++;
1377	}
1378	if (len + 2 + strlen(chips[i].name) < 78) {
1379	    xf86ErrorF(" ");
1380	    len++;
1381	} else {
1382	    xf86ErrorF("\n\t");
1383	    len = 8;
1384	}
1385	xf86ErrorF("%s", chips[i].name);
1386	len += strlen(chips[i].name);
1387    }
1388    xf86ErrorF("\n");
1389}
1390
1391
1392int
1393xf86MatchDevice(const char *drivername, GDevPtr **sectlist)
1394{
1395    GDevPtr       gdp, *pgdp = NULL;
1396    confScreenPtr screensecptr;
1397    int i,j;
1398
1399    if (sectlist)
1400	*sectlist = NULL;
1401
1402    /*
1403     * 20111009 jmcneill: This line was removed with the following commit upstream:
1404     *  http://cgit.freedesktop.org/xorg/xserver/commit/hw/xfree86/common/xf86Helper.c?id=0ceac6f64f5ad9bc2ac4b19be2dd245ffba78b05
1405     *
1406     * However, the log message is inaccurate: xf86MatchDevice will get called at
1407     * configuration time by drivers who still implement the legacy probing
1408     * API.
1409     */
1410    if (xf86DoConfigure && xf86DoConfigurePass1) return 1;
1411
1412    /*
1413     * This can happen when running Xorg -showopts and a module like ati
1414     * or vmware tries to load its submodules when xf86ConfigLayout is empty
1415     */
1416    if (!xf86ConfigLayout.screens)
1417	return 0;
1418
1419    /*
1420     * This is a very important function that matches the device sections
1421     * as they show up in the config file with the drivers that the server
1422     * loads at run time.
1423     *
1424     * ChipProbe can call
1425     * int xf86MatchDevice(char * drivername, GDevPtr ** sectlist)
1426     * with its driver name. The function allocates an array of GDevPtr and
1427     * returns this via sectlist and returns the number of elements in
1428     * this list as return value. 0 means none found, -1 means fatal error.
1429     *
1430     * It can figure out which of the Device sections to use for which card
1431     * (using things like the Card statement, etc). For single headed servers
1432     * there will of course be just one such Device section.
1433     */
1434    i = 0;
1435
1436    /*
1437     * first we need to loop over all the Screens sections to get to all
1438     * 'active' device sections
1439     */
1440    for (j=0; xf86ConfigLayout.screens[j].screen != NULL; j++) {
1441        screensecptr = xf86ConfigLayout.screens[j].screen;
1442        if ((screensecptr->device->driver != NULL)
1443            && (xf86NameCmp( screensecptr->device->driver,drivername) == 0)
1444            && (! screensecptr->device->claimed)) {
1445            /*
1446             * we have a matching driver that wasn't claimed, yet
1447             */
1448            pgdp = xnfrealloc(pgdp, (i + 2) * sizeof(GDevPtr));
1449            pgdp[i++] = screensecptr->device;
1450        }
1451    }
1452
1453    /* Then handle the inactive devices */
1454    j = 0;
1455    while (xf86ConfigLayout.inactives[j].identifier) {
1456	gdp = &xf86ConfigLayout.inactives[j];
1457	if (gdp->driver && !gdp->claimed &&
1458	    !xf86NameCmp(gdp->driver,drivername)) {
1459	    /* we have a matching driver that wasn't claimed yet */
1460	    pgdp = xnfrealloc(pgdp, (i + 2) * sizeof(GDevPtr));
1461	    pgdp[i++] = gdp;
1462	}
1463	j++;
1464    }
1465
1466    /*
1467     * make the array NULL terminated and return its address
1468     */
1469    if (i)
1470        pgdp[i] = NULL;
1471
1472    if (sectlist)
1473	*sectlist = pgdp;
1474    else
1475	free(pgdp);
1476    return i;
1477}
1478
1479/*
1480 * xf86GetClocks -- get the dot-clocks via a BIG BAD hack ...
1481 */
1482void
1483xf86GetClocks(ScrnInfoPtr pScrn, int num, Bool (*ClockFunc)(ScrnInfoPtr, int),
1484	      void (*ProtectRegs)(ScrnInfoPtr, Bool),
1485	      void (*BlankScreen)(ScrnInfoPtr, Bool), IOADDRESS vertsyncreg,
1486	      int maskval, int knownclkindex, int knownclkvalue)
1487{
1488    register int status = vertsyncreg;
1489    unsigned long i, cnt, rcnt, sync;
1490
1491    /* First save registers that get written on */
1492    (*ClockFunc)(pScrn, CLK_REG_SAVE);
1493
1494    if (num > MAXCLOCKS)
1495	num = MAXCLOCKS;
1496
1497    for (i = 0; i < num; i++)
1498    {
1499	if (ProtectRegs)
1500	    (*ProtectRegs)(pScrn, TRUE);
1501	if (!(*ClockFunc)(pScrn, i))
1502	{
1503	    pScrn->clock[i] = -1;
1504	    continue;
1505	}
1506	if (ProtectRegs)
1507	    (*ProtectRegs)(pScrn, FALSE);
1508	if (BlankScreen)
1509	    (*BlankScreen)(pScrn, FALSE);
1510
1511    	usleep(50000);     /* let VCO stabilise */
1512
1513    	cnt  = 0;
1514    	sync = 200000;
1515
1516	while ((inb(status) & maskval) == 0x00)
1517	    if (sync-- == 0) goto finish;
1518	/* Something appears to be happening, so reset sync count */
1519	sync = 200000;
1520	while ((inb(status) & maskval) == maskval)
1521	    if (sync-- == 0) goto finish;
1522	/* Something appears to be happening, so reset sync count */
1523	sync = 200000;
1524	while ((inb(status) & maskval) == 0x00)
1525	    if (sync-- == 0) goto finish;
1526
1527	for (rcnt = 0; rcnt < 5; rcnt++)
1528	{
1529	    while (!(inb(status) & maskval))
1530		cnt++;
1531	    while ((inb(status) & maskval))
1532		cnt++;
1533	}
1534
1535finish:
1536	pScrn->clock[i] = cnt ? cnt : -1;
1537	if (BlankScreen)
1538            (*BlankScreen)(pScrn, TRUE);
1539    }
1540
1541    for (i = 0; i < num; i++)
1542    {
1543	if (i != knownclkindex)
1544	{
1545	    if (pScrn->clock[i] == -1)
1546	    {
1547		pScrn->clock[i] = 0;
1548	    }
1549	    else
1550	    {
1551		pScrn->clock[i] = (int)(0.5 +
1552                    (((float)knownclkvalue) * pScrn->clock[knownclkindex]) /
1553	            (pScrn->clock[i]));
1554		/* Round to nearest 10KHz */
1555		pScrn->clock[i] += 5;
1556		pScrn->clock[i] /= 10;
1557		pScrn->clock[i] *= 10;
1558	    }
1559	}
1560    }
1561
1562    pScrn->clock[knownclkindex] = knownclkvalue;
1563    pScrn->numClocks = num;
1564
1565    /* Restore registers that were written on */
1566    (*ClockFunc)(pScrn, CLK_REG_RESTORE);
1567}
1568
1569const char *
1570xf86GetVisualName(int visual)
1571{
1572    if (visual < 0 || visual > DirectColor)
1573	return NULL;
1574
1575    return xf86VisualNames[visual];
1576}
1577
1578
1579int
1580xf86GetVerbosity(void)
1581{
1582    return max(xf86Verbose, xf86LogVerbose);
1583}
1584
1585Pix24Flags
1586xf86GetPix24(void)
1587{
1588    return xf86Info.pixmap24;
1589}
1590
1591
1592int
1593xf86GetDepth(void)
1594{
1595    return xf86Depth;
1596}
1597
1598
1599rgb
1600xf86GetWeight(void)
1601{
1602    return xf86Weight;
1603}
1604
1605
1606Gamma
1607xf86GetGamma(void)
1608{
1609    return xf86Gamma;
1610}
1611
1612
1613Bool
1614xf86GetFlipPixels(void)
1615{
1616    return xf86FlipPixels;
1617}
1618
1619
1620const char *
1621xf86GetServerName(void)
1622{
1623    return xf86ServerName;
1624}
1625
1626
1627Bool
1628xf86ServerIsExiting(void)
1629{
1630    return (dispatchException & DE_TERMINATE) == DE_TERMINATE;
1631}
1632
1633
1634Bool
1635xf86ServerIsResetting(void)
1636{
1637    return xf86Resetting;
1638}
1639
1640
1641Bool
1642xf86ServerIsInitialising(void)
1643{
1644    return xf86Initialising;
1645}
1646
1647
1648Bool
1649xf86ServerIsOnlyDetecting(void)
1650{
1651    return xf86DoConfigure;
1652}
1653
1654
1655Bool
1656xf86CaughtSignal(void)
1657{
1658    return xf86Info.caughtSignal;
1659}
1660
1661
1662Bool
1663xf86GetVidModeAllowNonLocal(void)
1664{
1665    return xf86Info.vidModeAllowNonLocal;
1666}
1667
1668
1669Bool
1670xf86GetVidModeEnabled(void)
1671{
1672    return xf86Info.vidModeEnabled;
1673}
1674
1675Bool
1676xf86GetModInDevAllowNonLocal(void)
1677{
1678    return xf86Info.miscModInDevAllowNonLocal;
1679}
1680
1681
1682Bool
1683xf86GetModInDevEnabled(void)
1684{
1685    return xf86Info.miscModInDevEnabled;
1686}
1687
1688
1689Bool
1690xf86GetAllowMouseOpenFail(void)
1691{
1692    return xf86Info.allowMouseOpenFail;
1693}
1694
1695
1696Bool
1697xf86IsPc98(void)
1698{
1699#if SUPPORT_PC98
1700    return xf86Info.pc98;
1701#else
1702    return FALSE;
1703#endif
1704}
1705
1706void
1707xf86DisableRandR(void)
1708{
1709    xf86Info.disableRandR = TRUE;
1710    xf86Info.randRFrom = X_PROBED;
1711}
1712
1713CARD32
1714xf86GetModuleVersion(pointer module)
1715{
1716    return (CARD32)LoaderGetModuleVersion(module);
1717}
1718
1719pointer
1720xf86LoadDrvSubModule(DriverPtr drv, const char *name)
1721{
1722    pointer ret;
1723    int errmaj = 0, errmin = 0;
1724
1725    ret = LoadSubModule(drv->module, name, NULL, NULL, NULL, NULL,
1726			&errmaj, &errmin);
1727    if (!ret)
1728	LoaderErrorMsg(NULL, name, errmaj, errmin);
1729    return ret;
1730}
1731
1732pointer
1733xf86LoadSubModule(ScrnInfoPtr pScrn, const char *name)
1734{
1735    pointer ret;
1736    int errmaj = 0, errmin = 0;
1737
1738    ret = LoadSubModule(pScrn->module, name, NULL, NULL, NULL, NULL,
1739			&errmaj, &errmin);
1740    if (!ret)
1741	LoaderErrorMsg(pScrn->name, name, errmaj, errmin);
1742    return ret;
1743}
1744
1745/*
1746 * xf86LoadOneModule loads a single module.
1747 */
1748pointer
1749xf86LoadOneModule(char *name, pointer opt)
1750{
1751    int errmaj, errmin;
1752    char *Name;
1753    pointer mod;
1754
1755    if (!name)
1756	return NULL;
1757
1758    /* Normalise the module name */
1759    Name = xf86NormalizeName(name);
1760
1761    /* Skip empty names */
1762    if (Name == NULL)
1763	return NULL;
1764    if (*Name == '\0') {
1765	free(Name);
1766	return NULL;
1767    }
1768
1769    mod = LoadModule(Name, NULL, NULL, NULL, opt, NULL, &errmaj, &errmin);
1770    if (!mod)
1771	LoaderErrorMsg(NULL, Name, errmaj, errmin);
1772    free(Name);
1773    return mod;
1774}
1775
1776void
1777xf86UnloadSubModule(pointer mod)
1778{
1779    /*
1780     * This is disabled for now.  The loader isn't smart enough yet to undo
1781     * relocations.
1782     */
1783#if 0
1784    UnloadSubModule(mod);
1785#endif
1786}
1787
1788Bool
1789xf86LoaderCheckSymbol(const char *name)
1790{
1791    return LoaderSymbol(name) != NULL;
1792}
1793
1794typedef enum {
1795   OPTION_BACKING_STORE
1796} BSOpts;
1797
1798static const OptionInfoRec BSOptions[] = {
1799   { OPTION_BACKING_STORE, "BackingStore", OPTV_BOOLEAN, {0}, FALSE },
1800   { -1,                   NULL,           OPTV_NONE,    {0}, FALSE }
1801};
1802
1803void
1804xf86SetBackingStore(ScreenPtr pScreen)
1805{
1806    Bool useBS = FALSE;
1807    MessageType from = X_DEFAULT;
1808    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1809    OptionInfoPtr options;
1810
1811    options = xnfalloc(sizeof(BSOptions));
1812    (void)memcpy(options, BSOptions, sizeof(BSOptions));
1813    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
1814
1815    /* check for commandline option here */
1816    if (xf86bsEnableFlag) {
1817	from = X_CMDLINE;
1818	useBS = TRUE;
1819    } else if (xf86bsDisableFlag) {
1820	from = X_CMDLINE;
1821	useBS = FALSE;
1822    } else {
1823	if (xf86GetOptValBool(options, OPTION_BACKING_STORE, &useBS))
1824	    from = X_CONFIG;
1825    }
1826    free(options);
1827    pScreen->backingStoreSupport = useBS ? Always : NotUseful;
1828    if (serverGeneration == 1)
1829	xf86DrvMsg(pScreen->myNum, from, "Backing store %s\n",
1830		   useBS ? "enabled" : "disabled");
1831}
1832
1833
1834typedef enum {
1835   OPTION_SILKEN_MOUSE
1836} SMOpts;
1837
1838static const OptionInfoRec SMOptions[] = {
1839   { OPTION_SILKEN_MOUSE, "SilkenMouse",   OPTV_BOOLEAN, {0}, FALSE },
1840   { -1,                   NULL,           OPTV_NONE,    {0}, FALSE }
1841};
1842
1843void
1844xf86SetSilkenMouse (ScreenPtr pScreen)
1845{
1846    Bool useSM = TRUE;
1847    MessageType from = X_DEFAULT;
1848    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1849    OptionInfoPtr options;
1850
1851    options = xnfalloc(sizeof(SMOptions));
1852    (void)memcpy(options, SMOptions, sizeof(SMOptions));
1853    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
1854
1855    /* check for commandline option here */
1856    /* disable if screen shares resources */
1857	/* TODO VGA arb disable silken mouse */
1858    if (xf86silkenMouseDisableFlag) {
1859        from = X_CMDLINE;
1860	useSM = FALSE;
1861    } else {
1862	if (xf86GetOptValBool(options, OPTION_SILKEN_MOUSE, &useSM))
1863	    from = X_CONFIG;
1864    }
1865    free(options);
1866    /*
1867     * XXX quick hack to report correctly for OSs that can't do SilkenMouse
1868     * yet.  Should handle this differently so that alternate async methods
1869     * work correctly with this too.
1870     */
1871    pScrn->silkenMouse = useSM && xf86Info.useSIGIO && xf86SIGIOSupported();
1872    if (serverGeneration == 1)
1873	xf86DrvMsg(pScreen->myNum, from, "Silken mouse %s\n",
1874		   pScrn->silkenMouse ? "enabled" : "disabled");
1875}
1876
1877/* Wrote this function for the PM2 Xv driver, preliminary. */
1878
1879pointer
1880xf86FindXvOptions(int scrnIndex, int adaptor_index, char *port_name,
1881		  char **adaptor_name, pointer *adaptor_options)
1882{
1883    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1884    confXvAdaptorPtr adaptor;
1885    int i;
1886
1887    if (adaptor_index >= pScrn->confScreen->numxvadaptors) {
1888	if (adaptor_name) *adaptor_name = NULL;
1889	if (adaptor_options) *adaptor_options = NULL;
1890	return NULL;
1891    }
1892
1893    adaptor = &pScrn->confScreen->xvadaptors[adaptor_index];
1894    if (adaptor_name) *adaptor_name = adaptor->identifier;
1895    if (adaptor_options) *adaptor_options = adaptor->options;
1896
1897    for (i = 0; i < adaptor->numports; i++)
1898	if (!xf86NameCmp(adaptor->ports[i].identifier, port_name))
1899	    return adaptor->ports[i].options;
1900
1901    return NULL;
1902}
1903
1904/* Rather than duplicate loader's get OS function, just include it directly */
1905#define LoaderGetOS xf86GetOS
1906#include "loader/os.c"
1907
1908static void
1909xf86ConfigFbEntityInactive(EntityInfoPtr pEnt, EntityProc init,
1910			   EntityProc enter, EntityProc leave, pointer private)
1911{
1912    ScrnInfoPtr pScrn;
1913
1914    if ((pScrn = xf86FindScreenForEntity(pEnt->index)))
1915	xf86RemoveEntityFromScreen(pScrn,pEnt->index);
1916    xf86SetEntityFuncs(pEnt->index,init,enter,leave,private);
1917}
1918
1919ScrnInfoPtr
1920xf86ConfigFbEntity(ScrnInfoPtr pScrn, int scrnFlag, int entityIndex,
1921		   EntityProc init, EntityProc enter, EntityProc leave,
1922		   pointer private)
1923{
1924    EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex);
1925    if (!pEnt) return pScrn;
1926
1927    if (!(pEnt->location.type == BUS_NONE)) {
1928	free(pEnt);
1929	return pScrn;
1930    }
1931
1932    if (!pEnt->active) {
1933	xf86ConfigFbEntityInactive(pEnt, init,  enter, leave,  private);
1934	free(pEnt);
1935	return pScrn;
1936    }
1937
1938    if (!pScrn)
1939	pScrn = xf86AllocateScreen(pEnt->driver,scrnFlag);
1940    xf86AddEntityToScreen(pScrn,entityIndex);
1941
1942    xf86SetEntityFuncs(entityIndex,init,enter,leave,private);
1943
1944    free(pEnt);
1945    return pScrn;
1946}
1947
1948Bool
1949xf86IsScreenPrimary(int scrnIndex)
1950{
1951    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1952    int i;
1953
1954    for (i=0 ; i < pScrn->numEntities; i++) {
1955	if (xf86IsEntityPrimary(i))
1956	    return TRUE;
1957    }
1958    return FALSE;
1959}
1960
1961int
1962xf86RegisterRootWindowProperty(int ScrnIndex, Atom property, Atom type,
1963			       int format, unsigned long len, pointer value )
1964{
1965    RootWinPropPtr pNewProp = NULL, pRegProp;
1966    int i;
1967    Bool existing = FALSE;
1968
1969    DebugF("xf86RegisterRootWindowProperty(%d, %ld, %ld, %d, %ld, %p)\n",
1970	   ScrnIndex, property, type, format, len, value);
1971
1972    if (ScrnIndex<0 || ScrnIndex>=xf86NumScreens) {
1973      return BadMatch;
1974    }
1975
1976    if (xf86RegisteredPropertiesTable &&
1977	xf86RegisteredPropertiesTable[ScrnIndex]) {
1978      for (pNewProp = xf86RegisteredPropertiesTable[ScrnIndex];
1979	   pNewProp; pNewProp = pNewProp->next) {
1980	if (strcmp(pNewProp->name, NameForAtom(property)) == 0)
1981	  break;
1982      }
1983    }
1984
1985    if (!pNewProp) {
1986      if ((pNewProp = (RootWinPropPtr)malloc(sizeof(RootWinProp))) == NULL) {
1987	return BadAlloc;
1988      }
1989      /*
1990       * We will put this property at the end of the list so that
1991       * the changes are made in the order they were requested.
1992       */
1993      pNewProp->next = NULL;
1994    } else {
1995      free(pNewProp->name);
1996      existing = TRUE;
1997    }
1998
1999    pNewProp->name = xnfstrdup(NameForAtom(property));
2000    pNewProp->type = type;
2001    pNewProp->format = format;
2002    pNewProp->size = len;
2003    pNewProp->data = value;
2004
2005    DebugF("new property filled\n");
2006
2007    if (NULL==xf86RegisteredPropertiesTable) {
2008      DebugF("creating xf86RegisteredPropertiesTable[] size %d\n",
2009	     xf86NumScreens);
2010      if ( NULL==(xf86RegisteredPropertiesTable=(RootWinPropPtr*)xnfcalloc(sizeof(RootWinProp),xf86NumScreens) )) {
2011	return BadAlloc;
2012      }
2013      for (i=0; i<xf86NumScreens; i++) {
2014	xf86RegisteredPropertiesTable[i] = NULL;
2015      }
2016    }
2017
2018    DebugF("xf86RegisteredPropertiesTable %p\n",
2019	   (void *)xf86RegisteredPropertiesTable);
2020    DebugF("xf86RegisteredPropertiesTable[%d] %p\n",
2021	   ScrnIndex, (void *)xf86RegisteredPropertiesTable[ScrnIndex]);
2022
2023    if (!existing) {
2024      if ( xf86RegisteredPropertiesTable[ScrnIndex] == NULL) {
2025	xf86RegisteredPropertiesTable[ScrnIndex] = pNewProp;
2026      } else {
2027	pRegProp = xf86RegisteredPropertiesTable[ScrnIndex];
2028	while (pRegProp->next != NULL) {
2029	  DebugF("- next %p\n", (void *)pRegProp);
2030	  pRegProp = pRegProp->next;
2031        }
2032	pRegProp->next = pNewProp;
2033      }
2034    }
2035    DebugF("xf86RegisterRootWindowProperty succeeded\n");
2036    return Success;
2037}
2038
2039Bool
2040xf86IsUnblank(int mode)
2041{
2042    switch(mode) {
2043    case SCREEN_SAVER_OFF:
2044    case SCREEN_SAVER_FORCER:
2045	return TRUE;
2046    case SCREEN_SAVER_ON:
2047    case SCREEN_SAVER_CYCLE:
2048	return FALSE;
2049    default:
2050	xf86MsgVerb(X_WARNING, 0, "Unexpected save screen mode: %d\n", mode);
2051	return TRUE;
2052    }
2053}
2054
2055void
2056xf86MotionHistoryAllocate(InputInfoPtr pInfo)
2057{
2058    AllocateMotionHistory(pInfo->dev);
2059}
2060