f8e6c8b41a8e29959d86dac8f1ed0bca7e188767
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 */
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 */
37 #ifdef HAVE_XORG_CONFIG_H
38 #include <xorg-config.h>
39 #endif
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"
59 /* For xf86GetClocks */
60 #if defined(CSRG_BASED) || defined(__GNU__)
61 #define HAS_SETPRIORITY
62 #include <sys/resource.h>
63 #endif
65 static int xf86ScrnInfoPrivateCount = 0;
68 /* Add a pointer to a new DriverRec to xf86DriverList */
70 void
71 xf86AddDriver(DriverPtr driver, pointer module, int flags)
72 {
73 /* Don't add null entries */
74 if (!driver)
75 return;
77 if (xf86DriverList == NULL)
78 xf86NumDrivers = 0;
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));
92 }
93 xf86DriverList[xf86NumDrivers - 1]->module = module;
94 xf86DriverList[xf86NumDrivers - 1]->refCount = 0;
95 }
97 void
98 xf86DeleteDriver(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 }
109 /* Add a pointer to a new InputDriverRec to xf86InputDriverList */
111 void
112 xf86AddInputDriver(InputDriverPtr driver, pointer module, int flags)
113 {
114 /* Don't add null entries */
115 if (!driver)
116 return;
118 if (xf86InputDriverList == NULL)
119 xf86NumInputDrivers = 0;
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 }
130 void
131 xf86DeleteInputDriver(int drvIndex)
132 {
133 if (xf86InputDriverList[drvIndex] && xf86InputDriverList[drvIndex]->module)
134 UnloadModule(xf86InputDriverList[drvIndex]->module);
135 free(xf86InputDriverList[drvIndex]);
136 xf86InputDriverList[drvIndex] = NULL;
137 }
139 InputDriverPtr
140 xf86LookupInputDriver(const char *name)
141 {
142 int i;
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 }
152 InputInfoPtr
153 xf86LookupInput(const char *name)
154 {
155 InputInfoPtr p;
157 for (p = xf86InputDevs; p != NULL; p = p->next) {
158 if (strcmp(name, p->name) == 0)
159 return p;
160 }
162 return NULL;
163 }
165 /* Allocate a new ScrnInfoRec in xf86Screens */
167 ScrnInfoPtr
168 xf86AllocateScreen(DriverPtr drv, int flags)
169 {
170 int i;
172 if (xf86Screens == NULL)
173 xf86NumScreens = 0;
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 */
187 xf86Screens[i]->drv = drv;
188 drv->refCount++;
189 xf86Screens[i]->module = DuplicateModule(drv->module, NULL);
191 xf86Screens[i]->DriverFunc = drv->driverFunc;
193 return xf86Screens[i];
194 }
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 */
202 void
203 xf86DeleteScreen(int scrnIndex, int flags)
204 {
205 ScrnInfoPtr pScrn;
206 int i;
208 /* First check if the screen is valid */
209 if (xf86NumScreens == 0 || xf86Screens == NULL)
210 return;
212 if (scrnIndex > xf86NumScreens - 1)
213 return;
215 if (!(pScrn = xf86Screens[scrnIndex]))
216 return;
218 /* If a FreeScreen function is defined, call it here */
219 if (pScrn->FreeScreen != NULL)
220 pScrn->FreeScreen(scrnIndex, 0);
222 while (pScrn->modes)
223 xf86DeleteMode(&pScrn->modes, pScrn->modes);
225 while (pScrn->modePool)
226 xf86DeleteMode(&pScrn->modePool, pScrn->modePool);
228 xf86OptionListFree(pScrn->options);
230 if (pScrn->module)
231 UnloadModule(pScrn->module);
233 if (pScrn->drv)
234 pScrn->drv->refCount--;
236 free(pScrn->privates);
238 xf86ClearEntityListForScreen(scrnIndex);
240 free(pScrn);
242 /* Move the other entries down, updating their scrnIndex fields */
244 xf86NumScreens--;
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 }
253 /*
254 * Allocate a private in ScrnInfoRec.
255 */
257 int
258 xf86AllocateScrnInfoPrivateIndex(void)
259 {
260 int idx, i;
261 ScrnInfoPtr pScr;
262 DevUnion *nprivs;
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 }
276 Bool
277 xf86AddPixFormat(ScrnInfoPtr pScrn, int depth, int bpp, int pad)
278 {
279 int i;
281 if (pScrn->numFormats >= MAXFORMATS)
282 return FALSE;
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;
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 }
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 */
321 /* Can the screen handle 24 bpp pixmaps */
322 #define DO_PIX24(f) ((f & Support24bppFb) || \
323 ((f & Support32bppFb) && (f & SupportConvert24to32)))
325 /* Can the screen handle 32 bpp pixmaps */
326 #define DO_PIX32(f) ((f & Support32bppFb) || \
327 ((f & Support24bppFb) && (f & SupportConvert32to24)))
329 /* Does the screen prefer 32bpp fb for 24bpp pixmaps */
330 #define CHOOSE32FOR24(f) ((f & Support32bppFb) && (f & SupportConvert24to32) \
331 && (f & PreferConvert24to32))
333 /* Does the screen prefer 24bpp fb for 32bpp pixmaps */
334 #define CHOOSE24FOR32(f) ((f & Support24bppFb) && (f & SupportConvert32to24) \
335 && (f & PreferConvert32to24))
337 /* Can the screen handle 32bpp pixmaps for 24bpp fb */
338 #define DO_PIX32FOR24(f) ((f & Support24bppFb) && (f & SupportConvert32to24))
340 /* Can the screen handle 24bpp pixmaps for 32bpp fb */
341 #define DO_PIX24FOR32(f) ((f & Support32bppFb) && (f & SupportConvert24to32))
343 #ifndef GLOBAL_DEFAULT_DEPTH
344 #define GLOBAL_DEFAULT_DEPTH 24
345 #endif
347 Bool
348 xf86SetDepthBpp(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;
356 scrp->bitsPerPixel = -1;
357 scrp->depth = -1;
358 scrp->pixmap24 = Pix24DontCare;
359 scrp->bitsPerPixelFrom = X_DEFAULT;
360 scrp->depthFrom = X_DEFAULT;
362 if (xf86FbBpp > 0) {
363 scrp->bitsPerPixel = xf86FbBpp;
364 scrp->bitsPerPixelFrom = X_CMDLINE;
365 }
367 if (xf86Depth > 0) {
368 scrp->depth = xf86Depth;
369 scrp->depthFrom = X_CMDLINE;
370 }
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 }
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;
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 }
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 }
428 /* If any are not given, determine a default for the others */
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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;
658 return TRUE;
659 }
661 /*
662 * Print out the selected depth and bpp.
663 */
664 void
665 xf86PrintDepthBpp(ScrnInfoPtr scrp)
666 {
667 xf86DrvMsg(scrp->scrnIndex, scrp->depthFrom, "Depth %d, ", scrp->depth);
668 xf86Msg(scrp->bitsPerPixelFrom, "framebuffer bpp %d\n", scrp->bitsPerPixel);
669 }
671 /*
672 * xf86SetWeight sets scrp->weight, scrp->mask, scrp->offset, and for depths
673 * greater than MAX_PSEUDO_DEPTH also scrp->rgbBits.
674 */
675 Bool
676 xf86SetWeight(ScrnInfoPtr scrp, rgb weight, rgb mask)
677 {
678 MessageType weightFrom = X_DEFAULT;
680 scrp->weight.red = 0;
681 scrp->weight.green = 0;
682 scrp->weight.blue = 0;
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 }
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);
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 }
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 }
770 Bool
771 xf86SetDefaultVisual(ScrnInfoPtr scrp, int visual)
772 {
773 MessageType visualFrom = X_DEFAULT;
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:
805 xf86DrvMsg(scrp->scrnIndex, X_ERROR,
806 "Invalid default visual class (%d)\n", scrp->defaultVisual);
807 return FALSE;
808 }
809 }
811 #define TEST_GAMMA(g) \
812 (g).red > GAMMA_ZERO || (g).green > GAMMA_ZERO || (g).blue > GAMMA_ZERO
814 #define SET_GAMMA(g) \
815 (g) > GAMMA_ZERO ? (g) : 1.0
817 Bool
818 xf86SetGamma(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);
861 return TRUE;
862 }
864 #undef TEST_GAMMA
865 #undef SET_GAMMA
868 /*
869 * Set the DPI from the command line option. XXX should allow it to be
870 * calculated from the widthmm/heightmm values.
871 */
873 #undef MMPERINCH
874 #define MMPERINCH 25.4
876 void
877 xf86SetDpi(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;
884 /* XXX Maybe there is no need for widthmm/heightmm in ScrnInfoRec */
885 pScrn->widthmm = pScrn->monitor->widthmm;
886 pScrn->heightmm = pScrn->monitor->heightmm;
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 }
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);
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 }
970 #undef MMPERINCH
973 void
974 xf86SetBlackWhitePixels(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 }
985 /*
986 * Function to enable/disable access to the frame buffer
987 *
988 * This is used when VT switching and when entering/leaving DGA direct mode.
989 *
990 * This has been rewritten again to eliminate the saved pixmap. The
991 * devPrivate field in the screen pixmap is set to NULL to catch code
992 * accidentally referencing the frame buffer while the X server is not
993 * supposed to touch it.
994 *
995 * Here, we exchange the pixmap private data, rather than the pixmaps
996 * themselves to avoid having to find and change any references to the screen
997 * pixmap such as GC's, window privates etc. This also means that this code
998 * does not need to know exactly how the pixmap pixels are accessed. Further,
999 * this exchange is >not< done through the screen's ModifyPixmapHeader()
1000 * vector. This means the called frame buffer code layers can determine
1001 * whether they are switched in or out by keeping track of the root pixmap's
1002 * private data, and therefore don't need to access pScrnInfo->vtSema.
1003 */
1004 void
1005 xf86EnableDisableFBAccess(int scrnIndex, Bool enable)
1006 {
1007 ScrnInfoPtr pScrnInfo = xf86Screens[scrnIndex];
1008 ScreenPtr pScreen = pScrnInfo->pScreen;
1009 PixmapPtr pspix;
1011 pspix = (*pScreen->GetScreenPixmap) (pScreen);
1012 if (enable)
1013 {
1014 /*
1015 * Restore all of the clip lists on the screen
1016 */
1017 if (!xf86Resetting)
1018 SetRootClip (pScreen, TRUE);
1020 }
1021 else
1022 {
1023 /*
1024 * Empty all of the clip lists on the screen
1025 */
1026 SetRootClip (pScreen, FALSE);
1027 }
1028 }
1030 /* Print driver messages in the standard format */
1032 #undef PREFIX_SIZE
1033 #define PREFIX_SIZE 14
1035 void
1036 xf86VDrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format,
1037 va_list args)
1038 {
1039 char *tmpFormat;
1041 /* Prefix the scrnIndex name to the format string. */
1042 if (scrnIndex >= 0 && scrnIndex < xf86NumScreens &&
1043 xf86Screens[scrnIndex]->name) {
1044 tmpFormat = malloc(strlen(format) +
1045 strlen(xf86Screens[scrnIndex]->name) +
1046 PREFIX_SIZE + 1);
1047 if (!tmpFormat)
1048 return;
1050 snprintf(tmpFormat, PREFIX_SIZE + 1, "%s(%d): ",
1051 xf86Screens[scrnIndex]->name, scrnIndex);
1053 strcat(tmpFormat, format);
1054 LogVMessageVerb(type, verb, tmpFormat, args);
1055 free(tmpFormat);
1056 } else
1057 LogVMessageVerb(type, verb, format, args);
1058 }
1059 #undef PREFIX_SIZE
1061 /* Print driver messages, with verbose level specified directly */
1062 void
1063 xf86DrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format,
1064 ...)
1065 {
1066 va_list ap;
1068 va_start(ap, format);
1069 xf86VDrvMsgVerb(scrnIndex, type, verb, format, ap);
1070 va_end(ap);
1071 }
1073 /* Print driver messages, with verbose level of 1 (default) */
1074 void
1075 xf86DrvMsg(int scrnIndex, MessageType type, const char *format, ...)
1076 {
1077 va_list ap;
1079 va_start(ap, format);
1080 xf86VDrvMsgVerb(scrnIndex, type, 1, format, ap);
1081 va_end(ap);
1082 }
1084 /* Print input driver messages in the standard format of
1085 <driver>: <device name>: <message> */
1086 void
1087 xf86VIDrvMsgVerb(InputInfoPtr dev, MessageType type, int verb, const char *format,
1088 va_list args)
1089 {
1090 char *msg;
1092 if (asprintf(&msg, "%s: %s: %s", dev->drv->driverName, dev->name, format)
1093 == -1) {
1094 LogVMessageVerb(type, verb, "%s", args);
1095 } else {
1096 LogVMessageVerb(type, verb, msg, args);
1097 free(msg);
1098 }
1099 }
1101 /* Print input driver message, with verbose level specified directly */
1102 void
1103 xf86IDrvMsgVerb(InputInfoPtr dev, MessageType type, int verb, const char *format,
1104 ...)
1105 {
1106 va_list ap;
1108 va_start(ap, format);
1109 xf86VIDrvMsgVerb(dev, type, verb, format, ap);
1110 va_end(ap);
1111 }
1113 /* Print input driver messages, with verbose level of 1 (default) */
1114 void
1115 xf86IDrvMsg(InputInfoPtr dev, MessageType type, const char *format, ...)
1116 {
1117 va_list ap;
1119 va_start(ap, format);
1120 xf86VIDrvMsgVerb(dev, type, 1, format, ap);
1121 va_end(ap);
1122 }
1125 /* Print non-driver messages with verbose level specified directly */
1126 void
1127 xf86MsgVerb(MessageType type, int verb, const char *format, ...)
1128 {
1129 va_list ap;
1131 va_start(ap, format);
1132 LogVMessageVerb(type, verb, format, ap);
1133 va_end(ap);
1134 }
1136 /* Print non-driver messages with verbose level of 1 (default) */
1137 void
1138 xf86Msg(MessageType type, const char *format, ...)
1139 {
1140 va_list ap;
1142 va_start(ap, format);
1143 LogVMessageVerb(type, 1, format, ap);
1144 va_end(ap);
1145 }
1147 /* Just like ErrorF, but with the verbose level checked */
1148 void
1149 xf86ErrorFVerb(int verb, const char *format, ...)
1150 {
1151 va_list ap;
1153 va_start(ap, format);
1154 if (xf86Verbose >= verb || xf86LogVerbose >= verb)
1155 LogVWrite(verb, format, ap);
1156 va_end(ap);
1157 }
1159 /* Like xf86ErrorFVerb, but with an implied verbose level of 1 */
1160 void
1161 xf86ErrorF(const char *format, ...)
1162 {
1163 va_list ap;
1165 va_start(ap, format);
1166 if (xf86Verbose >= 1 || xf86LogVerbose >= 1)
1167 LogVWrite(1, format, ap);
1168 va_end(ap);
1169 }
1172 void
1173 xf86LogInit(void)
1174 {
1175 char *lf = NULL;
1177 #define LOGSUFFIX ".log"
1178 #define LOGOLDSUFFIX ".old"
1180 /* Get the log file name */
1181 if (xf86LogFileFrom == X_DEFAULT) {
1182 /* Append the display number and ".log" */
1183 if (asprintf(&lf, "%s%%s" LOGSUFFIX, xf86LogFile) == -1)
1184 FatalError("Cannot allocate space for the log file name\n");
1185 xf86LogFile = lf;
1186 }
1188 xf86LogFile = LogInit(xf86LogFile, LOGOLDSUFFIX);
1189 xf86LogFileWasOpened = TRUE;
1191 xf86SetVerbosity(xf86Verbose);
1192 xf86SetLogVerbosity(xf86LogVerbose);
1194 #undef LOGSUFFIX
1195 #undef LOGOLDSUFFIX
1197 free(lf);
1198 }
1200 void
1201 xf86CloseLog(enum ExitCode error)
1202 {
1203 LogClose(error);
1204 }
1207 /*
1208 * Drivers can use these for using their own SymTabRecs.
1209 */
1211 const char *
1212 xf86TokenToString(SymTabPtr table, int token)
1213 {
1214 int i;
1216 for (i = 0; table[i].token >= 0 && table[i].token != token; i++)
1217 ;
1219 if (table[i].token < 0)
1220 return NULL;
1221 else
1222 return table[i].name;
1223 }
1225 int
1226 xf86StringToToken(SymTabPtr table, const char *string)
1227 {
1228 int i;
1230 if (string == NULL)
1231 return -1;
1233 for (i = 0; table[i].token >= 0 && xf86NameCmp(string, table[i].name); i++)
1234 ;
1236 return table[i].token;
1237 }
1239 /*
1240 * helper to display the clocks found on a card
1241 */
1242 void
1243 xf86ShowClocks(ScrnInfoPtr scrp, MessageType from)
1244 {
1245 int j;
1247 xf86DrvMsg(scrp->scrnIndex, from, "Pixel clocks available:");
1248 for (j=0; j < scrp->numClocks; j++) {
1249 if ((j % 4) == 0) {
1250 xf86ErrorF("\n");
1251 xf86DrvMsg(scrp->scrnIndex, from, "pixel clocks:");
1252 }
1253 xf86ErrorF(" %7.3f", (double)scrp->clock[j] / 1000.0);
1254 }
1255 xf86ErrorF("\n");
1256 }
1259 /*
1260 * This prints out the driver identify message, including the names of
1261 * the supported chipsets.
1262 *
1263 * XXX This makes assumptions about the line width, etc. Maybe we could
1264 * use a more general "pretty print" function for messages.
1265 */
1266 void
1267 xf86PrintChipsets(const char *drvname, const char *drvmsg, SymTabPtr chips)
1268 {
1269 int len, i;
1271 len = 6 + strlen(drvname) + 2 + strlen(drvmsg) + 2;
1272 xf86Msg(X_INFO, "%s: %s:", drvname, drvmsg);
1273 for (i = 0; chips[i].name != NULL; i++) {
1274 if (i != 0) {
1275 xf86ErrorF(",");
1276 len++;
1277 }
1278 if (len + 2 + strlen(chips[i].name) < 78) {
1279 xf86ErrorF(" ");
1280 len++;
1281 } else {
1282 xf86ErrorF("\n\t");
1283 len = 8;
1284 }
1285 xf86ErrorF("%s", chips[i].name);
1286 len += strlen(chips[i].name);
1287 }
1288 xf86ErrorF("\n");
1289 }
1292 int
1293 xf86MatchDevice(const char *drivername, GDevPtr **sectlist)
1294 {
1295 GDevPtr gdp, *pgdp = NULL;
1296 confScreenPtr screensecptr;
1297 int i,j;
1299 if (sectlist)
1300 *sectlist = NULL;
1302 /*
1303 * This can happen when running Xorg -showopts and a module like ati
1304 * or vmware tries to load its submodules when xf86ConfigLayout is empty
1305 */
1306 if (!xf86ConfigLayout.screens)
1307 return 0;
1309 /*
1310 * This is a very important function that matches the device sections
1311 * as they show up in the config file with the drivers that the server
1312 * loads at run time.
1313 *
1314 * ChipProbe can call
1315 * int xf86MatchDevice(char * drivername, GDevPtr ** sectlist)
1316 * with its driver name. The function allocates an array of GDevPtr and
1317 * returns this via sectlist and returns the number of elements in
1318 * this list as return value. 0 means none found, -1 means fatal error.
1319 *
1320 * It can figure out which of the Device sections to use for which card
1321 * (using things like the Card statement, etc). For single headed servers
1322 * there will of course be just one such Device section.
1323 */
1324 i = 0;
1326 /*
1327 * first we need to loop over all the Screens sections to get to all
1328 * 'active' device sections
1329 */
1330 for (j=0; xf86ConfigLayout.screens[j].screen != NULL; j++) {
1331 screensecptr = xf86ConfigLayout.screens[j].screen;
1332 if ((screensecptr->device->driver != NULL)
1333 && (xf86NameCmp( screensecptr->device->driver,drivername) == 0)
1334 && (! screensecptr->device->claimed)) {
1335 /*
1336 * we have a matching driver that wasn't claimed, yet
1337 */
1338 pgdp = xnfrealloc(pgdp, (i + 2) * sizeof(GDevPtr));
1339 pgdp[i++] = screensecptr->device;
1340 }
1341 }
1343 /* Then handle the inactive devices */
1344 j = 0;
1345 while (xf86ConfigLayout.inactives[j].identifier) {
1346 gdp = &xf86ConfigLayout.inactives[j];
1347 if (gdp->driver && !gdp->claimed &&
1348 !xf86NameCmp(gdp->driver,drivername)) {
1349 /* we have a matching driver that wasn't claimed yet */
1350 pgdp = xnfrealloc(pgdp, (i + 2) * sizeof(GDevPtr));
1351 pgdp[i++] = gdp;
1352 }
1353 j++;
1354 }
1356 /*
1357 * make the array NULL terminated and return its address
1358 */
1359 if (i)
1360 pgdp[i] = NULL;
1362 if (sectlist)
1363 *sectlist = pgdp;
1364 else
1365 free(pgdp);
1366 return i;
1367 }
1369 /*
1370 * xf86GetClocks -- get the dot-clocks via a BIG BAD hack ...
1371 */
1372 void
1373 xf86GetClocks(ScrnInfoPtr pScrn, int num, Bool (*ClockFunc)(ScrnInfoPtr, int),
1374 void (*ProtectRegs)(ScrnInfoPtr, Bool),
1375 void (*BlankScreen)(ScrnInfoPtr, Bool), IOADDRESS vertsyncreg,
1376 int maskval, int knownclkindex, int knownclkvalue)
1377 {
1378 register int status = vertsyncreg;
1379 unsigned long i, cnt, rcnt, sync;
1381 /* First save registers that get written on */
1382 (*ClockFunc)(pScrn, CLK_REG_SAVE);
1384 if (num > MAXCLOCKS)
1385 num = MAXCLOCKS;
1387 for (i = 0; i < num; i++)
1388 {
1389 if (ProtectRegs)
1390 (*ProtectRegs)(pScrn, TRUE);
1391 if (!(*ClockFunc)(pScrn, i))
1392 {
1393 pScrn->clock[i] = -1;
1394 continue;
1395 }
1396 if (ProtectRegs)
1397 (*ProtectRegs)(pScrn, FALSE);
1398 if (BlankScreen)
1399 (*BlankScreen)(pScrn, FALSE);
1401 usleep(50000); /* let VCO stabilise */
1403 cnt = 0;
1404 sync = 200000;
1406 while ((inb(status) & maskval) == 0x00)
1407 if (sync-- == 0) goto finish;
1408 /* Something appears to be happening, so reset sync count */
1409 sync = 200000;
1410 while ((inb(status) & maskval) == maskval)
1411 if (sync-- == 0) goto finish;
1412 /* Something appears to be happening, so reset sync count */
1413 sync = 200000;
1414 while ((inb(status) & maskval) == 0x00)
1415 if (sync-- == 0) goto finish;
1417 for (rcnt = 0; rcnt < 5; rcnt++)
1418 {
1419 while (!(inb(status) & maskval))
1420 cnt++;
1421 while ((inb(status) & maskval))
1422 cnt++;
1423 }
1425 finish:
1426 pScrn->clock[i] = cnt ? cnt : -1;
1427 if (BlankScreen)
1428 (*BlankScreen)(pScrn, TRUE);
1429 }
1431 for (i = 0; i < num; i++)
1432 {
1433 if (i != knownclkindex)
1434 {
1435 if (pScrn->clock[i] == -1)
1436 {
1437 pScrn->clock[i] = 0;
1438 }
1439 else
1440 {
1441 pScrn->clock[i] = (int)(0.5 +
1442 (((float)knownclkvalue) * pScrn->clock[knownclkindex]) /
1443 (pScrn->clock[i]));
1444 /* Round to nearest 10KHz */
1445 pScrn->clock[i] += 5;
1446 pScrn->clock[i] /= 10;
1447 pScrn->clock[i] *= 10;
1448 }
1449 }
1450 }
1452 pScrn->clock[knownclkindex] = knownclkvalue;
1453 pScrn->numClocks = num;
1455 /* Restore registers that were written on */
1456 (*ClockFunc)(pScrn, CLK_REG_RESTORE);
1457 }
1459 const char *
1460 xf86GetVisualName(int visual)
1461 {
1462 if (visual < 0 || visual > DirectColor)
1463 return NULL;
1465 return xf86VisualNames[visual];
1466 }
1469 int
1470 xf86GetVerbosity(void)
1471 {
1472 return max(xf86Verbose, xf86LogVerbose);
1473 }
1475 Pix24Flags
1476 xf86GetPix24(void)
1477 {
1478 return xf86Info.pixmap24;
1479 }
1482 int
1483 xf86GetDepth(void)
1484 {
1485 return xf86Depth;
1486 }
1489 rgb
1490 xf86GetWeight(void)
1491 {
1492 return xf86Weight;
1493 }
1496 Gamma
1497 xf86GetGamma(void)
1498 {
1499 return xf86Gamma;
1500 }
1503 Bool
1504 xf86GetFlipPixels(void)
1505 {
1506 return xf86FlipPixels;
1507 }
1510 const char *
1511 xf86GetServerName(void)
1512 {
1513 return xf86ServerName;
1514 }
1517 Bool
1518 xf86ServerIsExiting(void)
1519 {
1520 return (dispatchException & DE_TERMINATE) == DE_TERMINATE;
1521 }
1524 Bool
1525 xf86ServerIsResetting(void)
1526 {
1527 return xf86Resetting;
1528 }
1531 Bool
1532 xf86ServerIsInitialising(void)
1533 {
1534 return xf86Initialising;
1535 }
1538 Bool
1539 xf86ServerIsOnlyDetecting(void)
1540 {
1541 return xf86DoConfigure;
1542 }
1545 Bool
1546 xf86CaughtSignal(void)
1547 {
1548 return xf86Info.caughtSignal;
1549 }
1552 Bool
1553 xf86GetVidModeAllowNonLocal(void)
1554 {
1555 return xf86Info.vidModeAllowNonLocal;
1556 }
1559 Bool
1560 xf86GetVidModeEnabled(void)
1561 {
1562 return xf86Info.vidModeEnabled;
1563 }
1565 Bool
1566 xf86GetModInDevAllowNonLocal(void)
1567 {
1568 return xf86Info.miscModInDevAllowNonLocal;
1569 }
1572 Bool
1573 xf86GetModInDevEnabled(void)
1574 {
1575 return xf86Info.miscModInDevEnabled;
1576 }
1579 Bool
1580 xf86GetAllowMouseOpenFail(void)
1581 {
1582 return xf86Info.allowMouseOpenFail;
1583 }
1586 Bool
1587 xf86IsPc98(void)
1588 {
1589 #if SUPPORT_PC98
1590 return xf86Info.pc98;
1591 #else
1592 return FALSE;
1593 #endif
1594 }
1596 void
1597 xf86DisableRandR(void)
1598 {
1599 xf86Info.disableRandR = TRUE;
1600 xf86Info.randRFrom = X_PROBED;
1601 }
1603 CARD32
1604 xf86GetModuleVersion(pointer module)
1605 {
1606 return (CARD32)LoaderGetModuleVersion(module);
1607 }
1609 pointer
1610 xf86LoadDrvSubModule(DriverPtr drv, const char *name)
1611 {
1612 pointer ret;
1613 int errmaj = 0, errmin = 0;
1615 ret = LoadSubModule(drv->module, name, NULL, NULL, NULL, NULL,
1616 &errmaj, &errmin);
1617 if (!ret)
1618 LoaderErrorMsg(NULL, name, errmaj, errmin);
1619 return ret;
1620 }
1622 pointer
1623 xf86LoadSubModule(ScrnInfoPtr pScrn, const char *name)
1624 {
1625 pointer ret;
1626 int errmaj = 0, errmin = 0;
1628 ret = LoadSubModule(pScrn->module, name, NULL, NULL, NULL, NULL,
1629 &errmaj, &errmin);
1630 if (!ret)
1631 LoaderErrorMsg(pScrn->name, name, errmaj, errmin);
1632 return ret;
1633 }
1635 /*
1636 * xf86LoadOneModule loads a single module.
1637 */
1638 pointer
1639 xf86LoadOneModule(char *name, pointer opt)
1640 {
1641 int errmaj, errmin;
1642 char *Name;
1643 pointer mod;
1645 if (!name)
1646 return NULL;
1648 /* Normalise the module name */
1649 Name = xf86NormalizeName(name);
1651 /* Skip empty names */
1652 if (Name == NULL)
1653 return NULL;
1654 if (*Name == '\0') {
1655 free(Name);
1656 return NULL;
1657 }
1659 mod = LoadModule(Name, NULL, NULL, NULL, opt, NULL, &errmaj, &errmin);
1660 if (!mod)
1661 LoaderErrorMsg(NULL, Name, errmaj, errmin);
1662 free(Name);
1663 return mod;
1664 }
1666 void
1667 xf86UnloadSubModule(pointer mod)
1668 {
1669 /*
1670 * This is disabled for now. The loader isn't smart enough yet to undo
1671 * relocations.
1672 */
1673 #if 0
1674 UnloadSubModule(mod);
1675 #endif
1676 }
1678 Bool
1679 xf86LoaderCheckSymbol(const char *name)
1680 {
1681 return LoaderSymbol(name) != NULL;
1682 }
1684 typedef enum {
1685 OPTION_BACKING_STORE
1686 } BSOpts;
1688 static const OptionInfoRec BSOptions[] = {
1689 { OPTION_BACKING_STORE, "BackingStore", OPTV_BOOLEAN, {0}, FALSE },
1690 { -1, NULL, OPTV_NONE, {0}, FALSE }
1691 };
1693 void
1694 xf86SetBackingStore(ScreenPtr pScreen)
1695 {
1696 Bool useBS = FALSE;
1697 MessageType from = X_DEFAULT;
1698 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1699 OptionInfoPtr options;
1701 options = xnfalloc(sizeof(BSOptions));
1702 (void)memcpy(options, BSOptions, sizeof(BSOptions));
1703 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
1705 /* check for commandline option here */
1706 if (xf86bsEnableFlag) {
1707 from = X_CMDLINE;
1708 useBS = TRUE;
1709 } else if (xf86bsDisableFlag) {
1710 from = X_CMDLINE;
1711 useBS = FALSE;
1712 } else {
1713 if (xf86GetOptValBool(options, OPTION_BACKING_STORE, &useBS))
1714 from = X_CONFIG;
1715 }
1716 free(options);
1717 pScreen->backingStoreSupport = useBS ? Always : NotUseful;
1718 if (serverGeneration == 1)
1719 xf86DrvMsg(pScreen->myNum, from, "Backing store %s\n",
1720 useBS ? "enabled" : "disabled");
1721 }
1724 typedef enum {
1725 OPTION_SILKEN_MOUSE
1726 } SMOpts;
1728 static const OptionInfoRec SMOptions[] = {
1729 { OPTION_SILKEN_MOUSE, "SilkenMouse", OPTV_BOOLEAN, {0}, FALSE },
1730 { -1, NULL, OPTV_NONE, {0}, FALSE }
1731 };
1733 void
1734 xf86SetSilkenMouse (ScreenPtr pScreen)
1735 {
1736 Bool useSM = TRUE;
1737 MessageType from = X_DEFAULT;
1738 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1739 OptionInfoPtr options;
1741 options = xnfalloc(sizeof(SMOptions));
1742 (void)memcpy(options, SMOptions, sizeof(SMOptions));
1743 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
1745 /* check for commandline option here */
1746 /* disable if screen shares resources */
1747 /* TODO VGA arb disable silken mouse */
1748 if (xf86silkenMouseDisableFlag) {
1749 from = X_CMDLINE;
1750 useSM = FALSE;
1751 } else {
1752 if (xf86GetOptValBool(options, OPTION_SILKEN_MOUSE, &useSM))
1753 from = X_CONFIG;
1754 }
1755 free(options);
1756 /*
1757 * XXX quick hack to report correctly for OSs that can't do SilkenMouse
1758 * yet. Should handle this differently so that alternate async methods
1759 * work correctly with this too.
1760 */
1761 pScrn->silkenMouse = useSM && xf86Info.useSIGIO && xf86SIGIOSupported();
1762 if (serverGeneration == 1)
1763 xf86DrvMsg(pScreen->myNum, from, "Silken mouse %s\n",
1764 pScrn->silkenMouse ? "enabled" : "disabled");
1765 }
1767 /* Wrote this function for the PM2 Xv driver, preliminary. */
1769 pointer
1770 xf86FindXvOptions(int scrnIndex, int adaptor_index, char *port_name,
1771 char **adaptor_name, pointer *adaptor_options)
1772 {
1773 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1774 confXvAdaptorPtr adaptor;
1775 int i;
1777 if (adaptor_index >= pScrn->confScreen->numxvadaptors) {
1778 if (adaptor_name) *adaptor_name = NULL;
1779 if (adaptor_options) *adaptor_options = NULL;
1780 return NULL;
1781 }
1783 adaptor = &pScrn->confScreen->xvadaptors[adaptor_index];
1784 if (adaptor_name) *adaptor_name = adaptor->identifier;
1785 if (adaptor_options) *adaptor_options = adaptor->options;
1787 for (i = 0; i < adaptor->numports; i++)
1788 if (!xf86NameCmp(adaptor->ports[i].identifier, port_name))
1789 return adaptor->ports[i].options;
1791 return NULL;
1792 }
1794 /* Rather than duplicate loader's get OS function, just include it directly */
1795 #define LoaderGetOS xf86GetOS
1796 #include "loader/os.c"
1798 static void
1799 xf86ConfigFbEntityInactive(EntityInfoPtr pEnt, EntityProc init,
1800 EntityProc enter, EntityProc leave, pointer private)
1801 {
1802 ScrnInfoPtr pScrn;
1804 if ((pScrn = xf86FindScreenForEntity(pEnt->index)))
1805 xf86RemoveEntityFromScreen(pScrn,pEnt->index);
1806 xf86SetEntityFuncs(pEnt->index,init,enter,leave,private);
1807 }
1809 ScrnInfoPtr
1810 xf86ConfigFbEntity(ScrnInfoPtr pScrn, int scrnFlag, int entityIndex,
1811 EntityProc init, EntityProc enter, EntityProc leave,
1812 pointer private)
1813 {
1814 EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex);
1815 if (!pEnt) return pScrn;
1817 if (!(pEnt->location.type == BUS_NONE)) {
1818 free(pEnt);
1819 return pScrn;
1820 }
1822 if (!pEnt->active) {
1823 xf86ConfigFbEntityInactive(pEnt, init, enter, leave, private);
1824 free(pEnt);
1825 return pScrn;
1826 }
1828 if (!pScrn)
1829 pScrn = xf86AllocateScreen(pEnt->driver,scrnFlag);
1830 xf86AddEntityToScreen(pScrn,entityIndex);
1832 xf86SetEntityFuncs(entityIndex,init,enter,leave,private);
1834 free(pEnt);
1835 return pScrn;
1836 }
1838 Bool
1839 xf86IsScreenPrimary(int scrnIndex)
1840 {
1841 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1842 int i;
1844 for (i=0 ; i < pScrn->numEntities; i++) {
1845 if (xf86IsEntityPrimary(i))
1846 return TRUE;
1847 }
1848 return FALSE;
1849 }
1851 int
1852 xf86RegisterRootWindowProperty(int ScrnIndex, Atom property, Atom type,
1853 int format, unsigned long len, pointer value )
1854 {
1855 RootWinPropPtr pNewProp = NULL, pRegProp;
1856 int i;
1857 Bool existing = FALSE;
1859 DebugF("xf86RegisterRootWindowProperty(%d, %ld, %ld, %d, %ld, %p)\n",
1860 ScrnIndex, property, type, format, len, value);
1862 if (ScrnIndex<0 || ScrnIndex>=xf86NumScreens) {
1863 return BadMatch;
1864 }
1866 if (xf86RegisteredPropertiesTable &&
1867 xf86RegisteredPropertiesTable[ScrnIndex]) {
1868 for (pNewProp = xf86RegisteredPropertiesTable[ScrnIndex];
1869 pNewProp; pNewProp = pNewProp->next) {
1870 if (strcmp(pNewProp->name, NameForAtom(property)) == 0)
1871 break;
1872 }
1873 }
1875 if (!pNewProp) {
1876 if ((pNewProp = (RootWinPropPtr)malloc(sizeof(RootWinProp))) == NULL) {
1877 return BadAlloc;
1878 }
1879 /*
1880 * We will put this property at the end of the list so that
1881 * the changes are made in the order they were requested.
1882 */
1883 pNewProp->next = NULL;
1884 } else {
1885 free(pNewProp->name);
1886 existing = TRUE;
1887 }
1889 pNewProp->name = xnfstrdup(NameForAtom(property));
1890 pNewProp->type = type;
1891 pNewProp->format = format;
1892 pNewProp->size = len;
1893 pNewProp->data = value;
1895 DebugF("new property filled\n");
1897 if (NULL==xf86RegisteredPropertiesTable) {
1898 DebugF("creating xf86RegisteredPropertiesTable[] size %d\n",
1899 xf86NumScreens);
1900 if ( NULL==(xf86RegisteredPropertiesTable=(RootWinPropPtr*)xnfcalloc(sizeof(RootWinProp),xf86NumScreens) )) {
1901 return BadAlloc;
1902 }
1903 for (i=0; i<xf86NumScreens; i++) {
1904 xf86RegisteredPropertiesTable[i] = NULL;
1905 }
1906 }
1908 DebugF("xf86RegisteredPropertiesTable %p\n",
1909 (void *)xf86RegisteredPropertiesTable);
1910 DebugF("xf86RegisteredPropertiesTable[%d] %p\n",
1911 ScrnIndex, (void *)xf86RegisteredPropertiesTable[ScrnIndex]);
1913 if (!existing) {
1914 if ( xf86RegisteredPropertiesTable[ScrnIndex] == NULL) {
1915 xf86RegisteredPropertiesTable[ScrnIndex] = pNewProp;
1916 } else {
1917 pRegProp = xf86RegisteredPropertiesTable[ScrnIndex];
1918 while (pRegProp->next != NULL) {
1919 DebugF("- next %p\n", (void *)pRegProp);
1920 pRegProp = pRegProp->next;
1921 }
1922 pRegProp->next = pNewProp;
1923 }
1924 }
1925 DebugF("xf86RegisterRootWindowProperty succeeded\n");
1926 return Success;
1927 }
1929 Bool
1930 xf86IsUnblank(int mode)
1931 {
1932 switch(mode) {
1933 case SCREEN_SAVER_OFF:
1934 case SCREEN_SAVER_FORCER:
1935 return TRUE;
1936 case SCREEN_SAVER_ON:
1937 case SCREEN_SAVER_CYCLE:
1938 return FALSE;
1939 default:
1940 xf86MsgVerb(X_WARNING, 0, "Unexpected save screen mode: %d\n", mode);
1941 return TRUE;
1942 }
1943 }
1945 void
1946 xf86MotionHistoryAllocate(InputInfoPtr pInfo)
1947 {
1948 AllocateMotionHistory(pInfo->dev);
1949 }