xf86Bus.c revision 8aefa95b
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#include "xf86Resources.h" 44 45/* Bus-specific headers */ 46 47#include "xf86Bus.h" 48 49#define XF86_OS_PRIVS 50#define NEED_OS_RAC_PROTOS 51#include "xf86_OSproc.h" 52 53#include "xf86RAC.h" 54#include "Pci.h" 55 56/* Entity data */ 57EntityPtr *xf86Entities = NULL; /* Bus slots claimed by drivers */ 58int xf86NumEntities = 0; 59static int xf86EntityPrivateCount = 0; 60BusAccPtr xf86BusAccInfo = NULL; 61 62static void 63noopEnableDisable(void *arg) { } 64 65xf86AccessRec AccessNULL = { noopEnableDisable, noopEnableDisable, NULL }; 66 67xf86CurrentAccessRec xf86CurrentAccess = {NULL,NULL}; 68 69BusRec primaryBus = { BUS_NONE, {0}}; 70 71static Bool xf86ResAccessEnter = FALSE; 72 73 74/* resource lists */ 75resPtr Acc = NULL; 76 77/* predefined special resources */ 78_X_EXPORT resRange resVgaExclusive[] = {_VGA_EXCLUSIVE, _END}; 79_X_EXPORT resRange resVgaShared[] = {_VGA_SHARED, _END}; 80_X_EXPORT resRange resVgaMemShared[] = {_VGA_SHARED_MEM,_END}; 81_X_EXPORT resRange resVgaIoShared[] = {_VGA_SHARED_IO,_END}; 82_X_EXPORT resRange resVgaUnusedExclusive[] = {_VGA_EXCLUSIVE_UNUSED, _END}; 83_X_EXPORT resRange resVgaUnusedShared[] = {_VGA_SHARED_UNUSED, _END}; 84_X_EXPORT resRange resVgaSparseExclusive[] = {_VGA_EXCLUSIVE_SPARSE, _END}; 85_X_EXPORT resRange resVgaSparseShared[] = {_VGA_SHARED_SPARSE, _END}; 86_X_EXPORT resRange res8514Exclusive[] = {_8514_EXCLUSIVE, _END}; 87_X_EXPORT resRange res8514Shared[] = {_8514_SHARED, _END}; 88 89/* Flag: do we need RAC ? */ 90static Bool needRAC = FALSE; 91static Bool doFramebufferMode = FALSE; 92 93/* state change notification callback list */ 94static StateChangeNotificationPtr StateChangeNotificationList; 95static void notifyStateChange(xf86NotifyState state); 96 97/* 98 * Call the bus probes relevant to the architecture. 99 * 100 * The only one available so far is for PCI and SBUS. 101 */ 102 103void 104xf86BusProbe(void) 105{ 106 xf86PciProbe(); 107#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) 108 xf86SbusProbe(); 109#endif 110} 111 112/* 113 * Determine what bus type the busID string represents. The start of the 114 * bus-dependent part of the string is returned as retID. 115 */ 116 117BusType 118StringToBusType(const char* busID, const char **retID) 119{ 120 char *p, *s; 121 BusType ret = BUS_NONE; 122 123 /* If no type field, Default to PCI */ 124 if (isdigit(busID[0])) { 125 if (retID) 126 *retID = busID; 127 return BUS_PCI; 128 } 129 130 s = xstrdup(busID); 131 p = strtok(s, ":"); 132 if (p == NULL || *p == 0) { 133 xfree(s); 134 return BUS_NONE; 135 } 136 if (!xf86NameCmp(p, "pci") || !xf86NameCmp(p, "agp")) 137 ret = BUS_PCI; 138 if (!xf86NameCmp(p, "sbus")) 139 ret = BUS_SBUS; 140 if (ret != BUS_NONE) 141 if (retID) 142 *retID = busID + strlen(p) + 1; 143 xfree(s); 144 return ret; 145} 146 147/* 148 * Entity related code. 149 */ 150 151void 152xf86EntityInit(void) 153{ 154 int i; 155 xf86AccessPtr pacc; 156 157 for (i = 0; i < xf86NumEntities; i++) 158 if (xf86Entities[i]->entityInit) { 159 if (xf86Entities[i]->access->busAcc) 160 ((BusAccPtr)xf86Entities[i]->access->busAcc)->set_f 161 (xf86Entities[i]->access->busAcc); 162 pacc = xf86Entities[i]->access->fallback; 163 pacc->AccessEnable(pacc->arg); 164 xf86Entities[i]->entityInit(i,xf86Entities[i]->private); 165 pacc->AccessDisable(pacc->arg); 166 } 167} 168 169int 170xf86AllocateEntity(void) 171{ 172 xf86NumEntities++; 173 xf86Entities = xnfrealloc(xf86Entities, 174 sizeof(EntityPtr) * xf86NumEntities); 175 xf86Entities[xf86NumEntities - 1] = xnfcalloc(1,sizeof(EntityRec)); 176 xf86Entities[xf86NumEntities - 1]->entityPrivates = 177 xnfcalloc(sizeof(DevUnion) * xf86EntityPrivateCount, 1); 178 return (xf86NumEntities - 1); 179} 180 181static void 182EntityEnter(void) 183{ 184 int i; 185 xf86AccessPtr pacc; 186 187 for (i = 0; i < xf86NumEntities; i++) 188 if (xf86Entities[i]->entityEnter) { 189 if (xf86Entities[i]->access->busAcc) 190 ((BusAccPtr)xf86Entities[i]->access->busAcc)->set_f 191 (xf86Entities[i]->access->busAcc); 192 pacc = xf86Entities[i]->access->fallback; 193 pacc->AccessEnable(pacc->arg); 194 xf86Entities[i]->entityEnter(i,xf86Entities[i]->private); 195 pacc->AccessDisable(pacc->arg); 196 } 197} 198 199static void 200EntityLeave(void) 201{ 202 int i; 203 xf86AccessPtr pacc; 204 205 for (i = 0; i < xf86NumEntities; i++) 206 if (xf86Entities[i]->entityLeave) { 207 if (xf86Entities[i]->access->busAcc) 208 ((BusAccPtr)xf86Entities[i]->access->busAcc)->set_f 209 (xf86Entities[i]->access->busAcc); 210 pacc = xf86Entities[i]->access->fallback; 211 pacc->AccessEnable(pacc->arg); 212 xf86Entities[i]->entityLeave(i,xf86Entities[i]->private); 213 pacc->AccessDisable(pacc->arg); 214 } 215} 216 217_X_EXPORT Bool 218xf86IsEntityPrimary(int entityIndex) 219{ 220 EntityPtr pEnt = xf86Entities[entityIndex]; 221 222 if (primaryBus.type != pEnt->busType) return FALSE; 223 224 switch (pEnt->busType) { 225 case BUS_PCI: 226 return (pEnt->bus.id.pci == primaryBus.id.pci); 227 case BUS_SBUS: 228 return (pEnt->sbusBusId.fbNum == primaryBus.id.sbus.fbNum); 229 default: 230 return FALSE; 231 } 232} 233 234Bool 235xf86SetEntityFuncs(int entityIndex, EntityProc init, EntityProc enter, 236 EntityProc leave, pointer private) 237{ 238 if (entityIndex >= xf86NumEntities) 239 return FALSE; 240 xf86Entities[entityIndex]->entityInit = init; 241 xf86Entities[entityIndex]->entityEnter = enter; 242 xf86Entities[entityIndex]->entityLeave = leave; 243 xf86Entities[entityIndex]->private = private; 244 return TRUE; 245} 246 247Bool 248xf86DriverHasEntities(DriverPtr drvp) 249{ 250 int i; 251 for (i = 0; i < xf86NumEntities; i++) { 252 if (xf86Entities[i]->driver == drvp) 253 return TRUE; 254 } 255 return FALSE; 256} 257 258_X_EXPORT void 259xf86AddEntityToScreen(ScrnInfoPtr pScrn, int entityIndex) 260{ 261 if (entityIndex == -1) 262 return; 263 if (xf86Entities[entityIndex]->inUse && 264 !(xf86Entities[entityIndex]->entityProp & IS_SHARED_ACCEL)) { 265 ErrorF("Requested Entity already in use!\n"); 266 return; 267 } 268 269 pScrn->numEntities++; 270 pScrn->entityList = xnfrealloc(pScrn->entityList, 271 pScrn->numEntities * sizeof(int)); 272 pScrn->entityList[pScrn->numEntities - 1] = entityIndex; 273 xf86Entities[entityIndex]->access->next = pScrn->access; 274 pScrn->access = xf86Entities[entityIndex]->access; 275 xf86Entities[entityIndex]->inUse = TRUE; 276 pScrn->entityInstanceList = xnfrealloc(pScrn->entityInstanceList, 277 pScrn->numEntities * sizeof(int)); 278 pScrn->entityInstanceList[pScrn->numEntities - 1] = 0; 279 pScrn->domainIOBase = xf86Entities[entityIndex]->domainIO; 280} 281 282_X_EXPORT void 283xf86SetEntityInstanceForScreen(ScrnInfoPtr pScrn, int entityIndex, int instance) 284{ 285 int i; 286 287 if (entityIndex == -1 || entityIndex >= xf86NumEntities) 288 return; 289 290 for (i = 0; i < pScrn->numEntities; i++) { 291 if (pScrn->entityList[i] == entityIndex) { 292 pScrn->entityInstanceList[i] = instance; 293 break; 294 } 295 } 296} 297 298/* 299 * XXX This needs to be updated for the case where a single entity may have 300 * instances associated with more than one screen. 301 */ 302_X_EXPORT ScrnInfoPtr 303xf86FindScreenForEntity(int entityIndex) 304{ 305 int i,j; 306 307 if (entityIndex == -1) return NULL; 308 309 if (xf86Screens) { 310 for (i = 0; i < xf86NumScreens; i++) { 311 for (j = 0; j < xf86Screens[i]->numEntities; j++) { 312 if ( xf86Screens[i]->entityList[j] == entityIndex ) 313 return (xf86Screens[i]); 314 } 315 } 316 } 317 return NULL; 318} 319 320_X_EXPORT void 321xf86RemoveEntityFromScreen(ScrnInfoPtr pScrn, int entityIndex) 322{ 323 int i; 324 EntityAccessPtr *ptr = (EntityAccessPtr *)&pScrn->access; 325 EntityAccessPtr peacc; 326 327 for (i = 0; i < pScrn->numEntities; i++) { 328 if (pScrn->entityList[i] == entityIndex) { 329 peacc = xf86Entities[pScrn->entityList[i]]->access; 330 (*ptr) = peacc->next; 331 /* disable entity: call disable func */ 332 if (peacc->pAccess) 333 peacc->pAccess->AccessDisable(peacc->pAccess->arg); 334 /* also disable fallback - just in case */ 335 if (peacc->fallback) 336 peacc->fallback->AccessDisable(peacc->fallback->arg); 337 for (i++; i < pScrn->numEntities; i++) 338 pScrn->entityList[i-1] = pScrn->entityList[i]; 339 pScrn->numEntities--; 340 xf86Entities[entityIndex]->inUse = FALSE; 341 break; 342 } 343 ptr = &(xf86Entities[pScrn->entityList[i]]->access->next); 344 } 345} 346 347/* 348 * xf86ClearEntitiesForScreen() - called when a screen is deleted 349 * to mark it's entities unused. Called by xf86DeleteScreen(). 350 */ 351void 352xf86ClearEntityListForScreen(int scrnIndex) 353{ 354 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 355 EntityAccessPtr peacc; 356 int i, entityIndex; 357 358 if (pScrn->entityList == NULL || pScrn->numEntities == 0) return; 359 360 for (i = 0; i < pScrn->numEntities; i++) { 361 entityIndex = pScrn->entityList[i]; 362 xf86Entities[entityIndex]->inUse = FALSE; 363 /* disable resource: call the disable function */ 364 peacc = xf86Entities[entityIndex]->access; 365 if (peacc->pAccess) 366 peacc->pAccess->AccessDisable(peacc->pAccess->arg); 367 /* and the fallback function */ 368 if (peacc->fallback) 369 peacc->fallback->AccessDisable(peacc->fallback->arg); 370 /* shared resources are only needed when entity is active: remove */ 371 xf86DeallocateResourcesForEntity(entityIndex, ResShared); 372 } 373 xfree(pScrn->entityList); 374 xfree(pScrn->entityInstanceList); 375 if (pScrn->CurrentAccess->pIoAccess == (EntityAccessPtr)pScrn->access) 376 pScrn->CurrentAccess->pIoAccess = NULL; 377 if (pScrn->CurrentAccess->pMemAccess == (EntityAccessPtr)pScrn->access) 378 pScrn->CurrentAccess->pMemAccess = NULL; 379 pScrn->entityList = NULL; 380 pScrn->entityInstanceList = NULL; 381} 382 383void 384xf86DeallocateResourcesForEntity(int entityIndex, unsigned long type) 385{ 386 resPtr *pprev_next = &Acc; 387 resPtr res = Acc; 388 389 while (res) { 390 if (res->entityIndex == entityIndex && 391 (type & ResAccMask & res->res_type)) 392 { 393 (*pprev_next) = res->next; 394 xfree(res); 395 } else 396 pprev_next = &(res->next); 397 res = (*pprev_next); 398 } 399} 400 401/* 402 * Add an extra device section (GDevPtr) to an entity. 403 */ 404 405void 406xf86AddDevToEntity(int entityIndex, GDevPtr dev) 407{ 408 EntityPtr pEnt; 409 410 if (entityIndex >= xf86NumEntities) 411 return; 412 413 pEnt = xf86Entities[entityIndex]; 414 pEnt->numInstances++; 415 pEnt->devices = xnfrealloc(pEnt->devices, 416 pEnt->numInstances * sizeof(GDevPtr)); 417 pEnt->devices[pEnt->numInstances - 1] = dev; 418 dev->claimed = TRUE; 419} 420 421/* 422 * xf86GetEntityInfo() -- This function hands information from the 423 * EntityRec struct to the drivers. The EntityRec structure itself 424 * remains invisible to the driver. 425 */ 426_X_EXPORT EntityInfoPtr 427xf86GetEntityInfo(int entityIndex) 428{ 429 EntityInfoPtr pEnt; 430 int i; 431 432 if (entityIndex >= xf86NumEntities) 433 return NULL; 434 435 pEnt = xnfcalloc(1,sizeof(EntityInfoRec)); 436 pEnt->index = entityIndex; 437 pEnt->location = xf86Entities[entityIndex]->bus; 438 pEnt->active = xf86Entities[entityIndex]->active; 439 pEnt->chipset = xf86Entities[entityIndex]->chipset; 440 pEnt->resources = xf86Entities[entityIndex]->resources; 441 pEnt->driver = xf86Entities[entityIndex]->driver; 442 if ( (xf86Entities[entityIndex]->devices) && 443 (xf86Entities[entityIndex]->devices[0]) ) { 444 for (i = 0; i < xf86Entities[entityIndex]->numInstances; i++) 445 if (xf86Entities[entityIndex]->devices[i]->screen == 0) 446 break; 447 pEnt->device = xf86Entities[entityIndex]->devices[i]; 448 } else 449 pEnt->device = NULL; 450 451 return pEnt; 452} 453 454_X_EXPORT int 455xf86GetNumEntityInstances(int entityIndex) 456{ 457 if (entityIndex >= xf86NumEntities) 458 return -1; 459 460 return xf86Entities[entityIndex]->numInstances; 461} 462 463_X_EXPORT GDevPtr 464xf86GetDevFromEntity(int entityIndex, int instance) 465{ 466 int i; 467 468 /* We might not use AddDevtoEntity */ 469 if ( (!xf86Entities[entityIndex]->devices) || 470 (!xf86Entities[entityIndex]->devices[0]) ) 471 return NULL; 472 473 if (entityIndex >= xf86NumEntities || 474 instance >= xf86Entities[entityIndex]->numInstances) 475 return NULL; 476 477 for (i = 0; i < xf86Entities[entityIndex]->numInstances; i++) 478 if (xf86Entities[entityIndex]->devices[i]->screen == instance) 479 break; 480 return xf86Entities[entityIndex]->devices[i]; 481} 482 483/* 484 * general generic disable function. 485 */ 486static void 487disableAccess(void) 488{ 489 int i; 490 xf86AccessPtr pacc; 491 EntityAccessPtr peacc; 492 493 /* call disable funcs and reset current access pointer */ 494 /* the entity specific access funcs are in an enabled */ 495 /* state - driver must restore their state explicitely */ 496 for (i = 0; i < xf86NumScreens; i++) { 497 peacc = xf86Screens[i]->CurrentAccess->pIoAccess; 498 while (peacc) { 499 if (peacc->pAccess) 500 peacc->pAccess->AccessDisable(peacc->pAccess->arg); 501 peacc = peacc->next; 502 } 503 xf86Screens[i]->CurrentAccess->pIoAccess = NULL; 504 peacc = xf86Screens[i]->CurrentAccess->pMemAccess; 505 while (peacc) { 506 if (peacc->pAccess) 507 peacc->pAccess->AccessDisable(peacc->pAccess->arg); 508 peacc = peacc->next; 509 } 510 xf86Screens[i]->CurrentAccess->pMemAccess = NULL; 511 } 512 /* then call the generic entity disable funcs */ 513 for (i = 0; i < xf86NumEntities; i++) { 514 pacc = xf86Entities[i]->access->fallback; 515 pacc->AccessDisable(pacc->arg); 516 } 517} 518 519static void 520clearAccess(void) 521{ 522 int i; 523 524 /* call disable funcs and reset current access pointer */ 525 /* the entity specific access funcs are in an enabled */ 526 /* state - driver must restore their state explicitely */ 527 for (i = 0; i < xf86NumScreens; i++) { 528 xf86Screens[i]->CurrentAccess->pIoAccess = NULL; 529 xf86Screens[i]->CurrentAccess->pMemAccess = NULL; 530 } 531 532} 533 534/* 535 * Generic interface to bus specific code - add other buses here 536 */ 537 538/* 539 * xf86AccessInit() - set up everything needed for access control 540 * called only once on first server generation. 541 */ 542void 543xf86AccessInit(void) 544{ 545 initPciState(); 546 initPciBusState(); 547 DisablePciBusAccess(); 548 DisablePciAccess(); 549 550 xf86ResAccessEnter = TRUE; 551} 552 553/* 554 * xf86AccessEnter() -- gets called to save the text mode VGA IO 555 * resources when reentering the server after a VT switch. 556 */ 557void 558xf86AccessEnter(void) 559{ 560 if (xf86ResAccessEnter) 561 return; 562 563 /* 564 * on enter we simply disable routing of special resources 565 * to any bus and let the RAC code to "open" the right bridges. 566 */ 567 PciBusStateEnter(); 568 DisablePciBusAccess(); 569 PciStateEnter(); 570 disableAccess(); 571 EntityEnter(); 572 notifyStateChange(NOTIFY_ENTER); 573 xf86EnterServerState(SETUP); 574 xf86ResAccessEnter = TRUE; 575} 576 577/* 578 * xf86AccessLeave() -- prepares access for and calls the 579 * entityLeave() functions. 580 * xf86AccessLeaveState() --- gets called to restore the 581 * access to the VGA IO resources when switching VT or on 582 * server exit. 583 * This was split to call xf86AccessLeaveState() from 584 * ddxGiveUp(). 585 */ 586void 587xf86AccessLeave(void) 588{ 589 if (!xf86ResAccessEnter) 590 return; 591 notifyStateChange(NOTIFY_LEAVE); 592 disableAccess(); 593 DisablePciBusAccess(); 594 EntityLeave(); 595} 596 597void 598xf86AccessLeaveState(void) 599{ 600 if (!xf86ResAccessEnter) 601 return; 602 xf86ResAccessEnter = FALSE; 603 PciStateLeave(); 604 PciBusStateLeave(); 605} 606 607/* 608 * xf86AccessRestoreState() - Restore the access registers to the 609 * state before X was started. This is handy for framebuffers. 610 */ 611static void 612xf86AccessRestoreState(void) 613{ 614 if (!xf86ResAccessEnter) 615 return; 616 PciStateLeave(); 617 PciBusStateLeave(); 618} 619 620/* 621 * xf86EnableAccess() -- enable access to controlled resources. 622 * To reduce latency when switching access the ScrnInfoRec has 623 * a linked list of the EntityAccPtr of all screen entities. 624 */ 625/* 626 * switching access needs to be done in te following oder: 627 * disable 628 * 1. disable old entity 629 * 2. reroute bus 630 * 3. enable new entity 631 * Otherwise resources needed for access control might be shadowed 632 * by other resources! 633 */ 634 635_X_EXPORT void 636xf86EnableAccess(ScrnInfoPtr pScrn) 637{ 638 register EntityAccessPtr peAcc = (EntityAccessPtr) pScrn->access; 639 register EntityAccessPtr pceAcc; 640 register xf86AccessPtr pAcc; 641 EntityAccessPtr tmp; 642 643#ifdef DEBUG 644 ErrorF("Enable access %i\n",pScrn->scrnIndex); 645#endif 646 647 /* Entity is not under access control or currently enabled */ 648 if (!pScrn->access) { 649 if (pScrn->busAccess) { 650 ((BusAccPtr)pScrn->busAccess)->set_f(pScrn->busAccess); 651 } 652 return; 653 } 654 655 switch (pScrn->resourceType) { 656 case IO: 657 pceAcc = pScrn->CurrentAccess->pIoAccess; 658 if (peAcc == pceAcc) { 659 return; 660 } 661 if (pScrn->CurrentAccess->pMemAccess == pceAcc) 662 pScrn->CurrentAccess->pMemAccess = NULL; 663 while (pceAcc) { 664 pAcc = pceAcc->pAccess; 665 if (pAcc) 666 pAcc->AccessDisable(pAcc->arg); 667 pceAcc = pceAcc->next; 668 } 669 if (pScrn->busAccess) 670 ((BusAccPtr)pScrn->busAccess)->set_f(pScrn->busAccess); 671 while (peAcc) { 672 pAcc = peAcc->pAccess; 673 if (pAcc) 674 pAcc->AccessEnable(pAcc->arg); 675 peAcc = peAcc->next; 676 } 677 pScrn->CurrentAccess->pIoAccess = (EntityAccessPtr) pScrn->access; 678 return; 679 680 case MEM_IO: 681 pceAcc = pScrn->CurrentAccess->pIoAccess; 682 if (peAcc != pceAcc) { /* current Io != pAccess */ 683 tmp = pceAcc; 684 while (pceAcc) { 685 pAcc = pceAcc->pAccess; 686 if (pAcc) 687 pAcc->AccessDisable(pAcc->arg); 688 pceAcc = pceAcc->next; 689 } 690 pceAcc = pScrn->CurrentAccess->pMemAccess; 691 if (peAcc != pceAcc /* current Mem != pAccess */ 692 && tmp !=pceAcc) { 693 while (pceAcc) { 694 pAcc = pceAcc->pAccess; 695 if (pAcc) 696 pAcc->AccessDisable(pAcc->arg); 697 pceAcc = pceAcc->next; 698 } 699 } 700 } else { /* current Io == pAccess */ 701 pceAcc = pScrn->CurrentAccess->pMemAccess; 702 if (pceAcc == peAcc) { /* current Mem == pAccess */ 703 return; 704 } 705 while (pceAcc) { /* current Mem != pAccess */ 706 pAcc = pceAcc->pAccess; 707 if (pAcc) 708 pAcc->AccessDisable(pAcc->arg); 709 pceAcc = pceAcc->next; 710 } 711 } 712 if (pScrn->busAccess) 713 ((BusAccPtr)pScrn->busAccess)->set_f(pScrn->busAccess); 714 while (peAcc) { 715 pAcc = peAcc->pAccess; 716 if (pAcc) 717 pAcc->AccessEnable(pAcc->arg); 718 peAcc = peAcc->next; 719 } 720 pScrn->CurrentAccess->pMemAccess = 721 pScrn->CurrentAccess->pIoAccess = (EntityAccessPtr) pScrn->access; 722 return; 723 724 case MEM: 725 pceAcc = pScrn->CurrentAccess->pMemAccess; 726 if (peAcc == pceAcc) { 727 return; 728 } 729 if (pScrn->CurrentAccess->pIoAccess == pceAcc) 730 pScrn->CurrentAccess->pIoAccess = NULL; 731 while (pceAcc) { 732 pAcc = pceAcc->pAccess; 733 if (pAcc) 734 pAcc->AccessDisable(pAcc->arg); 735 pceAcc = pceAcc->next; 736 } 737 if (pScrn->busAccess) 738 ((BusAccPtr)pScrn->busAccess)->set_f(pScrn->busAccess); 739 while (peAcc) { 740 pAcc = peAcc->pAccess; 741 if (pAcc) 742 pAcc->AccessEnable(pAcc->arg); 743 peAcc = peAcc->next; 744 } 745 pScrn->CurrentAccess->pMemAccess = (EntityAccessPtr) pScrn->access; 746 return; 747 748 case NONE: 749 if (pScrn->busAccess) { 750 ((BusAccPtr)pScrn->busAccess)->set_f(pScrn->busAccess); 751 } 752 return; 753 } 754} 755 756_X_EXPORT void 757xf86SetCurrentAccess(Bool Enable, ScrnInfoPtr pScrn) 758{ 759 EntityAccessPtr pceAcc2 = NULL; 760 register EntityAccessPtr pceAcc = NULL; 761 register xf86AccessPtr pAcc; 762 763 764 switch(pScrn->resourceType) { 765 case IO: 766 pceAcc = pScrn->CurrentAccess->pIoAccess; 767 break; 768 case MEM: 769 pceAcc = pScrn->CurrentAccess->pMemAccess; 770 break; 771 case MEM_IO: 772 pceAcc = pScrn->CurrentAccess->pMemAccess; 773 pceAcc2 = pScrn->CurrentAccess->pIoAccess; 774 break; 775 default: 776 break; 777 } 778 779 while (pceAcc) { 780 pAcc = pceAcc->pAccess; 781 if (pAcc) { 782 if (Enable) { 783 pAcc->AccessEnable(pAcc->arg); 784 } else { 785 pAcc->AccessDisable(pAcc->arg); 786 } 787 } 788 pceAcc = pceAcc->next; 789 if (!pceAcc) { 790 pceAcc = pceAcc2; 791 pceAcc2 = NULL; 792 } 793 } 794} 795 796_X_EXPORT void 797xf86SetAccessFuncs(EntityInfoPtr pEnt, xf86SetAccessFuncPtr funcs, 798 xf86SetAccessFuncPtr oldFuncs) 799{ 800 AccessFuncPtr rac; 801 802 if (!xf86Entities[pEnt->index]->rac) 803 xf86Entities[pEnt->index]->rac = xnfcalloc(1,sizeof(AccessFuncRec)); 804 805 rac = xf86Entities[pEnt->index]->rac; 806 807 rac->mem_new = funcs->mem; 808 rac->io_new = funcs->io; 809 rac->io_mem_new = funcs->io_mem; 810 811 rac->old = oldFuncs; 812} 813 814/* 815 * Conflict checking 816 */ 817 818static memType 819getMask(memType val) 820{ 821 memType mask = 0; 822 memType tmp = 0; 823 824 mask=~mask; 825 tmp = ~((~tmp) >> 1); 826 827 while (!(val & tmp)) { 828 mask = mask >> 1; 829 val = val << 1; 830 } 831 return mask; 832} 833 834/* 835 * checkConflictBlock() -- check for conflicts of a block resource range. 836 * If conflict is found return end of conflicting range. Else return 0. 837 */ 838static memType 839checkConflictBlock(resRange *range, resPtr pRes) 840{ 841 memType val,tmp,prev; 842 int i; 843 844 switch (pRes->res_type & ResExtMask) { 845 case ResBlock: 846 if (range->rBegin < pRes->block_end && 847 range->rEnd > pRes->block_begin) { 848#ifdef DEBUG 849 ErrorF("b-b conflict w: %lx %lx\n", 850 pRes->block_begin,pRes->block_end); 851#endif 852 return pRes->block_end < range->rEnd ? 853 pRes->block_end : range->rEnd; 854 } 855 return 0; 856 case ResSparse: 857 if (pRes->sparse_base > range->rEnd) return 0; 858 859 val = (~pRes->sparse_mask | pRes->sparse_base) & getMask(range->rEnd); 860#ifdef DEBUG 861 ErrorF("base = 0x%lx, mask = 0x%lx, begin = 0x%lx, end = 0x%lx ," 862 "val = 0x%lx\n", 863 pRes->sparse_base, pRes->sparse_mask, range->rBegin, 864 range->rEnd, val); 865#endif 866 i = sizeof(memType) * 8; 867 tmp = prev = pRes->sparse_base; 868 869 while (i) { 870 tmp |= 1<< (--i) & val; 871 if (tmp > range->rEnd) 872 tmp = prev; 873 else 874 prev = tmp; 875 } 876 if (tmp >= range->rBegin) { 877#ifdef DEBUG 878 ErrorF("conflict found at: 0x%lx\n",tmp); 879 ErrorF("b-d conflict w: %lx %lx\n", 880 pRes->sparse_base,pRes->sparse_mask); 881#endif 882 return tmp; 883 } 884 else 885 return 0; 886 } 887 return 0; 888} 889 890/* 891 * checkConflictSparse() -- check for conflicts of a sparse resource range. 892 * If conflict is found return base of conflicting region. Else return 0. 893 */ 894#define mt_max ~(memType)0 895#define length sizeof(memType) * 8 896static memType 897checkConflictSparse(resRange *range, resPtr pRes) 898{ 899 memType val, tmp, prev; 900 int i; 901 902 switch (pRes->res_type & ResExtMask) { 903 case ResSparse: 904 tmp = pRes->sparse_mask & range->rMask; 905 if ((tmp & pRes->sparse_base) == (tmp & range->rBase)) { 906#ifdef DEBUG 907 ErrorF("s-b conflict w: %lx %lx\n", 908 pRes->sparse_base,pRes->sparse_mask); 909#endif 910 return pRes->sparse_mask; 911 } 912 return 0; 913 914 case ResBlock: 915 if (pRes->block_end < range->rBase) return 0; 916 917 val = (~range->rMask | range->rBase) & getMask(pRes->block_end); 918 i = length; 919 tmp = prev = range->rBase; 920 921 while (i) { 922#ifdef DEBUG 923 ErrorF("tmp = 0x%lx\n",tmp); 924#endif 925 tmp |= 1<< (--i) & val; 926 if (tmp > pRes->block_end) 927 tmp = prev; 928 else 929 prev = tmp; 930 } 931 if (tmp < pRes->block_begin) 932 return 0; 933 else { 934 /* 935 * now we subdivide the block region in sparse regions 936 * with base values = 2^n and find the smallest mask. 937 * This might be done in a simpler way.... 938 */ 939 memType mask, m_mask = 0, base = pRes->block_begin; 940 int i; 941 while (base < pRes->block_end) { 942 for (i = 1; i < length; i++) 943 if ( base != (base & (mt_max << i))) break; 944 mask = mt_max >> (length - i); 945 do mask >>= 1; 946 while ((mask + base + 1) > pRes->block_end); 947 /* m_mask and are _inverted_ sparse masks */ 948 m_mask = mask > m_mask ? mask : m_mask; 949 base = base + mask + 1; 950 } 951#ifdef DEBUG 952 ErrorF("conflict found at: 0x%lx\n",tmp); 953 ErrorF("b-b conflict w: %lx %lx\n", 954 pRes->block_begin,pRes->block_end); 955#endif 956 return ~m_mask; 957 } 958 } 959 return 0; 960} 961#undef mt_max 962#undef length 963 964/* 965 * needCheck() -- this function decides whether to check for conflicts 966 * depending on the types of the resource ranges and their locations 967 */ 968static Bool 969needCheck(resPtr pRes, unsigned long type, int entityIndex, xf86State state) 970{ 971 /* the same entity shouldn't conflict with itself */ 972 ScrnInfoPtr pScrn; 973 int i; 974 BusType loc = BUS_NONE; 975 BusType r_loc = BUS_NONE; 976 977 if ((pRes->res_type & ResTypeMask) != (type & ResTypeMask)) 978 return FALSE; 979 980 /* 981 * Resources set by BIOS (ResBios) are allowed to conflict 982 * with resources marked (ResBios). 983 */ 984 if (pRes->res_type & type & ResBios) 985 return FALSE; 986 987 if (type & pRes->res_type & ResUnused) 988 return FALSE; 989 990 if (state == OPERATING) { 991 if (type & ResDisableOpr || pRes->res_type & ResDisableOpr) 992 return FALSE; 993 if (type & pRes->res_type & ResUnusedOpr) return FALSE; 994 /* 995 * Maybe we should have ResUnused set The resUnusedOpr 996 * bit, too. This way we could avoid this confusion 997 */ 998 if ((type & ResUnusedOpr && pRes->res_type & ResUnused) || 999 (type & ResUnused && pRes->res_type & ResUnusedOpr)) 1000 return FALSE; 1001 } 1002 1003 if (entityIndex > -1) 1004 loc = xf86Entities[entityIndex]->busType; 1005 if (pRes->entityIndex > -1) 1006 r_loc = xf86Entities[pRes->entityIndex]->busType; 1007 1008 if ((type & ResAccMask) == ResShared && 1009 (pRes->res_type & ResAccMask) == ResShared) 1010 return FALSE; 1011 1012 if (pRes->entityIndex == entityIndex) return FALSE; 1013 1014 if (pRes->entityIndex > -1 && 1015 (pScrn = xf86FindScreenForEntity(entityIndex))) { 1016 for (i = 0; i < pScrn->numEntities; i++) 1017 if (pScrn->entityList[i] == pRes->entityIndex) return FALSE; 1018 } 1019 return TRUE; 1020} 1021 1022/* 1023 * checkConflict() - main conflict checking function which all other 1024 * function call. 1025 */ 1026static memType 1027checkConflict(resRange *rgp, resPtr pRes, int entityIndex, 1028 xf86State state, Bool ignoreIdentical) 1029{ 1030 memType ret; 1031 1032 while(pRes) { 1033 if (!needCheck(pRes,rgp->type, entityIndex ,state)) { 1034 pRes = pRes->next; 1035 continue; 1036 } 1037 switch (rgp->type & ResExtMask) { 1038 case ResBlock: 1039 if (rgp->rEnd < rgp->rBegin) { 1040 xf86Msg(X_ERROR,"end of block range 0x%lx < begin 0x%lx\n", 1041 (long)rgp->rEnd, (long)rgp->rBegin); 1042 return 0; 1043 } 1044 if ((ret = checkConflictBlock(rgp, pRes))) { 1045 if (!ignoreIdentical || (rgp->rBegin != pRes->block_begin) 1046 || (rgp->rEnd != pRes->block_end)) 1047 return ret; 1048 } 1049 break; 1050 case ResSparse: 1051 if ((rgp->rBase & rgp->rMask) != rgp->rBase) { 1052 xf86Msg(X_ERROR,"sparse io range (base: 0x%lx mask: 0x%lx)" 1053 "doesn't satisfy (base & mask = mask)\n", 1054 (long)rgp->rBase, (long)rgp->rMask); 1055 return 0; 1056 } 1057 if ((ret = checkConflictSparse(rgp, pRes))) { 1058 if (!ignoreIdentical || (rgp->rBase != pRes->sparse_base) 1059 || (rgp->rMask != pRes->sparse_mask)) 1060 return ret; 1061 } 1062 break; 1063 } 1064 pRes = pRes->next; 1065 } 1066 return 0; 1067} 1068 1069/* 1070 * xf86ChkConflict() - This function is the low level interface to 1071 * the resource broker that gets exported. Tests all resources ie. 1072 * performs test with SETUP flag. 1073 */ 1074static memType 1075xf86ChkConflict(resRange *rgp, int entityIndex) 1076{ 1077 return checkConflict(rgp, Acc, entityIndex, SETUP, FALSE); 1078} 1079 1080/* 1081 * Resources List handling 1082 */ 1083 1084static resPtr 1085xf86JoinResLists(resPtr rlist1, resPtr rlist2) 1086{ 1087 resPtr pRes; 1088 1089 if (!rlist1) 1090 return rlist2; 1091 1092 if (!rlist2) 1093 return rlist1; 1094 1095 for (pRes = rlist1; pRes->next; pRes = pRes->next) 1096 ; 1097 pRes->next = rlist2; 1098 return rlist1; 1099} 1100 1101resPtr 1102xf86AddResToList(resPtr rlist, resRange *range, int entityIndex) 1103{ 1104 resPtr new; 1105 1106 switch (range->type & ResExtMask) { 1107 case ResBlock: 1108 if (range->rEnd < range->rBegin) { 1109 xf86Msg(X_ERROR,"end of block range 0x%lx < begin 0x%lx\n", 1110 (long)range->rEnd, (long)range->rBegin); 1111 return rlist; 1112 } 1113 break; 1114 case ResSparse: 1115 if ((range->rBase & range->rMask) != range->rBase) { 1116 xf86Msg(X_ERROR,"sparse io range (base: 0x%lx mask: 0x%lx)" 1117 "doesn't satisfy (base & mask = mask)\n", 1118 (long)range->rBase, (long)range->rMask); 1119 return rlist; 1120 } 1121 break; 1122 } 1123 1124 new = xnfalloc(sizeof(resRec)); 1125 /* 1126 * Only background resources may be registered with ResBios 1127 * and ResEstimated set. Other resources only set it for 1128 * testing. 1129 */ 1130 if (entityIndex != (-1)) 1131 range->type &= ~(ResBios | ResEstimated); 1132 new->val = *range; 1133 new->entityIndex = entityIndex; 1134 new->next = rlist; 1135 return new; 1136} 1137 1138_X_EXPORT void 1139xf86FreeResList(resPtr rlist) 1140{ 1141 resPtr pRes; 1142 1143 if (!rlist) 1144 return; 1145 1146 for (pRes = rlist->next; pRes; rlist = pRes, pRes = pRes->next) 1147 xfree(rlist); 1148 xfree(rlist); 1149} 1150 1151static resPtr 1152xf86DupResList(const resPtr rlist) 1153{ 1154 resPtr pRes, ret, prev, new; 1155 1156 if (!rlist) 1157 return NULL; 1158 1159 ret = xnfalloc(sizeof(resRec)); 1160 *ret = *rlist; 1161 prev = ret; 1162 for (pRes = rlist->next; pRes; pRes = pRes->next) { 1163 new = xnfalloc(sizeof(resRec)); 1164 *new = *pRes; 1165 prev->next = new; 1166 prev = new; 1167 } 1168 return ret; 1169} 1170 1171static void 1172xf86PrintResList(int verb, resPtr list) 1173{ 1174 int i = 0; 1175 const char *s, *r; 1176 resPtr tmp = list; 1177 unsigned long type; 1178 1179 if (!list) 1180 return; 1181 1182 type = ResMem; 1183 r = "M"; 1184 while (1) { 1185 while (list) { 1186 if ((list->res_type & ResPhysMask) == type) { 1187 switch (list->res_type & ResExtMask) { 1188 case ResBlock: 1189 xf86ErrorFVerb(verb, 1190 "\t[%d] %d\t%ld\t0x%08lx - 0x%08lx (0x%lx)", 1191 i, list->entityIndex, 1192 (list->res_type & ResDomain) >> 24, 1193 (long)list->block_begin, 1194 (long)list->block_end, 1195 (long)(list->block_end - 1196 list->block_begin + 1)); 1197 break; 1198 case ResSparse: 1199 xf86ErrorFVerb(verb, "\t[%d] %d\t%ld\t0x%08lx - 0x%08lx ", 1200 i, list->entityIndex, 1201 (list->res_type & ResDomain) >> 24, 1202 (long)list->sparse_base, 1203 (long)list->sparse_mask); 1204 break; 1205 default: 1206 list = list->next; 1207 continue; 1208 } 1209 xf86ErrorFVerb(verb, " %s", r); 1210 switch (list->res_type & ResAccMask) { 1211 case ResExclusive: 1212 if (list->res_type & ResUnused) 1213 s = "x"; 1214 else 1215 s = "X"; 1216 break; 1217 case ResShared: 1218 if (list->res_type & ResUnused) 1219 s = "s"; 1220 else 1221 s = "S"; 1222 break; 1223 default: 1224 s = "?"; 1225 } 1226 xf86ErrorFVerb(verb, "%s", s); 1227 switch (list->res_type & ResExtMask) { 1228 case ResBlock: 1229 s = "[B]"; 1230 break; 1231 case ResSparse: 1232 s = "[S]"; 1233 break; 1234 default: 1235 s = "[?]"; 1236 } 1237 xf86ErrorFVerb(verb, "%s", s); 1238 if (list->res_type & ResInit) 1239 xf86ErrorFVerb(verb, "t"); 1240 if (list->res_type & ResBios) 1241 xf86ErrorFVerb(verb, "(B)"); 1242 if (list->res_type & ResBus) 1243 xf86ErrorFVerb(verb, "(b)"); 1244 if (list->res_type & ResOprMask) { 1245 switch (list->res_type & ResOprMask) { 1246 case ResUnusedOpr: 1247 s = "(OprU)"; 1248 break; 1249 case ResDisableOpr: 1250 s = "(OprD)"; 1251 break; 1252 default: 1253 s = "(Opr?)"; 1254 break; 1255 } 1256 xf86ErrorFVerb(verb, "%s", s); 1257 } 1258 xf86ErrorFVerb(verb, "\n"); 1259 i++; 1260 } 1261 list = list->next; 1262 } 1263 if (type == ResIo) break; 1264 type = ResIo; 1265 r = "I"; 1266 list = tmp; 1267 } 1268} 1269 1270resPtr 1271xf86AddRangesToList(resPtr list, resRange *pRange, int entityIndex) 1272{ 1273 while(pRange && pRange->type != ResEnd) { 1274 list = xf86AddResToList(list,pRange,entityIndex); 1275 pRange++; 1276 } 1277 return list; 1278} 1279 1280void 1281xf86ResourceBrokerInit(void) 1282{ 1283 Acc = NULL; 1284 1285 /* Get the ranges used exclusively by the system */ 1286 Acc = xf86AccResFromOS(Acc); 1287 xf86MsgVerb(X_INFO, 3, "System resource ranges:\n"); 1288 xf86PrintResList(3, Acc); 1289} 1290 1291/* 1292 * Resource registration 1293 */ 1294 1295static void 1296convertRange2Host(int entityIndex, resRange *pRange) 1297{ 1298 if (pRange->type & ResBus) { 1299 switch (xf86Entities[entityIndex]->busType) { 1300 case BUS_PCI: 1301 pciConvertRange2Host(entityIndex,pRange); 1302 break; 1303 default: 1304 break; 1305 } 1306 1307 pRange->type &= ~ResBus; 1308 } 1309} 1310 1311static void 1312xf86ConvertListToHost(int entityIndex, resPtr list) 1313{ 1314 while (list) { 1315 convertRange2Host(entityIndex, &list->val); 1316 list = list->next; 1317 } 1318} 1319 1320/* 1321 * xf86RegisterResources() -- attempts to register listed resources. 1322 * Returns a resPtr listing all resources not successfully registered, by 1323 * which we mean, NULL. 1324 */ 1325 1326_X_EXPORT resPtr 1327xf86RegisterResources(int entityIndex, resList list, unsigned long access) 1328{ 1329 resRange range; 1330 resList list_f = NULL; 1331 1332 if (!list) 1333 return NULL; 1334 1335 while(list->type != ResEnd) { 1336 range = *list; 1337 1338 convertRange2Host(entityIndex,&range); 1339 1340 if ((access != ResNone) && (access & ResAccMask)) { 1341 range.type = (range.type & ~ResAccMask) | (access & ResAccMask); 1342 } 1343 range.type &= ~ResEstimated; /* Not allowed for drivers */ 1344 Acc = xf86AddResToList(Acc,&range,entityIndex); 1345 list++; 1346 } 1347 if (list_f) 1348 xfree(list_f); 1349 1350#ifdef DEBUG 1351 xf86MsgVerb(X_INFO, 3,"Resources after driver initialization\n"); 1352 xf86PrintResList(3, Acc); 1353#endif 1354 return NULL; 1355 1356} 1357 1358static void 1359busTypeSpecific(EntityPtr pEnt, xf86AccessPtr *acc_mem, 1360 xf86AccessPtr *acc_io, xf86AccessPtr *acc_mem_io) 1361{ 1362 switch (pEnt->bus.type) { 1363 case BUS_SBUS: 1364 *acc_mem = *acc_io = *acc_mem_io = &AccessNULL; 1365 break; 1366 case BUS_PCI: { 1367 struct pci_device *const dev = pEnt->bus.id.pci; 1368 1369 if ((dev != NULL) && ((void *)dev->user_data != NULL)) { 1370 pciAccPtr const paccp = (pciAccPtr) dev->user_data; 1371 1372 *acc_io = & paccp->ioAccess; 1373 *acc_mem = & paccp->memAccess; 1374 *acc_mem_io = & paccp->io_memAccess; 1375 } 1376 else { 1377 /* FIXME: This is an error path. We should probably have an 1378 * FIXME: assertion here or something. 1379 */ 1380 *acc_io = NULL; 1381 *acc_mem = NULL; 1382 *acc_mem_io = NULL; 1383 } 1384 break; 1385 } 1386 default: 1387 *acc_mem = *acc_io = *acc_mem_io = NULL; 1388 break; 1389 } 1390 return; 1391} 1392 1393static void 1394setAccess(EntityPtr pEnt, xf86State state) 1395{ 1396 1397 xf86AccessPtr acc_mem, acc_io, acc_mem_io; 1398 xf86AccessPtr org_mem = NULL, org_io = NULL, org_mem_io = NULL; 1399 int prop; 1400 1401 busTypeSpecific(pEnt, &acc_mem, &acc_io, &acc_mem_io); 1402 1403 /* The replacement function needs to handle _all_ shared resources */ 1404 /* unless they are handeled locally and disabled otherwise */ 1405 if (pEnt->rac) { 1406 if (pEnt->rac->io_new) { 1407 org_io = acc_io; 1408 acc_io = pEnt->rac->io_new; 1409 } 1410 if (pEnt->rac->mem_new) { 1411 org_mem = acc_mem; 1412 acc_mem = pEnt->rac->mem_new; 1413 } 1414 if (pEnt->rac->io_mem_new) { 1415 org_mem_io = acc_mem_io; 1416 acc_mem_io = pEnt->rac->io_mem_new; 1417 } 1418 } 1419 1420 if (state == OPERATING) { 1421 prop = pEnt->entityProp; 1422 switch(pEnt->entityProp & NEED_SHARED) { 1423 case NEED_SHARED: 1424 pEnt->access->rt = MEM_IO; 1425 break; 1426 case NEED_IO_SHARED: 1427 pEnt->access->rt = IO; 1428 break; 1429 case NEED_MEM_SHARED: 1430 pEnt->access->rt = MEM; 1431 break; 1432 default: 1433 pEnt->access->rt = NONE; 1434 } 1435 } else { 1436 prop = NEED_SHARED | NEED_MEM | NEED_IO; 1437 pEnt->access->rt = MEM_IO; 1438 } 1439 1440 switch(pEnt->access->rt) { 1441 case IO: 1442 pEnt->access->pAccess = acc_io; 1443 break; 1444 case MEM: 1445 pEnt->access->pAccess = acc_mem; 1446 break; 1447 case MEM_IO: 1448 pEnt->access->pAccess = acc_mem_io; 1449 break; 1450 default: /* no conflicts at all */ 1451 pEnt->access->pAccess = NULL; /* remove from RAC */ 1452 break; 1453 } 1454 1455 if (org_io) { 1456 /* does the driver want the old access func? */ 1457 if (pEnt->rac->old) { 1458 /* give it to the driver, leave state disabled */ 1459 pEnt->rac->old->io = org_io; 1460 } else { 1461 /* driver doesn't want it - enable generic access */ 1462 org_io->AccessEnable(org_io->arg); 1463 } 1464 } 1465 1466 if (org_mem_io) { 1467 /* does the driver want the old access func? */ 1468 if (pEnt->rac->old) { 1469 /* give it to the driver, leave state disabled */ 1470 pEnt->rac->old->io_mem = org_mem_io; 1471 } else { 1472 /* driver doesn't want it - enable generic access */ 1473 org_mem_io->AccessEnable(org_mem_io->arg); 1474 } 1475 } 1476 1477 if (org_mem) { 1478 /* does the driver want the old access func? */ 1479 if (pEnt->rac->old) { 1480 /* give it to the driver, leave state disabled */ 1481 pEnt->rac->old->mem = org_mem; 1482 } else { 1483 /* driver doesn't want it - enable generic access */ 1484 org_mem->AccessEnable(org_mem->arg); 1485 } 1486 } 1487 1488 if (!(prop & NEED_MEM_SHARED)){ 1489 if (prop & NEED_MEM) { 1490 if (acc_mem) 1491 acc_mem->AccessEnable(acc_mem->arg); 1492 } else { 1493 if (acc_mem) 1494 acc_mem->AccessDisable(acc_mem->arg); 1495 } 1496 } 1497 1498 if (!(prop & NEED_IO_SHARED)) { 1499 if (prop & NEED_IO) { 1500 if (acc_io) 1501 acc_io->AccessEnable(acc_io->arg); 1502 } else { 1503 if (acc_io) 1504 acc_io->AccessDisable(acc_io->arg); 1505 } 1506 } 1507 1508 /* disable shared resources */ 1509 if (pEnt->access->pAccess) 1510 pEnt->access->pAccess->AccessDisable(pEnt->access->pAccess->arg); 1511 1512 /* 1513 * If device is not under access control it is enabled. 1514 * If it needs bus routing do it here as it isn't bus 1515 * type specific. Any conflicts should be checked at this 1516 * stage 1517 */ 1518 if (!pEnt->access->pAccess 1519 && (pEnt->entityProp & (state == SETUP ? NEED_VGA_ROUTED_SETUP : 1520 NEED_VGA_ROUTED))) 1521 ((BusAccPtr)pEnt->busAcc)->set_f(pEnt->busAcc); 1522} 1523 1524 1525/* 1526 * xf86EnterServerState() -- set state the server is in. 1527 */ 1528 1529typedef enum { TRI_UNSET, TRI_TRUE, TRI_FALSE } TriState; 1530 1531static void 1532SetSIGIOForState(xf86State state) 1533{ 1534 static int sigio_state; 1535 static TriState sigio_blocked = TRI_UNSET; 1536 1537 if ((state == SETUP) && (sigio_blocked != TRI_TRUE)) { 1538 sigio_state = xf86BlockSIGIO(); 1539 sigio_blocked = TRI_TRUE; 1540 } else if ((state == OPERATING) && (sigio_blocked != TRI_UNSET)) { 1541 xf86UnblockSIGIO(sigio_state); 1542 sigio_blocked = TRI_FALSE; 1543 } 1544} 1545 1546void 1547xf86EnterServerState(xf86State state) 1548{ 1549 EntityPtr pEnt; 1550 ScrnInfoPtr pScrn; 1551 int i,j; 1552 int needVGA = 0; 1553 resType rt; 1554 /* 1555 * This is a good place to block SIGIO during SETUP state. 1556 * SIGIO should be blocked in SETUP state otherwise (u)sleep() 1557 * might get interrupted early. 1558 * We take care not to call xf86BlockSIGIO() twice. 1559 */ 1560 SetSIGIOForState(state); 1561#ifdef DEBUG 1562 if (state == SETUP) 1563 ErrorF("Entering SETUP state\n"); 1564 else 1565 ErrorF("Entering OPERATING state\n"); 1566#endif 1567 1568 /* When servicing a dumb framebuffer we don't need to do anything */ 1569 if (doFramebufferMode) return; 1570 1571 for (i=0; i<xf86NumScreens; i++) { 1572 pScrn = xf86Screens[i]; 1573 j = pScrn->entityList[pScrn->numEntities - 1]; 1574 pScrn->access = xf86Entities[j]->access; 1575 1576 for (j = 0; j<xf86Screens[i]->numEntities; j++) { 1577 pEnt = xf86Entities[xf86Screens[i]->entityList[j]]; 1578 if (pEnt->entityProp & (state == SETUP ? NEED_VGA_ROUTED_SETUP 1579 : NEED_VGA_ROUTED)) 1580 xf86Screens[i]->busAccess = pEnt->busAcc; 1581 } 1582 if (xf86Screens[i]->busAccess) 1583 needVGA ++; 1584 } 1585 1586 /* 1587 * if we just have one screen we don't have RAC. 1588 * Therefore just enable the screen and return. 1589 */ 1590 if (!needRAC) { 1591 xf86EnableAccess(xf86Screens[0]); 1592 notifyStateChange(NOTIFY_ENABLE); 1593 return; 1594 } 1595 1596 if (state == SETUP) 1597 notifyStateChange(NOTIFY_SETUP_TRANSITION); 1598 else 1599 notifyStateChange(NOTIFY_OPERATING_TRANSITION); 1600 1601 clearAccess(); 1602 for (i=0; i<xf86NumScreens;i++) { 1603 1604 rt = NONE; 1605 1606 for (j = 0; j<xf86Screens[i]->numEntities; j++) { 1607 pEnt = xf86Entities[xf86Screens[i]->entityList[j]]; 1608 setAccess(pEnt,state); 1609 1610 if (pEnt->access->rt != NONE) { 1611 if (rt != NONE && rt != pEnt->access->rt) 1612 rt = MEM_IO; 1613 else 1614 rt = pEnt->access->rt; 1615 } 1616 } 1617 xf86Screens[i]->resourceType = rt; 1618 if (rt == NONE) { 1619 xf86Screens[i]->access = NULL; 1620 if (needVGA < 2) 1621 xf86Screens[i]->busAccess = NULL; 1622 } 1623 1624#ifdef DEBUG 1625 if (xf86Screens[i]->busAccess) 1626 ErrorF("Screen %i setting vga route\n",i); 1627#endif 1628 switch (rt) { 1629 case MEM_IO: 1630 xf86MsgVerb(X_INFO, 3, "Screen %i shares mem & io resources\n",i); 1631 break; 1632 case IO: 1633 xf86MsgVerb(X_INFO, 3, "Screen %i shares io resources\n",i); 1634 break; 1635 case MEM: 1636 xf86MsgVerb(X_INFO, 3, "Screen %i shares mem resources\n",i); 1637 break; 1638 default: 1639 xf86MsgVerb(X_INFO, 3, "Entity %i shares no resources\n",i); 1640 break; 1641 } 1642 } 1643 if (state == SETUP) 1644 notifyStateChange(NOTIFY_SETUP); 1645 else 1646 notifyStateChange(NOTIFY_OPERATING); 1647} 1648 1649/* 1650 * xf86SetOperatingState() -- Set ResOperMask for resources listed. 1651 */ 1652_X_EXPORT resPtr 1653xf86SetOperatingState(resList list, int entityIndex, int mask) 1654{ 1655 resPtr acc; 1656 resPtr r_fail = NULL; 1657 resRange range; 1658 1659 while (list->type != ResEnd) { 1660 range = *list; 1661 convertRange2Host(entityIndex,&range); 1662 1663 acc = Acc; 1664 while (acc) { 1665#define MASK (ResTypeMask | ResExtMask) 1666 if ((acc->entityIndex == entityIndex) 1667 && (acc->val.a == range.a) && (acc->val.b == range.b) 1668 && ((acc->val.type & MASK) == (range.type & MASK))) 1669 break; 1670#undef MASK 1671 acc = acc->next; 1672 } 1673 if (acc) 1674 acc->val.type = (acc->val.type & ~ResOprMask) 1675 | (mask & ResOprMask); 1676 else { 1677 r_fail = xf86AddResToList(r_fail,&range,entityIndex); 1678 } 1679 list ++; 1680 } 1681 1682 return r_fail; 1683} 1684 1685/* 1686 * Stage specific code 1687 */ 1688 1689/* 1690 * xf86ClaimFixedResources() is used to allocate non-relocatable resources. 1691 * This should only be done by a driver's Probe() function. 1692 */ 1693_X_EXPORT void 1694xf86ClaimFixedResources(resList list, int entityIndex) 1695{ 1696 resPtr ptr = NULL; 1697 resRange range; 1698 1699 if (!list) return; 1700 1701 while (list->type !=ResEnd) { 1702 range = *list; 1703 1704 convertRange2Host(entityIndex,&range); 1705 1706 range.type &= ~ResEstimated; /* Not allowed for drivers */ 1707 switch (range.type & ResAccMask) { 1708 case ResExclusive: 1709 if (!xf86ChkConflict(&range, entityIndex)) { 1710 Acc = xf86AddResToList(Acc, &range, entityIndex); 1711 } else FatalError("xf86ClaimFixedResources conflict\n"); 1712 break; 1713 case ResShared: 1714 /* at this stage the resources are just added to the 1715 * EntityRec. After the Probe() phase this list is checked by 1716 * xf86PostProbe(). All resources which don't 1717 * conflict with already allocated ones are allocated 1718 * and removed from the EntityRec. Thus a non-empty resource 1719 * list in the EntityRec indicates resource conflicts the 1720 * driver should either handle or fail. 1721 */ 1722 if (xf86Entities[entityIndex]->active) 1723 ptr = xf86AddResToList(ptr,&range,entityIndex); 1724 break; 1725 } 1726 list++; 1727 } 1728 xf86Entities[entityIndex]->resources = 1729 xf86JoinResLists(xf86Entities[entityIndex]->resources,ptr); 1730 xf86MsgVerb(X_INFO, 3, 1731 "resource ranges after xf86ClaimFixedResources() call:\n"); 1732 xf86PrintResList(3,Acc); 1733#ifdef DEBUG 1734 if (ptr) { 1735 xf86MsgVerb(X_INFO, 3, "to be registered later:\n"); 1736 xf86PrintResList(3,ptr); 1737 } 1738#endif 1739} 1740 1741static void 1742checkRoutingForScreens(xf86State state) 1743{ 1744 resList list = resVgaUnusedExclusive; 1745 resPtr pResVGA = NULL; 1746 resPtr pResVGAHost; 1747 pointer vga = NULL; 1748 int i,j; 1749 int entityIndex; 1750 EntityPtr pEnt; 1751 resPtr pAcc; 1752 resRange range; 1753 1754 /* 1755 * find devices that need VGA routed: ie the ones that have 1756 * registered VGA resources without ResUnused. ResUnused 1757 * doesn't conflict with itself therefore use it here. 1758 */ 1759 while (list->type != ResEnd) { /* create resPtr from resList for VGA */ 1760 range = *list; 1761 range.type &= ~(ResBios | ResEstimated); /* if set remove them */ 1762 pResVGA = xf86AddResToList(pResVGA, &range, -1); 1763 list++; 1764 } 1765 1766 for (i = 0; i < xf86NumScreens; i++) { 1767 for (j = 0; j < xf86Screens[i]->numEntities; j++) { 1768 entityIndex = xf86Screens[i]->entityList[j]; 1769 pEnt = xf86Entities[entityIndex]; 1770 pAcc = Acc; 1771 vga = NULL; 1772 pResVGAHost = xf86DupResList(pResVGA); 1773 xf86ConvertListToHost(entityIndex,pResVGAHost); 1774 while (pAcc) { 1775 if (pAcc->entityIndex == entityIndex) 1776 if (checkConflict(&pAcc->val, pResVGAHost, 1777 entityIndex, state, FALSE)) { 1778 if (vga && vga != pEnt->busAcc) { 1779 xf86Msg(X_ERROR, "Screen %i needs vga routed to" 1780 "different buses - deleting\n",i); 1781 xf86DeleteScreen(i--,0); 1782 } 1783#ifdef DEBUG 1784 { 1785 resPtr rlist = xf86AddResToList(NULL,&pAcc->val, 1786 pAcc->entityIndex); 1787 xf86MsgVerb(X_INFO,3,"====== %s\n", 1788 state == OPERATING ? "OPERATING" 1789 : "SETUP"); 1790 xf86MsgVerb(X_INFO,3,"%s Resource:\n", 1791 (pAcc->val.type) & ResMem ? "Mem" :"Io"); 1792 xf86PrintResList(3,rlist); 1793 xf86FreeResList(rlist); 1794 xf86MsgVerb(X_INFO,3,"Conflicts with:\n"); 1795 xf86PrintResList(3,pResVGAHost); 1796 xf86MsgVerb(X_INFO,3,"=====\n"); 1797 } 1798#endif 1799 vga = pEnt->busAcc; 1800 pEnt->entityProp |= (state == SETUP 1801 ? NEED_VGA_ROUTED_SETUP : NEED_VGA_ROUTED); 1802 if (state == OPERATING) { 1803 if (pAcc->val.type & ResMem) 1804 pEnt->entityProp |= NEED_VGA_MEM; 1805 else 1806 pEnt->entityProp |= NEED_VGA_IO; 1807 } 1808 } 1809 pAcc = pAcc->next; 1810 } 1811 if (vga) 1812 xf86MsgVerb(X_INFO, 3,"Setting vga for screen %i.\n",i); 1813 xf86FreeResList(pResVGAHost); 1814 } 1815 } 1816 xf86FreeResList(pResVGA); 1817} 1818 1819/* 1820 * xf86PostProbe() -- Allocate all non conflicting resources 1821 * This function gets called by xf86Init(). 1822 */ 1823void 1824xf86PostProbe(void) 1825{ 1826 memType val; 1827 int i,j; 1828 resPtr resp, acc, tmp, resp_x; 1829 1830 if (fbSlotClaimed) { 1831 if (pciSlotClaimed 1832#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) 1833 || sbusSlotClaimed 1834#endif 1835 ) { 1836 FatalError("Cannot run in framebuffer mode. Please specify busIDs " 1837 " for all framebuffer devices\n"); 1838 return; 1839 } else { 1840 xf86Msg(X_INFO,"Running in FRAMEBUFFER Mode\n"); 1841 xf86AccessRestoreState(); 1842 notifyStateChange(NOTIFY_ENABLE); 1843 doFramebufferMode = TRUE; 1844 1845 return; 1846 } 1847 } 1848 acc = tmp = xf86DupResList(Acc); 1849 1850 for (i=0; i<xf86NumEntities; i++) { 1851 resp = xf86Entities[i]->resources; 1852 xf86Entities[i]->resources = NULL; 1853 resp_x = NULL; 1854 while (resp) { 1855 if (! (val = checkConflict(&resp->val,acc,i,SETUP,FALSE))) { 1856 resp->res_type &= ~(ResBios); /* just used for chkConflict() */ 1857 tmp = resp_x; 1858 resp_x = resp; 1859 resp = resp->next; 1860 resp_x->next = tmp; 1861 } else { 1862 xf86MsgVerb(X_INFO, 3, "Found conflict at: 0x%lx\n", 1863 (long)val); 1864 resp->res_type &= ~ResEstimated; 1865 tmp = xf86Entities[i]->resources; 1866 xf86Entities[i]->resources = resp; 1867 resp = resp->next; 1868 xf86Entities[i]->resources->next = tmp; 1869 } 1870 } 1871 xf86JoinResLists(Acc,resp_x); 1872 } 1873 xf86FreeResList(acc); 1874 1875 xf86MsgVerb(X_INFO, 3, "resource ranges after probing:\n"); 1876 xf86PrintResList(3, Acc); 1877 checkRoutingForScreens(SETUP); 1878 1879 for (i = 0; i < xf86NumScreens; i++) { 1880 for (j = 0; j<xf86Screens[i]->numEntities; j++) { 1881 EntityPtr pEnt = xf86Entities[xf86Screens[i]->entityList[j]]; 1882 if ((pEnt->entityProp & NEED_VGA_ROUTED_SETUP) && 1883 ((xf86Screens[i]->busAccess = pEnt->busAcc))) 1884 break; 1885 } 1886 } 1887} 1888 1889static void 1890checkRequiredResources(int entityIndex) 1891{ 1892 resRange range; 1893 resPtr pAcc = Acc; 1894 const EntityPtr pEnt = xf86Entities[entityIndex]; 1895 while (pAcc) { 1896 if (pAcc->entityIndex == entityIndex) { 1897 range = pAcc->val; 1898 /* ResAny to find conflicts with anything. */ 1899 range.type = (range.type & ~ResAccMask) | ResAny | ResBios; 1900 if (checkConflict(&range,Acc,entityIndex,OPERATING,FALSE)) 1901 switch (pAcc->res_type & ResPhysMask) { 1902 case ResMem: 1903 pEnt->entityProp |= NEED_MEM_SHARED; 1904 break; 1905 case ResIo: 1906 pEnt->entityProp |= NEED_IO_SHARED; 1907 break; 1908 } 1909 if (!(pAcc->res_type & ResOprMask)) { 1910 switch (pAcc->res_type & ResPhysMask) { 1911 case ResMem: 1912 pEnt->entityProp |= NEED_MEM; 1913 break; 1914 case ResIo: 1915 pEnt->entityProp |= NEED_IO; 1916 break; 1917 } 1918 } 1919 } 1920 pAcc = pAcc->next; 1921 } 1922 1923 /* 1924 * After we have checked all resources of an entity agains any 1925 * other resource we know if the entity need this resource type 1926 * (ie. mem/io) at all. if not we can disable this type completely, 1927 * so no need to share it either. 1928 */ 1929 if ((pEnt->entityProp & NEED_MEM_SHARED) 1930 && (!(pEnt->entityProp & NEED_MEM))) 1931 pEnt->entityProp &= ~(unsigned long)NEED_MEM_SHARED; 1932 1933 if ((pEnt->entityProp & NEED_IO_SHARED) 1934 && (!(pEnt->entityProp & NEED_IO))) 1935 pEnt->entityProp &= ~(unsigned long)NEED_IO_SHARED; 1936} 1937 1938void 1939xf86PostPreInit() 1940{ 1941 if (doFramebufferMode) return; 1942 1943 if (xf86NumScreens > 1) 1944 needRAC = TRUE; 1945 1946 xf86MsgVerb(X_INFO, 3, "do I need RAC?"); 1947 1948 if (needRAC) { 1949 xf86ErrorFVerb(3, " Yes, I do.\n"); 1950 } else { 1951 xf86ErrorFVerb(3, " No, I don't.\n"); 1952 } 1953 1954 xf86MsgVerb(X_INFO, 3, "resource ranges after preInit:\n"); 1955 xf86PrintResList(3, Acc); 1956} 1957 1958void 1959xf86PostScreenInit(void) 1960{ 1961 int i,j; 1962 ScreenPtr pScreen; 1963 unsigned int flags; 1964 int nummem = 0, numio = 0; 1965 1966 if (doFramebufferMode) { 1967 SetSIGIOForState(OPERATING); 1968 return; 1969 } 1970 1971#ifdef DEBUG 1972 ErrorF("PostScreenInit generation: %i\n",serverGeneration); 1973#endif 1974 if (serverGeneration == 1) { 1975 checkRoutingForScreens(OPERATING); 1976 for (i=0; i<xf86NumEntities; i++) { 1977 checkRequiredResources(i); 1978 } 1979 1980 /* 1981 * after removing NEED_XXX_SHARED from entities that 1982 * don't need need XXX resources at all we might have 1983 * a single entity left that has NEED_XXX_SHARED set. 1984 * In this case we can delete that, too. 1985 */ 1986 for (i = 0; i < xf86NumEntities; i++) { 1987 if (xf86Entities[i]->entityProp & NEED_MEM_SHARED) 1988 nummem++; 1989 if (xf86Entities[i]->entityProp & NEED_IO_SHARED) 1990 numio++; 1991 } 1992 for (i = 0; i < xf86NumEntities; i++) { 1993 if (nummem < 2) 1994 xf86Entities[i]->entityProp &= ~NEED_MEM_SHARED; 1995 if (numio < 2) 1996 xf86Entities[i]->entityProp &= ~NEED_IO_SHARED; 1997 } 1998 } 1999 2000 if (xf86Screens && needRAC) { 2001 int needRACforVga = 0; 2002 2003 for (i = 0; i < xf86NumScreens; i++) { 2004 for (j = 0; j < xf86Screens[i]->numEntities; j++) { 2005 if (xf86Entities[xf86Screens[i]->entityList[j]]->entityProp 2006 & NEED_VGA_ROUTED) { 2007 needRACforVga ++; 2008 break; /* only count each screen once */ 2009 } 2010 } 2011 } 2012 2013 for (i = 0; i < xf86NumScreens; i++) { 2014 Bool needRACforMem = FALSE, needRACforIo = FALSE; 2015 2016 for (j = 0; j < xf86Screens[i]->numEntities; j++) { 2017 if (xf86Entities[xf86Screens[i]->entityList[j]]->entityProp 2018 & NEED_MEM_SHARED) 2019 needRACforMem = TRUE; 2020 if (xf86Entities[xf86Screens[i]->entityList[j]]->entityProp 2021 & NEED_IO_SHARED) 2022 needRACforIo = TRUE; 2023 /* 2024 * We may need RAC although we don't share any resources 2025 * as we need to route VGA to the correct bus. This can 2026 * only be done simultaniously for MEM and IO. 2027 */ 2028 if (needRACforVga > 1) { 2029 if (xf86Entities[xf86Screens[i]->entityList[j]]->entityProp 2030 & NEED_VGA_MEM) 2031 needRACforMem = TRUE; 2032 if (xf86Entities[xf86Screens[i]->entityList[j]]->entityProp 2033 & NEED_VGA_IO) 2034 needRACforIo = TRUE; 2035 } 2036 } 2037 2038 pScreen = xf86Screens[i]->pScreen; 2039 flags = 0; 2040 if (needRACforMem) { 2041 flags |= xf86Screens[i]->racMemFlags; 2042 xf86ErrorFVerb(3, "Screen %d is using RAC for mem\n", i); 2043 } 2044 if (needRACforIo) { 2045 flags |= xf86Screens[i]->racIoFlags; 2046 xf86ErrorFVerb(3, "Screen %d is using RAC for io\n", i); 2047 } 2048 2049 xf86RACInit(pScreen,flags); 2050 } 2051 } 2052 2053 xf86EnterServerState(OPERATING); 2054 2055} 2056 2057/* 2058 * Sets 2059 */ 2060 2061 2062static resPtr 2063decomposeSparse(resRange range) 2064{ 2065 resRange new; 2066 resPtr ret = NULL; 2067 memType val = range.rBegin; 2068 int i = 0; 2069 2070 new.type = (range.type & ~ResExtMask) | ResSparse; 2071 2072 while (1) { 2073 if (val & 0x01) { 2074 new.rBase = (val << i); 2075 new.rMask = ~((1 << i) - 1); 2076 ret = xf86AddResToList(ret,&new,-1); 2077 val ++; 2078 } 2079 i++; 2080 val >>= 1; 2081 if ((((val + 1) << i) - 1) > range.rEnd) 2082 break; 2083 } 2084 i--; 2085 val <<= 1; 2086 2087 while (1) { 2088 if((((val + 1) << i) - 1)> range.rEnd) { 2089 if (--i < 0) break; 2090 val <<= 1; 2091 } else { 2092 new.rBase = (val << i); 2093 new.rMask = ~((1 << i) - 1); 2094 val++; 2095 ret = xf86AddResToList(ret,&new,-1); 2096 } 2097 } 2098 return ret; 2099} 2100 2101static Bool 2102x_isSubsetOf(resRange range, resPtr list1, resPtr list2) 2103{ 2104 resRange range1, range2; 2105 memType m1_A_m2; 2106 Bool ret; 2107 resPtr list; 2108 2109 if (list1) { 2110 list = list1; 2111 if ((range.type & ResTypeMask) == (list->res_type & ResTypeMask)) { 2112 switch (range.type & ResExtMask) { 2113 case ResBlock: 2114 if ((list->res_type & ResExtMask) == ResBlock) { 2115 if (range.rBegin >= list->block_begin 2116 && range.rEnd <= list->block_end) 2117 return TRUE; 2118 else if (range.rBegin < list->block_begin 2119 && range.rEnd > list->block_end) { 2120 RANGE(range1, range.rBegin, list->block_begin - 1, 2121 range.type); 2122 RANGE(range2, list->block_end + 1, range.rEnd, 2123 range.type); 2124 return (x_isSubsetOf(range1,list->next,list2) && 2125 x_isSubsetOf(range2,list->next,list2)); 2126 } 2127 else if (range.rBegin >= list->block_begin 2128 && range.rBegin <= list->block_end) { 2129 RANGE(range1, list->block_end + 1, range.rEnd, 2130 range.type); 2131 return (x_isSubsetOf(range1,list->next,list2)); 2132 } else if (range.rEnd >= list->block_begin 2133 && range.rEnd <= list->block_end) { 2134 RANGE(range1,range.rBegin, list->block_begin - 1, 2135 range.type); 2136 return (x_isSubsetOf(range1,list->next,list2)); 2137 } 2138 } 2139 break; 2140 case ResSparse: 2141 if ((list->res_type & ResExtMask) == ResSparse) { 2142 memType test; 2143 int i; 2144 2145 m1_A_m2 = range.rMask & list->sparse_mask; 2146 if ((range.rBase ^ list->sparse_base) & m1_A_m2) 2147 break; 2148 /* 2149 * We use the following system: 2150 * let 0 ^= mask:1 base:0, 1 ^= mask:1 base:1, 2151 * X mask:0 ; S: set TSS: test set for subset 2152 * NTSS: new test set after test 2153 * S: 1 0 1 0 X X 0 1 X 2154 * TSS: 1 0 0 1 1 0 X X X 2155 * T: 0 0 1 1 0 0 0 0 0 2156 * NTSS: 1 0 0/X 1/X 1 0 1 0 X 2157 * R: 0 0 0 0 0 0 1 1 0 2158 * If R != 0 TSS and S are disjunct 2159 * If R == 0 TSS is subset of S 2160 * If R != 0 NTSS contains elements from TSS 2161 * which are not also members of S. 2162 * If a T is set one of the correspondig bits 2163 * in NTSS must be set to the specified value 2164 * all other are X 2165 */ 2166 test = list->sparse_mask & ~range.rMask; 2167 if (test == 0) 2168 return TRUE; 2169 for (i = 0; i < sizeof(memType); i++) { 2170 if ((test >> i) & 0x1) { 2171 RANGE(range1, ((range.rBase & list->sparse_base) 2172 | (range.rBase & ~list->sparse_mask) 2173 | ((~list->sparse_base & list->sparse_mask) 2174 & ~range.rMask)) & range1.rMask, 2175 ((range.rMask | list->sparse_mask) & ~test) 2176 | (1 << i), range.type); 2177 return (x_isSubsetOf(range1,list->next,list2)); 2178 } 2179 } 2180 } 2181 break; 2182 } 2183 } 2184 return (x_isSubsetOf(range,list->next,list2)); 2185 } else if (list2) { 2186 resPtr tmpList = NULL; 2187 switch (range.type & ResExtMask) { 2188 case ResBlock: 2189 tmpList = decomposeSparse(range); 2190 while (tmpList) { 2191 if (!x_isSubsetOf(tmpList->val,list2,NULL)) { 2192 xf86FreeResList(tmpList); 2193 return FALSE; 2194 } 2195 tmpList = tmpList->next; 2196 } 2197 xf86FreeResList(tmpList); 2198 return TRUE; 2199 break; 2200 case ResSparse: 2201 while (list2) { 2202 tmpList = xf86JoinResLists(tmpList,decomposeSparse(list2->val)); 2203 list2 = list2->next; 2204 } 2205 ret = x_isSubsetOf(range,tmpList,NULL); 2206 xf86FreeResList(tmpList); 2207 return ret; 2208 break; 2209 } 2210 } else 2211 return FALSE; 2212 2213 return FALSE; 2214} 2215 2216Bool 2217xf86IsSubsetOf(resRange range, resPtr list) 2218{ 2219 resPtr dup = xf86DupResList(list); 2220 resPtr r_sp = NULL, r = NULL, tmp = NULL; 2221 Bool ret = FALSE; 2222 2223 while (dup) { 2224 tmp = dup; 2225 dup = dup->next; 2226 switch (tmp->res_type & ResExtMask) { 2227 case ResBlock: 2228 tmp->next = r; 2229 r = tmp; 2230 break; 2231 case ResSparse: 2232 tmp->next = r_sp; 2233 r_sp = tmp; 2234 break; 2235 } 2236 } 2237 2238 switch (range.type & ResExtMask) { 2239 case ResBlock: 2240 ret = x_isSubsetOf(range,r,r_sp); 2241 break; 2242 case ResSparse: 2243 ret = x_isSubsetOf(range,r_sp,r); 2244 break; 2245 } 2246 xf86FreeResList(r); 2247 xf86FreeResList(r_sp); 2248 2249 return ret; 2250} 2251 2252static resPtr 2253findIntersect(resRange Range, resPtr list) 2254{ 2255 resRange range; 2256 resPtr new = NULL; 2257 2258 while (list) { 2259 if ((Range.type & ResTypeMask) == (list->res_type & ResTypeMask)) { 2260 switch (Range.type & ResExtMask) { 2261 case ResBlock: 2262 switch (list->res_type & ResExtMask) { 2263 case ResBlock: 2264 if (Range.rBegin >= list->block_begin) 2265 range.rBegin = Range.rBegin; 2266 else 2267 range.rBegin = list->block_begin; 2268 if (Range.rEnd <= list->block_end) 2269 range.rEnd = Range.rEnd; 2270 else 2271 range.rEnd = list->block_end; 2272 if (range.rEnd > range.rBegin) { 2273 range.type = Range.type; 2274 new = xf86AddResToList(new,&range,-1); 2275 } 2276 break; 2277 case ResSparse: 2278 new = xf86JoinResLists(new,xf86FindIntersectOfLists(new,decomposeSparse(list->val))); 2279 break; 2280 } 2281 break; 2282 case ResSparse: 2283 switch (list->res_type & ResExtMask) { 2284 case ResSparse: 2285 if (!((~(range.rBase ^ list->sparse_base) 2286 & (range.rMask & list->sparse_mask)))) { 2287 RANGE(range, (range.rBase & list->sparse_base) 2288 | (~range.rMask & list->sparse_base) 2289 | (~list->sparse_mask & range.rBase), 2290 range.rMask | list->sparse_mask, 2291 Range.type); 2292 new = xf86AddResToList(new,&range,-1); 2293 } 2294 break; 2295 case ResBlock: 2296 new = xf86JoinResLists(new,xf86FindIntersectOfLists( 2297 decomposeSparse(range),list)); 2298 break; 2299 } 2300 } 2301 } 2302 list = list->next; 2303 } 2304 return new; 2305} 2306 2307resPtr 2308xf86FindIntersectOfLists(resPtr l1, resPtr l2) 2309{ 2310 resPtr ret = NULL; 2311 2312 while (l1) { 2313 ret = xf86JoinResLists(ret,findIntersect(l1->val,l2)); 2314 l1 = l1->next; 2315 } 2316 return ret; 2317} 2318 2319#if 0 /* Not used */ 2320static resPtr 2321xf86FindComplement(resRange Range) 2322{ 2323 resRange range; 2324 memType tmp; 2325 resPtr new = NULL; 2326 int i; 2327 2328 switch (Range.type & ResExtMask) { 2329 case ResBlock: 2330 if (Range.rBegin > 0) { 2331 RANGE(range, 0, Range.rBegin - 1, Range.type); 2332 new = xf86AddResToList(new,&range,-1); 2333 } 2334 if (Range.rEnd < (memType)~0) { 2335 RANGE(range,Range.rEnd + 1, (memType)~0, Range.type); 2336 new = xf86AddResToList(new,&range,-1); 2337 } 2338 break; 2339 case ResSparse: 2340 tmp = Range.rMask; 2341 for (i = 0; i < sizeof(memType); i++) { 2342 if (tmp & 0x1) { 2343 RANGE(range,(~Range.rMask & range.rMask),(1 << i), Range.type); 2344 new = xf86AddResToList(new,&range,-1); 2345 } 2346 } 2347 break; 2348 default: 2349 break; 2350 } 2351 return new; 2352} 2353#endif 2354 2355resPtr 2356xf86ExtractTypeFromList(resPtr list, unsigned long type) 2357{ 2358 resPtr ret = NULL; 2359 2360 while (list) { 2361 if ((list->res_type & ResTypeMask) == type) 2362 ret = xf86AddResToList(ret,&(list->val),list->entityIndex); 2363 list = list->next; 2364 } 2365 return ret; 2366} 2367 2368/* 2369 * xf86FindPrimaryDevice() - Find the display device which 2370 * was active when the server was started. 2371 */ 2372void 2373xf86FindPrimaryDevice() 2374{ 2375 if (primaryBus.type != BUS_NONE) { 2376 char *bus; 2377 char loc[16]; 2378 2379 switch (primaryBus.type) { 2380 case BUS_PCI: 2381 bus = "PCI"; 2382 snprintf(loc, sizeof(loc), " %2.2x@%2.2x:%2.2x:%1.1x", 2383 primaryBus.id.pci->bus, 2384 primaryBus.id.pci->domain, 2385 primaryBus.id.pci->dev, 2386 primaryBus.id.pci->func); 2387 break; 2388 case BUS_SBUS: 2389 bus = "SBUS"; 2390 snprintf(loc, sizeof(loc), " %2.2x", primaryBus.id.sbus.fbNum); 2391 break; 2392 default: 2393 bus = ""; 2394 loc[0] = '\0'; 2395 } 2396 2397 xf86MsgVerb(X_INFO, 2, "Primary Device is: %s%s\n",bus,loc); 2398 } 2399} 2400 2401Bool 2402xf86NoSharedResources(int screenIndex,resType res) 2403{ 2404 int j; 2405 2406 if (screenIndex > xf86NumScreens) 2407 return TRUE; 2408 2409 for (j = 0; j < xf86Screens[screenIndex]->numEntities; j++) { 2410 switch (res) { 2411 case IO: 2412 if ( xf86Entities[xf86Screens[screenIndex]->entityList[j]]->entityProp 2413 & NEED_IO_SHARED) 2414 return FALSE; 2415 break; 2416 case MEM: 2417 if ( xf86Entities[xf86Screens[screenIndex]->entityList[j]]->entityProp 2418 & NEED_MEM_SHARED) 2419 return FALSE; 2420 break; 2421 case MEM_IO: 2422 if ( xf86Entities[xf86Screens[screenIndex]->entityList[j]]->entityProp 2423 & NEED_SHARED) 2424 return FALSE; 2425 break; 2426 case NONE: 2427 break; 2428 } 2429 } 2430 return TRUE; 2431} 2432 2433_X_EXPORT void 2434xf86RegisterStateChangeNotificationCallback(xf86StateChangeNotificationCallbackFunc func, pointer arg) 2435{ 2436 StateChangeNotificationPtr ptr = 2437 (StateChangeNotificationPtr)xnfalloc(sizeof(StateChangeNotificationRec)); 2438 2439 ptr->func = func; 2440 ptr->arg = arg; 2441 ptr->next = StateChangeNotificationList; 2442 StateChangeNotificationList = ptr; 2443} 2444 2445_X_EXPORT Bool 2446xf86DeregisterStateChangeNotificationCallback(xf86StateChangeNotificationCallbackFunc func) 2447{ 2448 StateChangeNotificationPtr *ptr = &StateChangeNotificationList; 2449 StateChangeNotificationPtr tmp; 2450 2451 while (*ptr) { 2452 if ((*ptr)->func == func) { 2453 tmp = (*ptr); 2454 (*ptr) = (*ptr)->next; 2455 xfree(tmp); 2456 return TRUE; 2457 } 2458 ptr = &((*ptr)->next); 2459 } 2460 return FALSE; 2461} 2462 2463static void 2464notifyStateChange(xf86NotifyState state) 2465{ 2466 StateChangeNotificationPtr ptr = StateChangeNotificationList; 2467 while (ptr) { 2468 ptr->func(state,ptr->arg); 2469 ptr = ptr->next; 2470 } 2471} 2472 2473/* Multihead accel sharing accessor functions and entity Private handling */ 2474 2475_X_EXPORT int 2476xf86GetLastScrnFlag(int entityIndex) 2477{ 2478 if(entityIndex < xf86NumEntities) { 2479 return(xf86Entities[entityIndex]->lastScrnFlag); 2480 } else { 2481 return -1; 2482 } 2483} 2484 2485_X_EXPORT void 2486xf86SetLastScrnFlag(int entityIndex, int scrnIndex) 2487{ 2488 if(entityIndex < xf86NumEntities) { 2489 xf86Entities[entityIndex]->lastScrnFlag = scrnIndex; 2490 } 2491} 2492 2493_X_EXPORT Bool 2494xf86IsEntityShared(int entityIndex) 2495{ 2496 if(entityIndex < xf86NumEntities) { 2497 if(xf86Entities[entityIndex]->entityProp & IS_SHARED_ACCEL) { 2498 return TRUE; 2499 } 2500 } 2501 return FALSE; 2502} 2503 2504_X_EXPORT void 2505xf86SetEntityShared(int entityIndex) 2506{ 2507 if(entityIndex < xf86NumEntities) { 2508 xf86Entities[entityIndex]->entityProp |= IS_SHARED_ACCEL; 2509 } 2510} 2511 2512_X_EXPORT Bool 2513xf86IsEntitySharable(int entityIndex) 2514{ 2515 if(entityIndex < xf86NumEntities) { 2516 if(xf86Entities[entityIndex]->entityProp & ACCEL_IS_SHARABLE) { 2517 return TRUE; 2518 } 2519 } 2520 return FALSE; 2521} 2522 2523_X_EXPORT void 2524xf86SetEntitySharable(int entityIndex) 2525{ 2526 if(entityIndex < xf86NumEntities) { 2527 xf86Entities[entityIndex]->entityProp |= ACCEL_IS_SHARABLE; 2528 } 2529} 2530 2531_X_EXPORT Bool 2532xf86IsPrimInitDone(int entityIndex) 2533{ 2534 if(entityIndex < xf86NumEntities) { 2535 if(xf86Entities[entityIndex]->entityProp & SA_PRIM_INIT_DONE) { 2536 return TRUE; 2537 } 2538 } 2539 return FALSE; 2540} 2541 2542_X_EXPORT void 2543xf86SetPrimInitDone(int entityIndex) 2544{ 2545 if(entityIndex < xf86NumEntities) { 2546 xf86Entities[entityIndex]->entityProp |= SA_PRIM_INIT_DONE; 2547 } 2548} 2549 2550_X_EXPORT void 2551xf86ClearPrimInitDone(int entityIndex) 2552{ 2553 if(entityIndex < xf86NumEntities) { 2554 xf86Entities[entityIndex]->entityProp &= ~SA_PRIM_INIT_DONE; 2555 } 2556} 2557 2558 2559/* 2560 * Allocate a private in the entities. 2561 */ 2562 2563_X_EXPORT int 2564xf86AllocateEntityPrivateIndex(void) 2565{ 2566 int idx, i; 2567 EntityPtr pEnt; 2568 DevUnion *nprivs; 2569 2570 idx = xf86EntityPrivateCount++; 2571 for (i = 0; i < xf86NumEntities; i++) { 2572 pEnt = xf86Entities[i]; 2573 nprivs = xnfrealloc(pEnt->entityPrivates, 2574 xf86EntityPrivateCount * sizeof(DevUnion)); 2575 /* Zero the new private */ 2576 bzero(&nprivs[idx], sizeof(DevUnion)); 2577 pEnt->entityPrivates = nprivs; 2578 } 2579 return idx; 2580} 2581 2582_X_EXPORT DevUnion * 2583xf86GetEntityPrivate(int entityIndex, int privIndex) 2584{ 2585 if (entityIndex >= xf86NumEntities || privIndex >= xf86EntityPrivateCount) 2586 return NULL; 2587 2588 return &(xf86Entities[entityIndex]->entityPrivates[privIndex]); 2589} 2590 2591