xf86Bus.c revision 4202a189
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    xf86EnterServerState(SETUP);
489}
490
491void
492xf86AccessLeave(void)
493{
494    int i;
495
496    for (i = 0; i < xf86NumEntities; i++)
497        if (xf86Entities[i]->entityLeave)
498		xf86Entities[i]->entityLeave(i,xf86Entities[i]->private);
499}
500
501/*
502 * xf86EnterServerState() -- set state the server is in.
503 */
504
505typedef enum { TRI_UNSET, TRI_TRUE, TRI_FALSE } TriState;
506
507void
508xf86EnterServerState(xf86State state)
509{
510    static int sigio_state;
511    static TriState sigio_blocked = TRI_UNSET;
512
513    /*
514     * This is a good place to block SIGIO during SETUP state. SIGIO should be
515     * blocked in SETUP state otherwise (u)sleep() might get interrupted
516     * early. We take care not to call xf86BlockSIGIO() twice.
517     */
518    if ((state == SETUP) && (sigio_blocked != TRI_TRUE)) {
519        sigio_state = xf86BlockSIGIO();
520	sigio_blocked = TRI_TRUE;
521    } else if ((state == OPERATING) && (sigio_blocked != TRI_UNSET)) {
522        xf86UnblockSIGIO(sigio_state);
523        sigio_blocked = TRI_FALSE;
524    }
525}
526
527/*
528 * xf86PostProbe() -- Allocate all non conflicting resources
529 * This function gets called by xf86Init().
530 */
531void
532xf86PostProbe(void)
533{
534    int i;
535
536    if (fbSlotClaimed && (pciSlotClaimed
537#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
538	    || sbusSlotClaimed
539#endif
540	    ))
541	    FatalError("Cannot run in framebuffer mode. Please specify busIDs "
542		       "       for all framebuffer devices\n");
543
544    for (i = 0; i < xf86NumEntities; i++)
545        if (xf86Entities[i]->entityInit)
546	    xf86Entities[i]->entityInit(i,xf86Entities[i]->private);
547}
548
549void
550xf86PostScreenInit(void)
551{
552    xf86VGAarbiterWrapFunctions();
553    xf86EnterServerState(OPERATING);
554}
555
556int
557xf86GetLastScrnFlag(int entityIndex)
558{
559    if(entityIndex < xf86NumEntities) {
560        return xf86Entities[entityIndex]->lastScrnFlag;
561    } else {
562        return -1;
563    }
564}
565
566void
567xf86SetLastScrnFlag(int entityIndex, int scrnIndex)
568{
569    if(entityIndex < xf86NumEntities) {
570        xf86Entities[entityIndex]->lastScrnFlag = scrnIndex;
571    }
572}
573
574Bool
575xf86IsEntityShared(int entityIndex)
576{
577    if(entityIndex < xf86NumEntities) {
578        if(xf86Entities[entityIndex]->entityProp & IS_SHARED_ACCEL) {
579	    return TRUE;
580	}
581    }
582    return FALSE;
583}
584
585void
586xf86SetEntityShared(int entityIndex)
587{
588    if(entityIndex < xf86NumEntities) {
589        xf86Entities[entityIndex]->entityProp |= IS_SHARED_ACCEL;
590    }
591}
592
593Bool
594xf86IsEntitySharable(int entityIndex)
595{
596    if(entityIndex < xf86NumEntities) {
597        if(xf86Entities[entityIndex]->entityProp & ACCEL_IS_SHARABLE) {
598	    return TRUE;
599	}
600    }
601    return FALSE;
602}
603
604void
605xf86SetEntitySharable(int entityIndex)
606{
607    if(entityIndex < xf86NumEntities) {
608        xf86Entities[entityIndex]->entityProp |= ACCEL_IS_SHARABLE;
609    }
610}
611
612Bool
613xf86IsPrimInitDone(int entityIndex)
614{
615    if(entityIndex < xf86NumEntities) {
616        if(xf86Entities[entityIndex]->entityProp & SA_PRIM_INIT_DONE) {
617	    return TRUE;
618	}
619    }
620    return FALSE;
621}
622
623void
624xf86SetPrimInitDone(int entityIndex)
625{
626    if(entityIndex < xf86NumEntities) {
627        xf86Entities[entityIndex]->entityProp |= SA_PRIM_INIT_DONE;
628    }
629}
630
631void
632xf86ClearPrimInitDone(int entityIndex)
633{
634    if(entityIndex < xf86NumEntities) {
635        xf86Entities[entityIndex]->entityProp &= ~SA_PRIM_INIT_DONE;
636    }
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 = xnfrealloc(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
672