xf86Bus.c revision 7e31ba66
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 */
54EntityPtr *xf86Entities = NULL; /* Bus slots claimed by drivers */
55int xf86NumEntities = 0;
56static int xf86EntityPrivateCount = 0;
57
58BusRec 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 */
75Bool
76xf86CallDriverProbe(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 */
113Bool
114xf86BusConfig(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
222void
223xf86BusProbe(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
246BusType
247StringToBusType(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
278int
279xf86AllocateEntity(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
290Bool
291xf86IsEntityPrimary(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
315Bool
316xf86DriverHasEntities(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
327void
328xf86AddEntityToScreen(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
349void
350xf86SetEntityInstanceForScreen(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 */
369ScrnInfoPtr
370xf86FindScreenForEntity(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
388void
389xf86RemoveEntityFromScreen(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 */
408void
409xf86ClearEntityListForScreen(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
431void
432xf86AddDevToEntity(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
448void
449xf86RemoveDevFromEntity(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 */
472EntityInfoPtr
473xf86GetEntityInfo(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
503int
504xf86GetNumEntityInstances(int entityIndex)
505{
506    if (entityIndex >= xf86NumEntities)
507        return -1;
508
509    return xf86Entities[entityIndex]->numInstances;
510}
511
512GDevPtr
513xf86GetDevFromEntity(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            break;
529    return xf86Entities[entityIndex]->devices[i];
530}
531
532/*
533 * xf86PostProbe() -- Allocate all non conflicting resources
534 * This function gets called by xf86Init().
535 */
536void
537xf86PostProbe(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
556int
557xf86GetLastScrnFlag(int entityIndex)
558{
559    if (entityIndex < xf86NumEntities) {
560        return xf86Entities[entityIndex]->lastScrnFlag;
561    }
562    else {
563        return -1;
564    }
565}
566
567void
568xf86SetLastScrnFlag(int entityIndex, int scrnIndex)
569{
570    if (entityIndex < xf86NumEntities) {
571        xf86Entities[entityIndex]->lastScrnFlag = scrnIndex;
572    }
573}
574
575Bool
576xf86IsEntityShared(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
586void
587xf86SetEntityShared(int entityIndex)
588{
589    if (entityIndex < xf86NumEntities) {
590        xf86Entities[entityIndex]->entityProp |= IS_SHARED_ACCEL;
591    }
592}
593
594Bool
595xf86IsEntitySharable(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
605void
606xf86SetEntitySharable(int entityIndex)
607{
608    if (entityIndex < xf86NumEntities) {
609        xf86Entities[entityIndex]->entityProp |= ACCEL_IS_SHARABLE;
610    }
611}
612
613Bool
614xf86IsPrimInitDone(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
624void
625xf86SetPrimInitDone(int entityIndex)
626{
627    if (entityIndex < xf86NumEntities) {
628        xf86Entities[entityIndex]->entityProp |= SA_PRIM_INIT_DONE;
629    }
630}
631
632void
633xf86ClearPrimInitDone(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
644int
645xf86AllocateEntityPrivateIndex(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
663DevUnion *
664xf86GetEntityPrivate(int entityIndex, int privIndex)
665{
666    if (entityIndex >= xf86NumEntities || privIndex >= xf86EntityPrivateCount)
667        return NULL;
668
669    return &(xf86Entities[entityIndex]->entityPrivates[privIndex]);
670}
671