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