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