xf86Bus.c (18512B)
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 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 static screenLayoutPtr 110 xf86BusConfigMatch(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 */ 144 Bool 145 xf86BusConfig(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 239 void 240 xf86BusProbe(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 263 BusType 264 StringToBusType(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 297 int 298 xf86AllocateEntity(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 309 Bool 310 xf86IsEntityPrimary(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 335 Bool 336 xf86DriverHasEntities(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 347 void 348 xf86AddEntityToScreen(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 369 void 370 xf86SetEntityInstanceForScreen(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 */ 389 ScrnInfoPtr 390 xf86FindScreenForEntity(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 408 void 409 xf86RemoveEntityFromScreen(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 */ 428 void 429 xf86ClearEntityListForScreen(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 451 void 452 xf86AddDevToEntity(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 468 void 469 xf86RemoveDevFromEntity(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 */ 492 EntityInfoPtr 493 xf86GetEntityInfo(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 523 int 524 xf86GetNumEntityInstances(int entityIndex) 525 { 526 if (entityIndex >= xf86NumEntities) 527 return -1; 528 529 return xf86Entities[entityIndex]->numInstances; 530 } 531 532 GDevPtr 533 xf86GetDevFromEntity(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 */ 556 void 557 xf86PostProbe(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 576 Bool 577 xf86IsEntityShared(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 587 void 588 xf86SetEntityShared(int entityIndex) 589 { 590 if (entityIndex < xf86NumEntities) { 591 xf86Entities[entityIndex]->entityProp |= IS_SHARED_ACCEL; 592 } 593 } 594 595 Bool 596 xf86IsEntitySharable(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 606 void 607 xf86SetEntitySharable(int entityIndex) 608 { 609 if (entityIndex < xf86NumEntities) { 610 xf86Entities[entityIndex]->entityProp |= ACCEL_IS_SHARABLE; 611 } 612 } 613 614 Bool 615 xf86IsPrimInitDone(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 625 void 626 xf86SetPrimInitDone(int entityIndex) 627 { 628 if (entityIndex < xf86NumEntities) { 629 xf86Entities[entityIndex]->entityProp |= SA_PRIM_INIT_DONE; 630 } 631 } 632 633 void 634 xf86ClearPrimInitDone(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 645 int 646 xf86AllocateEntityPrivateIndex(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 664 DevUnion * 665 xf86GetEntityPrivate(int entityIndex, int privIndex) 666 { 667 if (entityIndex >= xf86NumEntities || privIndex >= xf86EntityPrivateCount) 668 return NULL; 669 670 return &(xf86Entities[entityIndex]->entityPrivates[privIndex]); 671 }