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