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