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