xf86Bus.c revision d44ca368
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 109/** 110 * @return TRUE if all buses are configured and set up correctly and FALSE 111 * otherwise. 112 */ 113Bool 114xf86BusConfig(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 222void 223xf86BusProbe(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 246BusType 247StringToBusType(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 278int 279xf86AllocateEntity(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 290Bool 291xf86IsEntityPrimary(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 315Bool 316xf86DriverHasEntities(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 327void 328xf86AddEntityToScreen(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 349void 350xf86SetEntityInstanceForScreen(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 */ 369ScrnInfoPtr 370xf86FindScreenForEntity(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 388void 389xf86RemoveEntityFromScreen(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 */ 408void 409xf86ClearEntityListForScreen(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 431void 432xf86AddDevToEntity(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 448void 449xf86RemoveDevFromEntity(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 */ 472EntityInfoPtr 473xf86GetEntityInfo(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 503int 504xf86GetNumEntityInstances(int entityIndex) 505{ 506 if (entityIndex >= xf86NumEntities) 507 return -1; 508 509 return xf86Entities[entityIndex]->numInstances; 510} 511 512GDevPtr 513xf86GetDevFromEntity(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 */ 536void 537xf86PostProbe(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 556int 557xf86GetLastScrnFlag(int entityIndex) 558{ 559 if (entityIndex < xf86NumEntities) { 560 return xf86Entities[entityIndex]->lastScrnFlag; 561 } 562 else { 563 return -1; 564 } 565} 566 567void 568xf86SetLastScrnFlag(int entityIndex, int scrnIndex) 569{ 570 if (entityIndex < xf86NumEntities) { 571 xf86Entities[entityIndex]->lastScrnFlag = scrnIndex; 572 } 573} 574 575Bool 576xf86IsEntityShared(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 586void 587xf86SetEntityShared(int entityIndex) 588{ 589 if (entityIndex < xf86NumEntities) { 590 xf86Entities[entityIndex]->entityProp |= IS_SHARED_ACCEL; 591 } 592} 593 594Bool 595xf86IsEntitySharable(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 605void 606xf86SetEntitySharable(int entityIndex) 607{ 608 if (entityIndex < xf86NumEntities) { 609 xf86Entities[entityIndex]->entityProp |= ACCEL_IS_SHARABLE; 610 } 611} 612 613Bool 614xf86IsPrimInitDone(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 624void 625xf86SetPrimInitDone(int entityIndex) 626{ 627 if (entityIndex < xf86NumEntities) { 628 xf86Entities[entityIndex]->entityProp |= SA_PRIM_INIT_DONE; 629 } 630} 631 632void 633xf86ClearPrimInitDone(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 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 = 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 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