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