xf86Helper.c revision 9ace9065
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     * This can happen when running Xorg -showopts and a module like ati
1404     * or vmware tries to load its submodules when xf86ConfigLayout is empty
1405     */
1406    if (!xf86ConfigLayout.screens)
1407	return 0;
1408
1409    /*
1410     * This is a very important function that matches the device sections
1411     * as they show up in the config file with the drivers that the server
1412     * loads at run time.
1413     *
1414     * ChipProbe can call
1415     * int xf86MatchDevice(char * drivername, GDevPtr ** sectlist)
1416     * with its driver name. The function allocates an array of GDevPtr and
1417     * returns this via sectlist and returns the number of elements in
1418     * this list as return value. 0 means none found, -1 means fatal error.
1419     *
1420     * It can figure out which of the Device sections to use for which card
1421     * (using things like the Card statement, etc). For single headed servers
1422     * there will of course be just one such Device section.
1423     */
1424    i = 0;
1425
1426    /*
1427     * first we need to loop over all the Screens sections to get to all
1428     * 'active' device sections
1429     */
1430    for (j=0; xf86ConfigLayout.screens[j].screen != NULL; j++) {
1431        screensecptr = xf86ConfigLayout.screens[j].screen;
1432        if ((screensecptr->device->driver != NULL)
1433            && (xf86NameCmp( screensecptr->device->driver,drivername) == 0)
1434            && (! screensecptr->device->claimed)) {
1435            /*
1436             * we have a matching driver that wasn't claimed, yet
1437             */
1438            pgdp = xnfrealloc(pgdp, (i + 2) * sizeof(GDevPtr));
1439            pgdp[i++] = screensecptr->device;
1440        }
1441    }
1442
1443    /* Then handle the inactive devices */
1444    j = 0;
1445    while (xf86ConfigLayout.inactives[j].identifier) {
1446	gdp = &xf86ConfigLayout.inactives[j];
1447	if (gdp->driver && !gdp->claimed &&
1448	    !xf86NameCmp(gdp->driver,drivername)) {
1449	    /* we have a matching driver that wasn't claimed yet */
1450	    pgdp = xnfrealloc(pgdp, (i + 2) * sizeof(GDevPtr));
1451	    pgdp[i++] = gdp;
1452	}
1453	j++;
1454    }
1455
1456    /*
1457     * make the array NULL terminated and return its address
1458     */
1459    if (i)
1460        pgdp[i] = NULL;
1461
1462    if (sectlist)
1463	*sectlist = pgdp;
1464    else
1465	free(pgdp);
1466    return i;
1467}
1468
1469/*
1470 * xf86GetClocks -- get the dot-clocks via a BIG BAD hack ...
1471 */
1472void
1473xf86GetClocks(ScrnInfoPtr pScrn, int num, Bool (*ClockFunc)(ScrnInfoPtr, int),
1474	      void (*ProtectRegs)(ScrnInfoPtr, Bool),
1475	      void (*BlankScreen)(ScrnInfoPtr, Bool), IOADDRESS vertsyncreg,
1476	      int maskval, int knownclkindex, int knownclkvalue)
1477{
1478    register int status = vertsyncreg;
1479    unsigned long i, cnt, rcnt, sync;
1480
1481    /* First save registers that get written on */
1482    (*ClockFunc)(pScrn, CLK_REG_SAVE);
1483
1484    if (num > MAXCLOCKS)
1485	num = MAXCLOCKS;
1486
1487    for (i = 0; i < num; i++)
1488    {
1489	if (ProtectRegs)
1490	    (*ProtectRegs)(pScrn, TRUE);
1491	if (!(*ClockFunc)(pScrn, i))
1492	{
1493	    pScrn->clock[i] = -1;
1494	    continue;
1495	}
1496	if (ProtectRegs)
1497	    (*ProtectRegs)(pScrn, FALSE);
1498	if (BlankScreen)
1499	    (*BlankScreen)(pScrn, FALSE);
1500
1501    	usleep(50000);     /* let VCO stabilise */
1502
1503    	cnt  = 0;
1504    	sync = 200000;
1505
1506	while ((inb(status) & maskval) == 0x00)
1507	    if (sync-- == 0) goto finish;
1508	/* Something appears to be happening, so reset sync count */
1509	sync = 200000;
1510	while ((inb(status) & maskval) == maskval)
1511	    if (sync-- == 0) goto finish;
1512	/* Something appears to be happening, so reset sync count */
1513	sync = 200000;
1514	while ((inb(status) & maskval) == 0x00)
1515	    if (sync-- == 0) goto finish;
1516
1517	for (rcnt = 0; rcnt < 5; rcnt++)
1518	{
1519	    while (!(inb(status) & maskval))
1520		cnt++;
1521	    while ((inb(status) & maskval))
1522		cnt++;
1523	}
1524
1525finish:
1526	pScrn->clock[i] = cnt ? cnt : -1;
1527	if (BlankScreen)
1528            (*BlankScreen)(pScrn, TRUE);
1529    }
1530
1531    for (i = 0; i < num; i++)
1532    {
1533	if (i != knownclkindex)
1534	{
1535	    if (pScrn->clock[i] == -1)
1536	    {
1537		pScrn->clock[i] = 0;
1538	    }
1539	    else
1540	    {
1541		pScrn->clock[i] = (int)(0.5 +
1542                    (((float)knownclkvalue) * pScrn->clock[knownclkindex]) /
1543	            (pScrn->clock[i]));
1544		/* Round to nearest 10KHz */
1545		pScrn->clock[i] += 5;
1546		pScrn->clock[i] /= 10;
1547		pScrn->clock[i] *= 10;
1548	    }
1549	}
1550    }
1551
1552    pScrn->clock[knownclkindex] = knownclkvalue;
1553    pScrn->numClocks = num;
1554
1555    /* Restore registers that were written on */
1556    (*ClockFunc)(pScrn, CLK_REG_RESTORE);
1557}
1558
1559const char *
1560xf86GetVisualName(int visual)
1561{
1562    if (visual < 0 || visual > DirectColor)
1563	return NULL;
1564
1565    return xf86VisualNames[visual];
1566}
1567
1568
1569int
1570xf86GetVerbosity(void)
1571{
1572    return max(xf86Verbose, xf86LogVerbose);
1573}
1574
1575Pix24Flags
1576xf86GetPix24(void)
1577{
1578    return xf86Info.pixmap24;
1579}
1580
1581
1582int
1583xf86GetDepth(void)
1584{
1585    return xf86Depth;
1586}
1587
1588
1589rgb
1590xf86GetWeight(void)
1591{
1592    return xf86Weight;
1593}
1594
1595
1596Gamma
1597xf86GetGamma(void)
1598{
1599    return xf86Gamma;
1600}
1601
1602
1603Bool
1604xf86GetFlipPixels(void)
1605{
1606    return xf86FlipPixels;
1607}
1608
1609
1610const char *
1611xf86GetServerName(void)
1612{
1613    return xf86ServerName;
1614}
1615
1616
1617Bool
1618xf86ServerIsExiting(void)
1619{
1620    return (dispatchException & DE_TERMINATE) == DE_TERMINATE;
1621}
1622
1623
1624Bool
1625xf86ServerIsResetting(void)
1626{
1627    return xf86Resetting;
1628}
1629
1630
1631Bool
1632xf86ServerIsInitialising(void)
1633{
1634    return xf86Initialising;
1635}
1636
1637
1638Bool
1639xf86ServerIsOnlyDetecting(void)
1640{
1641    return xf86DoConfigure;
1642}
1643
1644
1645Bool
1646xf86CaughtSignal(void)
1647{
1648    return xf86Info.caughtSignal;
1649}
1650
1651
1652Bool
1653xf86GetVidModeAllowNonLocal(void)
1654{
1655    return xf86Info.vidModeAllowNonLocal;
1656}
1657
1658
1659Bool
1660xf86GetVidModeEnabled(void)
1661{
1662    return xf86Info.vidModeEnabled;
1663}
1664
1665Bool
1666xf86GetModInDevAllowNonLocal(void)
1667{
1668    return xf86Info.miscModInDevAllowNonLocal;
1669}
1670
1671
1672Bool
1673xf86GetModInDevEnabled(void)
1674{
1675    return xf86Info.miscModInDevEnabled;
1676}
1677
1678
1679Bool
1680xf86GetAllowMouseOpenFail(void)
1681{
1682    return xf86Info.allowMouseOpenFail;
1683}
1684
1685
1686Bool
1687xf86IsPc98(void)
1688{
1689#if SUPPORT_PC98
1690    return xf86Info.pc98;
1691#else
1692    return FALSE;
1693#endif
1694}
1695
1696void
1697xf86DisableRandR(void)
1698{
1699    xf86Info.disableRandR = TRUE;
1700    xf86Info.randRFrom = X_PROBED;
1701}
1702
1703CARD32
1704xf86GetModuleVersion(pointer module)
1705{
1706    return (CARD32)LoaderGetModuleVersion(module);
1707}
1708
1709pointer
1710xf86LoadDrvSubModule(DriverPtr drv, const char *name)
1711{
1712    pointer ret;
1713    int errmaj = 0, errmin = 0;
1714
1715    ret = LoadSubModule(drv->module, name, NULL, NULL, NULL, NULL,
1716			&errmaj, &errmin);
1717    if (!ret)
1718	LoaderErrorMsg(NULL, name, errmaj, errmin);
1719    return ret;
1720}
1721
1722pointer
1723xf86LoadSubModule(ScrnInfoPtr pScrn, const char *name)
1724{
1725    pointer ret;
1726    int errmaj = 0, errmin = 0;
1727
1728    ret = LoadSubModule(pScrn->module, name, NULL, NULL, NULL, NULL,
1729			&errmaj, &errmin);
1730    if (!ret)
1731	LoaderErrorMsg(pScrn->name, name, errmaj, errmin);
1732    return ret;
1733}
1734
1735/*
1736 * xf86LoadOneModule loads a single module.
1737 */
1738pointer
1739xf86LoadOneModule(char *name, pointer opt)
1740{
1741    int errmaj, errmin;
1742    char *Name;
1743    pointer mod;
1744
1745    if (!name)
1746	return NULL;
1747
1748    /* Normalise the module name */
1749    Name = xf86NormalizeName(name);
1750
1751    /* Skip empty names */
1752    if (Name == NULL)
1753	return NULL;
1754    if (*Name == '\0') {
1755	free(Name);
1756	return NULL;
1757    }
1758
1759    mod = LoadModule(Name, NULL, NULL, NULL, opt, NULL, &errmaj, &errmin);
1760    if (!mod)
1761	LoaderErrorMsg(NULL, Name, errmaj, errmin);
1762    free(Name);
1763    return mod;
1764}
1765
1766void
1767xf86UnloadSubModule(pointer mod)
1768{
1769    /*
1770     * This is disabled for now.  The loader isn't smart enough yet to undo
1771     * relocations.
1772     */
1773#if 0
1774    UnloadSubModule(mod);
1775#endif
1776}
1777
1778Bool
1779xf86LoaderCheckSymbol(const char *name)
1780{
1781    return LoaderSymbol(name) != NULL;
1782}
1783
1784typedef enum {
1785   OPTION_BACKING_STORE
1786} BSOpts;
1787
1788static const OptionInfoRec BSOptions[] = {
1789   { OPTION_BACKING_STORE, "BackingStore", OPTV_BOOLEAN, {0}, FALSE },
1790   { -1,                   NULL,           OPTV_NONE,    {0}, FALSE }
1791};
1792
1793void
1794xf86SetBackingStore(ScreenPtr pScreen)
1795{
1796    Bool useBS = FALSE;
1797    MessageType from = X_DEFAULT;
1798    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1799    OptionInfoPtr options;
1800
1801    options = xnfalloc(sizeof(BSOptions));
1802    (void)memcpy(options, BSOptions, sizeof(BSOptions));
1803    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
1804
1805    /* check for commandline option here */
1806    if (xf86bsEnableFlag) {
1807	from = X_CMDLINE;
1808	useBS = TRUE;
1809    } else if (xf86bsDisableFlag) {
1810	from = X_CMDLINE;
1811	useBS = FALSE;
1812    } else {
1813	if (xf86GetOptValBool(options, OPTION_BACKING_STORE, &useBS))
1814	    from = X_CONFIG;
1815    }
1816    free(options);
1817    pScreen->backingStoreSupport = useBS ? Always : NotUseful;
1818    if (serverGeneration == 1)
1819	xf86DrvMsg(pScreen->myNum, from, "Backing store %s\n",
1820		   useBS ? "enabled" : "disabled");
1821}
1822
1823
1824typedef enum {
1825   OPTION_SILKEN_MOUSE
1826} SMOpts;
1827
1828static const OptionInfoRec SMOptions[] = {
1829   { OPTION_SILKEN_MOUSE, "SilkenMouse",   OPTV_BOOLEAN, {0}, FALSE },
1830   { -1,                   NULL,           OPTV_NONE,    {0}, FALSE }
1831};
1832
1833void
1834xf86SetSilkenMouse (ScreenPtr pScreen)
1835{
1836    Bool useSM = TRUE;
1837    MessageType from = X_DEFAULT;
1838    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1839    OptionInfoPtr options;
1840
1841    options = xnfalloc(sizeof(SMOptions));
1842    (void)memcpy(options, SMOptions, sizeof(SMOptions));
1843    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
1844
1845    /* check for commandline option here */
1846    /* disable if screen shares resources */
1847	/* TODO VGA arb disable silken mouse */
1848    if (xf86silkenMouseDisableFlag) {
1849        from = X_CMDLINE;
1850	useSM = FALSE;
1851    } else {
1852	if (xf86GetOptValBool(options, OPTION_SILKEN_MOUSE, &useSM))
1853	    from = X_CONFIG;
1854    }
1855    free(options);
1856    /*
1857     * XXX quick hack to report correctly for OSs that can't do SilkenMouse
1858     * yet.  Should handle this differently so that alternate async methods
1859     * work correctly with this too.
1860     */
1861    pScrn->silkenMouse = useSM && xf86Info.useSIGIO && xf86SIGIOSupported();
1862    if (serverGeneration == 1)
1863	xf86DrvMsg(pScreen->myNum, from, "Silken mouse %s\n",
1864		   pScrn->silkenMouse ? "enabled" : "disabled");
1865}
1866
1867/* Wrote this function for the PM2 Xv driver, preliminary. */
1868
1869pointer
1870xf86FindXvOptions(int scrnIndex, int adaptor_index, char *port_name,
1871		  char **adaptor_name, pointer *adaptor_options)
1872{
1873    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1874    confXvAdaptorPtr adaptor;
1875    int i;
1876
1877    if (adaptor_index >= pScrn->confScreen->numxvadaptors) {
1878	if (adaptor_name) *adaptor_name = NULL;
1879	if (adaptor_options) *adaptor_options = NULL;
1880	return NULL;
1881    }
1882
1883    adaptor = &pScrn->confScreen->xvadaptors[adaptor_index];
1884    if (adaptor_name) *adaptor_name = adaptor->identifier;
1885    if (adaptor_options) *adaptor_options = adaptor->options;
1886
1887    for (i = 0; i < adaptor->numports; i++)
1888	if (!xf86NameCmp(adaptor->ports[i].identifier, port_name))
1889	    return adaptor->ports[i].options;
1890
1891    return NULL;
1892}
1893
1894/* Rather than duplicate loader's get OS function, just include it directly */
1895#define LoaderGetOS xf86GetOS
1896#include "loader/os.c"
1897
1898static void
1899xf86ConfigFbEntityInactive(EntityInfoPtr pEnt, EntityProc init,
1900			   EntityProc enter, EntityProc leave, pointer private)
1901{
1902    ScrnInfoPtr pScrn;
1903
1904    if ((pScrn = xf86FindScreenForEntity(pEnt->index)))
1905	xf86RemoveEntityFromScreen(pScrn,pEnt->index);
1906    xf86SetEntityFuncs(pEnt->index,init,enter,leave,private);
1907}
1908
1909ScrnInfoPtr
1910xf86ConfigFbEntity(ScrnInfoPtr pScrn, int scrnFlag, int entityIndex,
1911		   EntityProc init, EntityProc enter, EntityProc leave,
1912		   pointer private)
1913{
1914    EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex);
1915    if (!pEnt) return pScrn;
1916
1917    if (!(pEnt->location.type == BUS_NONE)) {
1918	free(pEnt);
1919	return pScrn;
1920    }
1921
1922    if (!pEnt->active) {
1923	xf86ConfigFbEntityInactive(pEnt, init,  enter, leave,  private);
1924	free(pEnt);
1925	return pScrn;
1926    }
1927
1928    if (!pScrn)
1929	pScrn = xf86AllocateScreen(pEnt->driver,scrnFlag);
1930    xf86AddEntityToScreen(pScrn,entityIndex);
1931
1932    xf86SetEntityFuncs(entityIndex,init,enter,leave,private);
1933
1934    free(pEnt);
1935    return pScrn;
1936}
1937
1938Bool
1939xf86IsScreenPrimary(int scrnIndex)
1940{
1941    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1942    int i;
1943
1944    for (i=0 ; i < pScrn->numEntities; i++) {
1945	if (xf86IsEntityPrimary(i))
1946	    return TRUE;
1947    }
1948    return FALSE;
1949}
1950
1951int
1952xf86RegisterRootWindowProperty(int ScrnIndex, Atom property, Atom type,
1953			       int format, unsigned long len, pointer value )
1954{
1955    RootWinPropPtr pNewProp = NULL, pRegProp;
1956    int i;
1957    Bool existing = FALSE;
1958
1959    DebugF("xf86RegisterRootWindowProperty(%d, %ld, %ld, %d, %ld, %p)\n",
1960	   ScrnIndex, property, type, format, len, value);
1961
1962    if (ScrnIndex<0 || ScrnIndex>=xf86NumScreens) {
1963      return BadMatch;
1964    }
1965
1966    if (xf86RegisteredPropertiesTable &&
1967	xf86RegisteredPropertiesTable[ScrnIndex]) {
1968      for (pNewProp = xf86RegisteredPropertiesTable[ScrnIndex];
1969	   pNewProp; pNewProp = pNewProp->next) {
1970	if (strcmp(pNewProp->name, NameForAtom(property)) == 0)
1971	  break;
1972      }
1973    }
1974
1975    if (!pNewProp) {
1976      if ((pNewProp = (RootWinPropPtr)malloc(sizeof(RootWinProp))) == NULL) {
1977	return BadAlloc;
1978      }
1979      /*
1980       * We will put this property at the end of the list so that
1981       * the changes are made in the order they were requested.
1982       */
1983      pNewProp->next = NULL;
1984    } else {
1985      free(pNewProp->name);
1986      existing = TRUE;
1987    }
1988
1989    pNewProp->name = xnfstrdup(NameForAtom(property));
1990    pNewProp->type = type;
1991    pNewProp->format = format;
1992    pNewProp->size = len;
1993    pNewProp->data = value;
1994
1995    DebugF("new property filled\n");
1996
1997    if (NULL==xf86RegisteredPropertiesTable) {
1998      DebugF("creating xf86RegisteredPropertiesTable[] size %d\n",
1999	     xf86NumScreens);
2000      if ( NULL==(xf86RegisteredPropertiesTable=(RootWinPropPtr*)xnfcalloc(sizeof(RootWinProp),xf86NumScreens) )) {
2001	return BadAlloc;
2002      }
2003      for (i=0; i<xf86NumScreens; i++) {
2004	xf86RegisteredPropertiesTable[i] = NULL;
2005      }
2006    }
2007
2008    DebugF("xf86RegisteredPropertiesTable %p\n",
2009	   (void *)xf86RegisteredPropertiesTable);
2010    DebugF("xf86RegisteredPropertiesTable[%d] %p\n",
2011	   ScrnIndex, (void *)xf86RegisteredPropertiesTable[ScrnIndex]);
2012
2013    if (!existing) {
2014      if ( xf86RegisteredPropertiesTable[ScrnIndex] == NULL) {
2015	xf86RegisteredPropertiesTable[ScrnIndex] = pNewProp;
2016      } else {
2017	pRegProp = xf86RegisteredPropertiesTable[ScrnIndex];
2018	while (pRegProp->next != NULL) {
2019	  DebugF("- next %p\n", (void *)pRegProp);
2020	  pRegProp = pRegProp->next;
2021        }
2022	pRegProp->next = pNewProp;
2023      }
2024    }
2025    DebugF("xf86RegisterRootWindowProperty succeeded\n");
2026    return Success;
2027}
2028
2029Bool
2030xf86IsUnblank(int mode)
2031{
2032    switch(mode) {
2033    case SCREEN_SAVER_OFF:
2034    case SCREEN_SAVER_FORCER:
2035	return TRUE;
2036    case SCREEN_SAVER_ON:
2037    case SCREEN_SAVER_CYCLE:
2038	return FALSE;
2039    default:
2040	xf86MsgVerb(X_WARNING, 0, "Unexpected save screen mode: %d\n", mode);
2041	return TRUE;
2042    }
2043}
2044
2045void
2046xf86MotionHistoryAllocate(InputInfoPtr pInfo)
2047{
2048    AllocateMotionHistory(pInfo->dev);
2049}
2050