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  * This file contains the interfaces to the bus-specific code
30  */
31 
32 #ifdef HAVE_XORG_CONFIG_H
33 #include <xorg-config.h>
34 #endif
35 
36 #include <ctype.h>
37 #include <stdlib.h>
38 #include <unistd.h>
39 #include <X11/X.h>
40 #include "os.h"
41 #include "xf86.h"
42 #include "xf86Priv.h"
43 
44 /* Bus-specific headers */
45 
46 #include "xf86Bus.h"
47 
48 #define XF86_OS_PRIVS
49 #include "xf86_OSproc.h"
50 #ifdef XSERVER_LIBPCIACCESS
51 #include "xf86VGAarbiter.h"
52 #endif
53 /* Entity data */
54 EntityPtr *xf86Entities = NULL; /* Bus slots claimed by drivers */
55 int xf86NumEntities = 0;
56 static int xf86EntityPrivateCount = 0;
57 
58 BusRec primaryBus = { BUS_NONE, {0} };
59 
60 /**
61  * Call the driver's correct probe function.
62  *
63  * If the driver implements the \c DriverRec::PciProbe entry-point and an
64  * appropriate PCI device (with matching Device section in the xorg.conf file)
65  * is found, it is called.  If \c DriverRec::PciProbe or no devices can be
66  * successfully probed with it (e.g., only non-PCI devices are available),
67  * the driver's \c DriverRec::Probe function is called.
68  *
69  * \param drv   Driver to probe
70  *
71  * \return
72  * If a device can be successfully probed by the driver, \c TRUE is
73  * returned.  Otherwise, \c FALSE is returned.
74  */
75 Bool
xf86CallDriverProbe(DriverPtr drv,Bool detect_only)76 xf86CallDriverProbe(DriverPtr drv, Bool detect_only)
77 {
78     Bool foundScreen = FALSE;
79 
80 #ifdef XSERVER_PLATFORM_BUS
81     /* xf86platformBus.c does not support Xorg -configure */
82     if (!xf86DoConfigure && drv->platformProbe != NULL) {
83         foundScreen = xf86platformProbeDev(drv);
84     }
85 #endif
86 
87 #ifdef XSERVER_LIBPCIACCESS
88     if (!foundScreen && (drv->PciProbe != NULL)) {
89         if (xf86DoConfigure && xf86DoConfigurePass1) {
90             assert(detect_only);
91             foundScreen = xf86PciAddMatchingDev(drv);
92         }
93         else {
94             assert(!detect_only);
95             foundScreen = xf86PciProbeDev(drv);
96         }
97     }
98 #endif
99     if (!foundScreen && (drv->Probe != NULL)) {
100         xf86Msg(X_WARNING, "Falling back to old probe method for %s\n",
101                 drv->driverName);
102         foundScreen = (*drv->Probe) (drv, (detect_only) ? PROBE_DETECT
103                                      : PROBE_DEFAULT);
104     }
105 
106     return foundScreen;
107 }
108 
109 /**
110  * @return TRUE if all buses are configured and set up correctly and FALSE
111  * otherwise.
112  */
113 Bool
xf86BusConfig(void)114 xf86BusConfig(void)
115 {
116     screenLayoutPtr layout;
117     int i, j;
118 
119     /*
120      * 3 step probe to (hopefully) ensure that we always find at least 1
121      * (non GPU) screen:
122      *
123      * 1. Call each drivers probe function normally,
124      *    Each successful probe will result in an extra entry added to the
125      *    xf86Screens[] list for each instance of the hardware found.
126      */
127     for (i = 0; i < xf86NumDrivers; i++) {
128         xf86CallDriverProbe(xf86DriverList[i], FALSE);
129     }
130 
131     /*
132      * 2. If no Screens were found, call each drivers probe function with
133      *    ignorePrimary = TRUE, to ensure that we do actually get a
134      *    Screen if there is atleast one supported video card.
135      */
136     if (xf86NumScreens == 0) {
137         xf86ProbeIgnorePrimary = TRUE;
138         for (i = 0; i < xf86NumDrivers && xf86NumScreens == 0; i++) {
139             xf86CallDriverProbe(xf86DriverList[i], FALSE);
140         }
141         xf86ProbeIgnorePrimary = FALSE;
142     }
143 
144     /*
145      * 3. Call xf86platformAddGPUDevices() to add any additional video cards as
146      *    GPUScreens (GPUScreens are only supported by platformBus drivers).
147      */
148     for (i = 0; i < xf86NumDrivers; i++) {
149         xf86platformAddGPUDevices(xf86DriverList[i]);
150     }
151 
152     /* If nothing was detected, return now */
153     if (xf86NumScreens == 0) {
154         xf86Msg(X_ERROR, "No devices detected.\n");
155         return FALSE;
156     }
157 
158     xf86VGAarbiterInit();
159 
160     /*
161      * Match up the screens found by the probes against those specified
162      * in the config file.  Remove the ones that won't be used.  Sort
163      * them in the order specified.
164      *
165      * What is the best way to do this?
166      *
167      * For now, go through the screens allocated by the probes, and
168      * look for screen config entry which refers to the same device
169      * section as picked out by the probe.
170      *
171      */
172     for (i = 0; i < xf86NumScreens; i++) {
173         for (layout = xf86ConfigLayout.screens; layout->screen != NULL;
174              layout++) {
175             Bool found = FALSE;
176 
177             for (j = 0; j < xf86Screens[i]->numEntities; j++) {
178 
179                 GDevPtr dev =
180                     xf86GetDevFromEntity(xf86Screens[i]->entityList[j],
181                                          xf86Screens[i]->entityInstanceList[j]);
182 
183                 if (dev == layout->screen->device) {
184                     /* A match has been found */
185                     xf86Screens[i]->confScreen = layout->screen;
186                     found = TRUE;
187                     break;
188                 }
189             }
190             if (found)
191                 break;
192         }
193         if (layout->screen == NULL) {
194             /* No match found */
195             xf86Msg(X_ERROR,
196                     "Screen %d deleted because of no matching config section.\n",
197                     i);
198             xf86DeleteScreen(xf86Screens[i--]);
199         }
200     }
201 
202     /* bind GPU conf screen to protocol screen 0 */
203     for (i = 0; i < xf86NumGPUScreens; i++)
204         xf86GPUScreens[i]->confScreen = xf86Screens[0]->confScreen;
205 
206     /* If no screens left, return now.  */
207     if (xf86NumScreens == 0) {
208         xf86Msg(X_ERROR,
209                 "Device(s) detected, but none match those in the config file.\n");
210         return FALSE;
211     }
212 
213     return TRUE;
214 }
215 
216 /*
217  * Call the bus probes relevant to the architecture.
218  *
219  * The only one available so far is for PCI and SBUS.
220  */
221 
222 void
xf86BusProbe(void)223 xf86BusProbe(void)
224 {
225 #ifdef XSERVER_PLATFORM_BUS
226     xf86platformProbe();
227     if (ServerIsNotSeat0() && xf86_num_platform_devices > 0)
228         return;
229 #endif
230 #ifdef XSERVER_LIBPCIACCESS
231     xf86PciProbe();
232 #endif
233 #if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
234     xf86SbusProbe();
235 #endif
236 #ifdef XSERVER_PLATFORM_BUS
237     xf86platformPrimary();
238 #endif
239 }
240 
241 /*
242  * Determine what bus type the busID string represents.  The start of the
243  * bus-dependent part of the string is returned as retID.
244  */
245 
246 BusType
StringToBusType(const char * busID,const char ** retID)247 StringToBusType(const char *busID, const char **retID)
248 {
249     char *p, *s;
250     BusType ret = BUS_NONE;
251 
252     /* If no type field, Default to PCI */
253     if (isdigit(busID[0])) {
254         if (retID)
255             *retID = busID;
256         return BUS_PCI;
257     }
258 
259     s = xstrdup(busID);
260     p = strtok(s, ":");
261     if (p == NULL || *p == 0) {
262         free(s);
263         return BUS_NONE;
264     }
265     if (!xf86NameCmp(p, "pci") || !xf86NameCmp(p, "agp"))
266         ret = BUS_PCI;
267     if (!xf86NameCmp(p, "sbus"))
268         ret = BUS_SBUS;
269     if (!xf86NameCmp(p, "platform"))
270         ret = BUS_PLATFORM;
271     if (ret != BUS_NONE)
272         if (retID)
273             *retID = busID + strlen(p) + 1;
274     free(s);
275     return ret;
276 }
277 
278 int
xf86AllocateEntity(void)279 xf86AllocateEntity(void)
280 {
281     xf86NumEntities++;
282     xf86Entities = xnfreallocarray(xf86Entities,
283                                    xf86NumEntities, sizeof(EntityPtr));
284     xf86Entities[xf86NumEntities - 1] = xnfcalloc(1, sizeof(EntityRec));
285     xf86Entities[xf86NumEntities - 1]->entityPrivates =
286         xnfcalloc(xf86EntityPrivateCount, sizeof(DevUnion));
287     return xf86NumEntities - 1;
288 }
289 
290 Bool
xf86IsEntityPrimary(int entityIndex)291 xf86IsEntityPrimary(int entityIndex)
292 {
293     EntityPtr pEnt = xf86Entities[entityIndex];
294 
295 #ifdef XSERVER_LIBPCIACCESS
296     if (primaryBus.type == BUS_PLATFORM && pEnt->bus.type == BUS_PCI)
297 	return MATCH_PCI_DEVICES(pEnt->bus.id.pci, primaryBus.id.plat->pdev);
298 #endif
299 
300     if (primaryBus.type != pEnt->bus.type)
301         return FALSE;
302 
303     switch (pEnt->bus.type) {
304     case BUS_PCI:
305         return pEnt->bus.id.pci == primaryBus.id.pci;
306     case BUS_SBUS:
307         return pEnt->bus.id.sbus.fbNum == primaryBus.id.sbus.fbNum;
308     case BUS_PLATFORM:
309         return pEnt->bus.id.plat == primaryBus.id.plat;
310     default:
311         return FALSE;
312     }
313 }
314 
315 Bool
xf86DriverHasEntities(DriverPtr drvp)316 xf86DriverHasEntities(DriverPtr drvp)
317 {
318     int i;
319 
320     for (i = 0; i < xf86NumEntities; i++) {
321         if (xf86Entities[i]->driver == drvp)
322             return TRUE;
323     }
324     return FALSE;
325 }
326 
327 void
xf86AddEntityToScreen(ScrnInfoPtr pScrn,int entityIndex)328 xf86AddEntityToScreen(ScrnInfoPtr pScrn, int entityIndex)
329 {
330     if (entityIndex == -1)
331         return;
332     if (xf86Entities[entityIndex]->inUse &&
333         !(xf86Entities[entityIndex]->entityProp & IS_SHARED_ACCEL)) {
334         ErrorF("Requested Entity already in use!\n");
335         return;
336     }
337 
338     pScrn->numEntities++;
339     pScrn->entityList = xnfreallocarray(pScrn->entityList,
340                                         pScrn->numEntities, sizeof(int));
341     pScrn->entityList[pScrn->numEntities - 1] = entityIndex;
342     xf86Entities[entityIndex]->inUse = TRUE;
343     pScrn->entityInstanceList = xnfreallocarray(pScrn->entityInstanceList,
344                                                 pScrn->numEntities,
345                                                 sizeof(int));
346     pScrn->entityInstanceList[pScrn->numEntities - 1] = 0;
347 }
348 
349 void
xf86SetEntityInstanceForScreen(ScrnInfoPtr pScrn,int entityIndex,int instance)350 xf86SetEntityInstanceForScreen(ScrnInfoPtr pScrn, int entityIndex, int instance)
351 {
352     int i;
353 
354     if (entityIndex == -1 || entityIndex >= xf86NumEntities)
355         return;
356 
357     for (i = 0; i < pScrn->numEntities; i++) {
358         if (pScrn->entityList[i] == entityIndex) {
359             pScrn->entityInstanceList[i] = instance;
360             break;
361         }
362     }
363 }
364 
365 /*
366  * XXX  This needs to be updated for the case where a single entity may have
367  * instances associated with more than one screen.
368  */
369 ScrnInfoPtr
xf86FindScreenForEntity(int entityIndex)370 xf86FindScreenForEntity(int entityIndex)
371 {
372     int i, j;
373 
374     if (entityIndex == -1)
375         return NULL;
376 
377     if (xf86Screens) {
378         for (i = 0; i < xf86NumScreens; i++) {
379             for (j = 0; j < xf86Screens[i]->numEntities; j++) {
380                 if (xf86Screens[i]->entityList[j] == entityIndex)
381                     return xf86Screens[i];
382             }
383         }
384     }
385     return NULL;
386 }
387 
388 void
xf86RemoveEntityFromScreen(ScrnInfoPtr pScrn,int entityIndex)389 xf86RemoveEntityFromScreen(ScrnInfoPtr pScrn, int entityIndex)
390 {
391     int i;
392 
393     for (i = 0; i < pScrn->numEntities; i++) {
394         if (pScrn->entityList[i] == entityIndex) {
395             for (i++; i < pScrn->numEntities; i++)
396                 pScrn->entityList[i - 1] = pScrn->entityList[i];
397             pScrn->numEntities--;
398             xf86Entities[entityIndex]->inUse = FALSE;
399             break;
400         }
401     }
402 }
403 
404 /*
405  * xf86ClearEntityListForScreen() - called when a screen is deleted
406  * to mark it's entities unused. Called by xf86DeleteScreen().
407  */
408 void
xf86ClearEntityListForScreen(ScrnInfoPtr pScrn)409 xf86ClearEntityListForScreen(ScrnInfoPtr pScrn)
410 {
411     int i, entityIndex;
412 
413     if (pScrn->entityList == NULL || pScrn->numEntities == 0)
414         return;
415 
416     for (i = 0; i < pScrn->numEntities; i++) {
417         entityIndex = pScrn->entityList[i];
418         xf86Entities[entityIndex]->inUse = FALSE;
419         /* disable resource: call the disable function */
420     }
421     free(pScrn->entityList);
422     free(pScrn->entityInstanceList);
423     pScrn->entityList = NULL;
424     pScrn->entityInstanceList = NULL;
425 }
426 
427 /*
428  * Add an extra device section (GDevPtr) to an entity.
429  */
430 
431 void
xf86AddDevToEntity(int entityIndex,GDevPtr dev)432 xf86AddDevToEntity(int entityIndex, GDevPtr dev)
433 {
434     EntityPtr pEnt;
435 
436     if (entityIndex >= xf86NumEntities)
437         return;
438 
439     pEnt = xf86Entities[entityIndex];
440     pEnt->numInstances++;
441     pEnt->devices = xnfreallocarray(pEnt->devices,
442                                     pEnt->numInstances, sizeof(GDevPtr));
443     pEnt->devices[pEnt->numInstances - 1] = dev;
444     dev->claimed = TRUE;
445 }
446 
447 
448 void
xf86RemoveDevFromEntity(int entityIndex,GDevPtr dev)449 xf86RemoveDevFromEntity(int entityIndex, GDevPtr dev)
450 {
451     EntityPtr pEnt;
452     int i, j;
453     if (entityIndex >= xf86NumEntities)
454         return;
455 
456     pEnt = xf86Entities[entityIndex];
457     for (i = 0; i < pEnt->numInstances; i++) {
458         if (pEnt->devices[i] == dev) {
459             for (j = i; j < pEnt->numInstances - 1; j++)
460                 pEnt->devices[j] = pEnt->devices[j + 1];
461             break;
462         }
463     }
464     pEnt->numInstances--;
465     dev->claimed = FALSE;
466 }
467 /*
468  * xf86GetEntityInfo() -- This function hands information from the
469  * EntityRec struct to the drivers. The EntityRec structure itself
470  * remains invisible to the driver.
471  */
472 EntityInfoPtr
xf86GetEntityInfo(int entityIndex)473 xf86GetEntityInfo(int entityIndex)
474 {
475     EntityInfoPtr pEnt;
476     int i;
477 
478     if (entityIndex == -1)
479         return NULL;
480 
481     if (entityIndex >= xf86NumEntities)
482         return NULL;
483 
484     pEnt = xnfcalloc(1, sizeof(EntityInfoRec));
485     pEnt->index = entityIndex;
486     pEnt->location = xf86Entities[entityIndex]->bus;
487     pEnt->active = xf86Entities[entityIndex]->active;
488     pEnt->chipset = xf86Entities[entityIndex]->chipset;
489     pEnt->driver = xf86Entities[entityIndex]->driver;
490     if ((xf86Entities[entityIndex]->devices) &&
491         (xf86Entities[entityIndex]->devices[0])) {
492         for (i = 0; i < xf86Entities[entityIndex]->numInstances; i++)
493             if (xf86Entities[entityIndex]->devices[i]->screen == 0)
494                 break;
495         pEnt->device = xf86Entities[entityIndex]->devices[i];
496     }
497     else
498         pEnt->device = NULL;
499 
500     return pEnt;
501 }
502 
503 int
xf86GetNumEntityInstances(int entityIndex)504 xf86GetNumEntityInstances(int entityIndex)
505 {
506     if (entityIndex >= xf86NumEntities)
507         return -1;
508 
509     return xf86Entities[entityIndex]->numInstances;
510 }
511 
512 GDevPtr
xf86GetDevFromEntity(int entityIndex,int instance)513 xf86GetDevFromEntity(int entityIndex, int instance)
514 {
515     int i;
516 
517     /* We might not use AddDevtoEntity */
518     if ((!xf86Entities[entityIndex]->devices) ||
519         (!xf86Entities[entityIndex]->devices[0]))
520         return NULL;
521 
522     if (entityIndex >= xf86NumEntities ||
523         instance >= xf86Entities[entityIndex]->numInstances)
524         return NULL;
525 
526     for (i = 0; i < xf86Entities[entityIndex]->numInstances; i++)
527         if (xf86Entities[entityIndex]->devices[i]->screen == instance)
528             return xf86Entities[entityIndex]->devices[i];
529     return NULL;
530 }
531 
532 /*
533  * xf86PostProbe() -- Allocate all non conflicting resources
534  * This function gets called by xf86Init().
535  */
536 void
xf86PostProbe(void)537 xf86PostProbe(void)
538 {
539     if (fbSlotClaimed && (
540 #if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
541                              sbusSlotClaimed ||
542 #endif
543 #ifdef XSERVER_PLATFORM_BUS
544                              platformSlotClaimed ||
545 #endif
546 #ifdef XSERVER_LIBPCIACCESS
547                              pciSlotClaimed
548 #else
549                              TRUE
550 #endif
551         ))
552         FatalError("Cannot run in framebuffer mode. Please specify busIDs "
553                    "       for all framebuffer devices\n");
554 }
555 
556 int
xf86GetLastScrnFlag(int entityIndex)557 xf86GetLastScrnFlag(int entityIndex)
558 {
559     if (entityIndex < xf86NumEntities) {
560         return xf86Entities[entityIndex]->lastScrnFlag;
561     }
562     else {
563         return -1;
564     }
565 }
566 
567 void
xf86SetLastScrnFlag(int entityIndex,int scrnIndex)568 xf86SetLastScrnFlag(int entityIndex, int scrnIndex)
569 {
570     if (entityIndex < xf86NumEntities) {
571         xf86Entities[entityIndex]->lastScrnFlag = scrnIndex;
572     }
573 }
574 
575 Bool
xf86IsEntityShared(int entityIndex)576 xf86IsEntityShared(int entityIndex)
577 {
578     if (entityIndex < xf86NumEntities) {
579         if (xf86Entities[entityIndex]->entityProp & IS_SHARED_ACCEL) {
580             return TRUE;
581         }
582     }
583     return FALSE;
584 }
585 
586 void
xf86SetEntityShared(int entityIndex)587 xf86SetEntityShared(int entityIndex)
588 {
589     if (entityIndex < xf86NumEntities) {
590         xf86Entities[entityIndex]->entityProp |= IS_SHARED_ACCEL;
591     }
592 }
593 
594 Bool
xf86IsEntitySharable(int entityIndex)595 xf86IsEntitySharable(int entityIndex)
596 {
597     if (entityIndex < xf86NumEntities) {
598         if (xf86Entities[entityIndex]->entityProp & ACCEL_IS_SHARABLE) {
599             return TRUE;
600         }
601     }
602     return FALSE;
603 }
604 
605 void
xf86SetEntitySharable(int entityIndex)606 xf86SetEntitySharable(int entityIndex)
607 {
608     if (entityIndex < xf86NumEntities) {
609         xf86Entities[entityIndex]->entityProp |= ACCEL_IS_SHARABLE;
610     }
611 }
612 
613 Bool
xf86IsPrimInitDone(int entityIndex)614 xf86IsPrimInitDone(int entityIndex)
615 {
616     if (entityIndex < xf86NumEntities) {
617         if (xf86Entities[entityIndex]->entityProp & SA_PRIM_INIT_DONE) {
618             return TRUE;
619         }
620     }
621     return FALSE;
622 }
623 
624 void
xf86SetPrimInitDone(int entityIndex)625 xf86SetPrimInitDone(int entityIndex)
626 {
627     if (entityIndex < xf86NumEntities) {
628         xf86Entities[entityIndex]->entityProp |= SA_PRIM_INIT_DONE;
629     }
630 }
631 
632 void
xf86ClearPrimInitDone(int entityIndex)633 xf86ClearPrimInitDone(int entityIndex)
634 {
635     if (entityIndex < xf86NumEntities) {
636         xf86Entities[entityIndex]->entityProp &= ~SA_PRIM_INIT_DONE;
637     }
638 }
639 
640 /*
641  * Allocate a private in the entities.
642  */
643 
644 int
xf86AllocateEntityPrivateIndex(void)645 xf86AllocateEntityPrivateIndex(void)
646 {
647     int idx, i;
648     EntityPtr pEnt;
649     DevUnion *nprivs;
650 
651     idx = xf86EntityPrivateCount++;
652     for (i = 0; i < xf86NumEntities; i++) {
653         pEnt = xf86Entities[i];
654         nprivs = xnfreallocarray(pEnt->entityPrivates,
655                                  xf86EntityPrivateCount, sizeof(DevUnion));
656         /* Zero the new private */
657         memset(&nprivs[idx], 0, sizeof(DevUnion));
658         pEnt->entityPrivates = nprivs;
659     }
660     return idx;
661 }
662 
663 DevUnion *
xf86GetEntityPrivate(int entityIndex,int privIndex)664 xf86GetEntityPrivate(int entityIndex, int privIndex)
665 {
666     if (entityIndex >= xf86NumEntities || privIndex >= xf86EntityPrivateCount)
667         return NULL;
668 
669     return &(xf86Entities[entityIndex]->entityPrivates[privIndex]);
670 }
671