Logo Search packages:      
Sourcecode: xorg-server version File versions  Download package

xf86Bus.c

/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Bus.c,v 1.80 2004/02/05 18:24:59 eich Exp $ */
/*
 * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Except as contained in this notice, the name of the copyright holder(s)
 * and author(s) shall not be used in advertising or otherwise to promote
 * the sale, use or other dealings in this Software without prior written
 * authorization from the copyright holder(s) and author(s).
 */

#define REDUCER
/*
 * This file contains the interfaces to the bus-specific code
 */

#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif

#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <X11/X.h>
#include "os.h"
#include "xf86.h"
#include "xf86Priv.h"
#include "xf86Resources.h"

/* Bus-specific headers */

#include "xf86Bus.h"

#define XF86_OS_PRIVS
#define NEED_OS_RAC_PROTOS
#include "xf86_OSproc.h"

#include "xf86RAC.h"

/* Entity data */
EntityPtr *xf86Entities = NULL;     /* Bus slots claimed by drivers */
int xf86NumEntities = 0;
static int xf86EntityPrivateCount = 0;
BusAccPtr xf86BusAccInfo = NULL;

xf86AccessRec AccessNULL = {NULL,NULL,NULL};

xf86CurrentAccessRec xf86CurrentAccess = {NULL,NULL};

BusRec primaryBus = { BUS_NONE, {{0}}};

Bool xf86ResAccessEnter = FALSE;

#ifdef REDUCER
/* Resources that temporarily conflict with estimated resources */
static resPtr AccReducers = NULL;
#endif

/* resource lists */
resPtr Acc = NULL;
resPtr osRes = NULL;

/* allocatable ranges */
resPtr ResRange = NULL;

/* predefined special resources */
resRange resVgaExclusive[] = {_VGA_EXCLUSIVE, _END};
resRange resVgaShared[] = {_VGA_SHARED, _END};
resRange resVgaMemShared[] = {_VGA_SHARED_MEM,_END};
resRange resVgaIoShared[] = {_VGA_SHARED_IO,_END};
resRange resVgaUnusedExclusive[] = {_VGA_EXCLUSIVE_UNUSED, _END};
resRange resVgaUnusedShared[] = {_VGA_SHARED_UNUSED, _END};
resRange resVgaSparseExclusive[] = {_VGA_EXCLUSIVE_SPARSE, _END};
resRange resVgaSparseShared[] = {_VGA_SHARED_SPARSE, _END};
resRange res8514Exclusive[] = {_8514_EXCLUSIVE, _END};
resRange res8514Shared[] = {_8514_SHARED, _END};

/* Flag: do we need RAC ? */
static Bool needRAC = FALSE;
static Bool doFramebufferMode = FALSE;

/* state change notification callback list */
static StateChangeNotificationPtr StateChangeNotificationList;
static void notifyStateChange(xf86NotifyState state);

#undef MIN
#define MIN(x,y) ((x<y)?x:y)


/*
 * Call the bus probes relevant to the architecture.
 *
 * The only one available so far is for PCI and SBUS.
 */

void
xf86BusProbe(void)
{
    xf86PciProbe();
#if defined(__sparc__) && !defined(__OpenBSD__)
    xf86SbusProbe();
#endif
}

/*
 * Determine what bus type the busID string represents.  The start of the
 * bus-dependent part of the string is returned as retID.
 */

BusType
StringToBusType(const char* busID, const char **retID)
{
    char *p, *s;
    BusType ret = BUS_NONE;

    /* If no type field, Default to PCI */
    if (isdigit(busID[0])) {
      if (retID)
          *retID = busID;
      return BUS_PCI;
    }

    s = xstrdup(busID);
    p = strtok(s, ":");
    if (p == NULL || *p == 0) {
      xfree(s);
      return BUS_NONE;
    }
    if (!xf86NameCmp(p, "pci") || !xf86NameCmp(p, "agp"))
      ret = BUS_PCI; 
    if (!xf86NameCmp(p, "isa"))
      ret = BUS_ISA;
    if (!xf86NameCmp(p, "sbus"))
      ret = BUS_SBUS;
    if (ret != BUS_NONE)
      if (retID)
          *retID = busID + strlen(p) + 1;
    xfree(s);
    return ret;
}

/*
 * Entity related code.
 */

void
xf86EntityInit(void)
{
    int i;
    resPtr *pprev_next;
    resPtr res;
    xf86AccessPtr pacc;
    
    for (i = 0; i < xf86NumEntities; i++)
      if (xf86Entities[i]->entityInit) {
          if (xf86Entities[i]->access->busAcc)
            ((BusAccPtr)xf86Entities[i]->access->busAcc)->set_f
                (xf86Entities[i]->access->busAcc);
          pacc = xf86Entities[i]->access->fallback;
          if (pacc->AccessEnable)
            pacc->AccessEnable(pacc->arg);
          xf86Entities[i]->entityInit(i,xf86Entities[i]->private);
          if (pacc->AccessDisable)
            pacc->AccessDisable(pacc->arg);
          /* remove init resources after init is processed */
          pprev_next = &Acc;
          res = Acc;
          while (res) {  
            if (res->res_type & ResInit && (res->entityIndex == i)) {
                (*pprev_next) = res->next;
                xfree(res);
            } else 
                pprev_next = &(res->next);
            res = (*pprev_next);
          }
      }
}

int
xf86AllocateEntity(void)
{
    xf86NumEntities++;
    xf86Entities = xnfrealloc(xf86Entities,
                        sizeof(EntityPtr) * xf86NumEntities);
    xf86Entities[xf86NumEntities - 1] = xnfcalloc(1,sizeof(EntityRec));
    xf86Entities[xf86NumEntities - 1]->entityPrivates =
               xnfcalloc(sizeof(DevUnion) * xf86EntityPrivateCount, 1);
    return (xf86NumEntities - 1);
}

static void
EntityEnter(void)
{
    int i;
    xf86AccessPtr pacc;
    
    for (i = 0; i < xf86NumEntities; i++)
      if (xf86Entities[i]->entityEnter) {
          if (xf86Entities[i]->access->busAcc)
            ((BusAccPtr)xf86Entities[i]->access->busAcc)->set_f
                (xf86Entities[i]->access->busAcc);
          pacc = xf86Entities[i]->access->fallback;
          if (pacc->AccessEnable)
            pacc->AccessEnable(pacc->arg);
          xf86Entities[i]->entityEnter(i,xf86Entities[i]->private);
          if (pacc->AccessDisable)
            pacc->AccessDisable(pacc->arg);
      }
}

static void
EntityLeave(void)
{
    int i;
    xf86AccessPtr pacc;

    for (i = 0; i < xf86NumEntities; i++)
      if (xf86Entities[i]->entityLeave) {
          if (xf86Entities[i]->access->busAcc)
            ((BusAccPtr)xf86Entities[i]->access->busAcc)->set_f
                (xf86Entities[i]->access->busAcc);
          pacc = xf86Entities[i]->access->fallback;
          if (pacc->AccessEnable)
            pacc->AccessEnable(pacc->arg);
          xf86Entities[i]->entityLeave(i,xf86Entities[i]->private);
          if (pacc->AccessDisable)
            pacc->AccessDisable(pacc->arg);
      }
}

Bool
xf86IsEntityPrimary(int entityIndex)
{
    EntityPtr pEnt = xf86Entities[entityIndex];
    
    if (primaryBus.type != pEnt->busType) return FALSE;

    switch (pEnt->busType) {
    case BUS_PCI:
      return (pEnt->pciBusId.bus == primaryBus.id.pci.bus &&
            pEnt->pciBusId.device == primaryBus.id.pci.device &&
            pEnt->pciBusId.func == primaryBus.id.pci.func);
    case BUS_ISA:
      return TRUE;
    case BUS_SBUS:
      return (pEnt->sbusBusId.fbNum == primaryBus.id.sbus.fbNum);
    default:
      return FALSE;
    }
}
      
Bool
xf86SetEntityFuncs(int entityIndex, EntityProc init, EntityProc enter,
               EntityProc leave, pointer private)
{
    if (entityIndex >= xf86NumEntities)
      return FALSE;
    xf86Entities[entityIndex]->entityInit = init;
    xf86Entities[entityIndex]->entityEnter = enter;
    xf86Entities[entityIndex]->entityLeave = leave;
    xf86Entities[entityIndex]->private = private;
    return TRUE;
}

Bool
xf86DriverHasEntities(DriverPtr drvp)
{
    int i;
    for (i = 0; i < xf86NumEntities; i++) {
      if (xf86Entities[i]->driver == drvp) 
          return TRUE;
    }
    return FALSE;
}

void
xf86AddEntityToScreen(ScrnInfoPtr pScrn, int entityIndex)
{
    if (entityIndex == -1)
      return;
    if (xf86Entities[entityIndex]->inUse &&
      !(xf86Entities[entityIndex]->entityProp & IS_SHARED_ACCEL))
      FatalError("Requested Entity already in use!\n");

    pScrn->numEntities++;
    pScrn->entityList = xnfrealloc(pScrn->entityList,
                            pScrn->numEntities * sizeof(int));
    pScrn->entityList[pScrn->numEntities - 1] = entityIndex;
    xf86Entities[entityIndex]->access->next = pScrn->access;
    pScrn->access = xf86Entities[entityIndex]->access;
    xf86Entities[entityIndex]->inUse = TRUE;
    pScrn->entityInstanceList = xnfrealloc(pScrn->entityInstanceList,
                            pScrn->numEntities * sizeof(int));
    pScrn->entityInstanceList[pScrn->numEntities - 1] = 0;
    pScrn->domainIOBase = xf86Entities[entityIndex]->domainIO;
}

void
xf86SetEntityInstanceForScreen(ScrnInfoPtr pScrn, int entityIndex, int instance)
{
    int i;

    if (entityIndex == -1 || entityIndex >= xf86NumEntities)
      return;

    for (i = 0; i < pScrn->numEntities; i++) {
      if (pScrn->entityList[i] == entityIndex) {
          pScrn->entityInstanceList[i] = instance;
          break;
      }
    }
}

/*
 * XXX  This needs to be updated for the case where a single entity may have
 * instances associated with more than one screen.
 */
ScrnInfoPtr
xf86FindScreenForEntity(int entityIndex)
{
    int i,j;

    if (entityIndex == -1) return NULL;
    
    if (xf86Screens) {
      for (i = 0; i < xf86NumScreens; i++) {
          for (j = 0; j < xf86Screens[i]->numEntities; j++) {
            if ( xf86Screens[i]->entityList[j] == entityIndex )
                return (xf86Screens[i]);
          }
      }
    }
    return NULL;
}

void
xf86RemoveEntityFromScreen(ScrnInfoPtr pScrn, int entityIndex)
{
    int i;
    EntityAccessPtr *ptr = (EntityAccessPtr *)&pScrn->access;
    EntityAccessPtr peacc;
    
    for (i = 0; i < pScrn->numEntities; i++) {
      if (pScrn->entityList[i] == entityIndex) {
          peacc = xf86Entities[pScrn->entityList[i]]->access;
          (*ptr) = peacc->next;
          /* disable entity: call disable func */
          if (peacc->pAccess && peacc->pAccess->AccessDisable)
            peacc->pAccess->AccessDisable(peacc->pAccess->arg);
          /* also disable fallback - just in case */
          if (peacc->fallback && peacc->fallback->AccessDisable)
            peacc->fallback->AccessDisable(peacc->fallback->arg);
          for (i++; i < pScrn->numEntities; i++)
            pScrn->entityList[i-1] = pScrn->entityList[i];
          pScrn->numEntities--;
          xf86Entities[entityIndex]->inUse = FALSE;
          break;
      }
      ptr = &(xf86Entities[pScrn->entityList[i]]->access->next);
    }
}

/*
 * xf86ClearEntitiesForScreen() - called when a screen is deleted
 * to mark it's entities unused. Called by xf86DeleteScreen().
 */
void
xf86ClearEntityListForScreen(int scrnIndex)
{
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
    EntityAccessPtr peacc;
    int i, entityIndex;
    
    if (pScrn->entityList == NULL || pScrn->numEntities == 0) return;
      
    for (i = 0; i < pScrn->numEntities; i++) {
      entityIndex = pScrn->entityList[i];
      xf86Entities[entityIndex]->inUse = FALSE;
      /* disable resource: call the disable function */
      peacc = xf86Entities[entityIndex]->access;
      if (peacc->pAccess && peacc->pAccess->AccessDisable)
          peacc->pAccess->AccessDisable(peacc->pAccess->arg);
      /* and the fallback function */
      if (peacc->fallback && peacc->fallback->AccessDisable)
          peacc->fallback->AccessDisable(peacc->fallback->arg);
      /* shared resources are only needed when entity is active: remove */
      xf86DeallocateResourcesForEntity(entityIndex, ResShared);
    }
    xfree(pScrn->entityList);
    xfree(pScrn->entityInstanceList);
    if (pScrn->CurrentAccess->pIoAccess == (EntityAccessPtr)pScrn->access)
      pScrn->CurrentAccess->pIoAccess = NULL;
    if (pScrn->CurrentAccess->pMemAccess == (EntityAccessPtr)pScrn->access)
      pScrn->CurrentAccess->pMemAccess = NULL;
    pScrn->entityList = NULL;
    pScrn->entityInstanceList = NULL;
}

void
xf86DeallocateResourcesForEntity(int entityIndex, unsigned long type)
{
    resPtr *pprev_next = &Acc;
    resPtr res = Acc;

    while (res) {
      if (res->entityIndex == entityIndex &&
          (type & ResAccMask & res->res_type))
      {
          (*pprev_next) = res->next;
          xfree(res);
      } else 
          pprev_next = &(res->next);
      res = (*pprev_next);
    }
}

/*
 * Add an extra device section (GDevPtr) to an entity.
 */

void
xf86AddDevToEntity(int entityIndex, GDevPtr dev)
{
    EntityPtr pEnt;
    
    if (entityIndex >= xf86NumEntities)
      return;
    
    pEnt = xf86Entities[entityIndex];
    pEnt->numInstances++;
    pEnt->devices = xnfrealloc(pEnt->devices,
                        pEnt->numInstances * sizeof(GDevPtr));
    pEnt->devices[pEnt->numInstances - 1] = dev;
    dev->claimed = TRUE;
}

/*
 * xf86GetEntityInfo() -- This function hands information from the
 * EntityRec struct to the drivers. The EntityRec structure itself
 * remains invisible to the driver.
 */
EntityInfoPtr
xf86GetEntityInfo(int entityIndex)
{
    EntityInfoPtr pEnt;
    int i;
    
    if (entityIndex >= xf86NumEntities)
      return NULL;
    
    pEnt = xnfcalloc(1,sizeof(EntityInfoRec));
    pEnt->index = entityIndex;
    pEnt->location = xf86Entities[entityIndex]->bus;
    pEnt->active = xf86Entities[entityIndex]->active;
    pEnt->chipset = xf86Entities[entityIndex]->chipset;
    pEnt->resources = xf86Entities[entityIndex]->resources;
    pEnt->driver = xf86Entities[entityIndex]->driver;
    if ( (xf86Entities[entityIndex]->devices) &&
         (xf86Entities[entityIndex]->devices[0]) ) {
      for (i = 0; i < xf86Entities[entityIndex]->numInstances; i++)
          if (xf86Entities[entityIndex]->devices[i]->screen == 0)
              break;
      pEnt->device = xf86Entities[entityIndex]->devices[i];
    } else
      pEnt->device = NULL;
    
    return pEnt;
}

int
xf86GetNumEntityInstances(int entityIndex)
{
    if (entityIndex >= xf86NumEntities)
      return -1;
    
    return xf86Entities[entityIndex]->numInstances;
}

GDevPtr
xf86GetDevFromEntity(int entityIndex, int instance)
{
    int i;
  
    /* We might not use AddDevtoEntity */
    if ( (!xf86Entities[entityIndex]->devices) ||
         (!xf86Entities[entityIndex]->devices[0]) ) 
      return NULL;

    if (entityIndex >= xf86NumEntities ||
      instance >= xf86Entities[entityIndex]->numInstances)
      return NULL;
    
    for (i = 0; i < xf86Entities[entityIndex]->numInstances; i++)
      if (xf86Entities[entityIndex]->devices[i]->screen == instance)
          break;
    return xf86Entities[entityIndex]->devices[i];
}

/*
 * general generic disable function.
 */
static void
disableAccess(void)
{
    int i;
    xf86AccessPtr pacc;
    EntityAccessPtr peacc;
    
    /* call disable funcs and reset current access pointer */
    /* the entity specific access funcs are in an enabled  */
    /* state - driver must restore their state explicitely */
    for (i = 0; i < xf86NumScreens; i++) {
      peacc = xf86Screens[i]->CurrentAccess->pIoAccess;
      while (peacc) {
          if (peacc->pAccess && peacc->pAccess->AccessDisable)
            peacc->pAccess->AccessDisable(peacc->pAccess->arg);
          peacc = peacc->next;
      }
      xf86Screens[i]->CurrentAccess->pIoAccess = NULL;
      peacc = xf86Screens[i]->CurrentAccess->pMemAccess;
      while (peacc) {
          if (peacc->pAccess && peacc->pAccess->AccessDisable)
            peacc->pAccess->AccessDisable(peacc->pAccess->arg);
          peacc = peacc->next;
      }
      xf86Screens[i]->CurrentAccess->pMemAccess = NULL;
    }
    /* then call the generic entity disable funcs */
    for (i = 0; i < xf86NumEntities; i++) {
      pacc = xf86Entities[i]->access->fallback; 
      if (pacc->AccessDisable)
          pacc->AccessDisable(pacc->arg);
    }
}

static void
clearAccess(void)
{
    int i;
    
    /* call disable funcs and reset current access pointer */
    /* the entity specific access funcs are in an enabled  */
    /* state - driver must restore their state explicitely */
    for (i = 0; i < xf86NumScreens; i++) {
      xf86Screens[i]->CurrentAccess->pIoAccess = NULL;
      xf86Screens[i]->CurrentAccess->pMemAccess = NULL;
    }

}

/*
 * Generic interface to bus specific code - add other buses here
 */

/*
 * xf86AccessInit() - set up everything needed for access control
 * called only once on first server generation.
 */
void
xf86AccessInit(void)
{
    initPciState();
    initPciBusState();
    DisablePciBusAccess();
    DisablePciAccess();
    
    xf86ResAccessEnter = TRUE;
}

/*
 * xf86AccessEnter() -- gets called to save the text mode VGA IO 
 * resources when reentering the server after a VT switch.
 */
void
xf86AccessEnter(void)
{
    if (xf86ResAccessEnter) 
      return;

    /*
     * on enter we simply disable routing of special resources
     * to any bus and let the RAC code to "open" the right bridges.
     */
    PciBusStateEnter();
    DisablePciBusAccess();
    PciStateEnter();
    disableAccess();
    EntityEnter();
    notifyStateChange(NOTIFY_ENTER);
    xf86EnterServerState(SETUP);
    xf86ResAccessEnter = TRUE;
}

/*
 * xf86AccessLeave() -- prepares access for and calls the
 * entityLeave() functions.
 * xf86AccessLeaveState() --- gets called to restore the
 * access to the VGA IO resources when switching VT or on
 * server exit.
 * This was split to call xf86AccessLeaveState() from
 * ddxGiveUp().
 */
void
xf86AccessLeave(void)
{
    if (!xf86ResAccessEnter)
      return;
    notifyStateChange(NOTIFY_LEAVE);
    disableAccess();
    DisablePciBusAccess();
    EntityLeave();
}

void
xf86AccessLeaveState(void)
{
    if (!xf86ResAccessEnter)
      return;
    xf86ResAccessEnter = FALSE;
    PciStateLeave();
    PciBusStateLeave();
}

/*
 * xf86AccessRestoreState() - Restore the access registers to the
 * state before X was started. This is handy for framebuffers.
 */
static void 
xf86AccessRestoreState(void)
{
    if (!xf86ResAccessEnter)
      return;
    PciStateLeave();
    PciBusStateLeave();
}

/*
 * xf86EnableAccess() -- enable access to controlled resources.
 * To reduce latency when switching access the ScrnInfoRec has
 * a linked list of the EntityAccPtr of all screen entities.
 */
/*
 * switching access needs to be done in te following oder:
 * disable
 * 1. disable old entity
 * 2. reroute bus
 * 3. enable new entity
 * Otherwise resources needed for access control might be shadowed
 * by other resources!
 */
#ifdef async

static AsyncQPtr *AsyncQ = NULL;
ScrnInfoPtr xf86CurrentScreen = NULL;

#define SETUP_Q  org = AsyncQ; \
               AsyncQ = &new;

#define PROCESS_Q xf86CurrentScreen = pScrn;
                  if (!new) AsyncQ = org; \
                  else { \
                       AsyncQPtr tmp_Q; \
                       while (1) {\
                          new->func(new->arg);\
                          if (!(new->next)) {\
                        AsyncQ = org; xfree(new); break; \
                     } \
                     tmp_Q = new->next; \
                       xfree(new); \
                       new = tmp_Q; \
                   } \
                  }
#else
#define SETUP_Q
#define PROCESS_Q
#endif

void
xf86EnableAccess(ScrnInfoPtr pScrn)
{
    register EntityAccessPtr peAcc = (EntityAccessPtr) pScrn->access;
    register EntityAccessPtr pceAcc;
    register xf86AccessPtr pAcc;
    EntityAccessPtr tmp;
#ifdef async
    AsyncQPtr *org, new = NULL;
#endif

#ifdef DEBUG
    ErrorF("Enable access %i\n",pScrn->scrnIndex);
#endif

    /* Entity is not under access control or currently enabled */
    if (!pScrn->access) {
      if (pScrn->busAccess) {
          SETUP_Q;
          ((BusAccPtr)pScrn->busAccess)->set_f(pScrn->busAccess);
          PROCESS_Q;
      }
      return;
    }
    
    switch (pScrn->resourceType) {
    case IO:
      pceAcc = pScrn->CurrentAccess->pIoAccess;
      if (peAcc == pceAcc) {
          return;
      }
      SETUP_Q;
      if (pScrn->CurrentAccess->pMemAccess == pceAcc)
          pScrn->CurrentAccess->pMemAccess = NULL;
      while (pceAcc) {
          pAcc = pceAcc->pAccess;
          if ( pAcc && pAcc->AccessDisable) 
            (*pAcc->AccessDisable)(pAcc->arg);
          pceAcc = pceAcc->next;
      }
      if (pScrn->busAccess)
          ((BusAccPtr)pScrn->busAccess)->set_f(pScrn->busAccess);
      while (peAcc) {
          pAcc = peAcc->pAccess;
          if (pAcc && pAcc->AccessEnable) 
            (*pAcc->AccessEnable)(pAcc->arg);
          peAcc = peAcc->next;
      }
      pScrn->CurrentAccess->pIoAccess = (EntityAccessPtr) pScrn->access;
      PROCESS_Q;
      return;
      
    case MEM_IO:
      pceAcc = pScrn->CurrentAccess->pIoAccess;
      if (peAcc != pceAcc) { /* current Io != pAccess */
          SETUP_Q;
          tmp = pceAcc;
          while (pceAcc) {
            pAcc = pceAcc->pAccess;
            if (pAcc && pAcc->AccessDisable)
                (*pAcc->AccessDisable)(pAcc->arg);
            pceAcc = pceAcc->next;
          }
          pceAcc = pScrn->CurrentAccess->pMemAccess;
          if (peAcc != pceAcc /* current Mem != pAccess */
            && tmp !=pceAcc) {
            while (pceAcc) {
                pAcc = pceAcc->pAccess;
                if (pAcc && pAcc->AccessDisable)
                  (*pAcc->AccessDisable)(pAcc->arg);
                pceAcc = pceAcc->next;
            }
          }
      } else {    /* current Io == pAccess */
          pceAcc = pScrn->CurrentAccess->pMemAccess;
          if (pceAcc == peAcc) { /* current Mem == pAccess */
            return;
          }
          SETUP_Q;
          while (pceAcc) {  /* current Mem != pAccess */
            pAcc = pceAcc->pAccess;
            if (pAcc && pAcc->AccessDisable) 
                (*pAcc->AccessDisable)(pAcc->arg);
            pceAcc = pceAcc->next;
          }
      }
      if (pScrn->busAccess)
          ((BusAccPtr)pScrn->busAccess)->set_f(pScrn->busAccess);
      while (peAcc) {
          pAcc = peAcc->pAccess;
          if (pAcc && pAcc->AccessEnable) 
            (*pAcc->AccessEnable)(pAcc->arg);
            peAcc = peAcc->next;
      }
      pScrn->CurrentAccess->pMemAccess =
          pScrn->CurrentAccess->pIoAccess = (EntityAccessPtr) pScrn->access;
      PROCESS_Q;
      return;
      
    case MEM:
      pceAcc = pScrn->CurrentAccess->pMemAccess;
      if (peAcc == pceAcc) {
          return;
      }
      SETUP_Q;
      if (pScrn->CurrentAccess->pIoAccess == pceAcc)
          pScrn->CurrentAccess->pIoAccess = NULL;
      while (pceAcc) {
          pAcc = pceAcc->pAccess;
          if ( pAcc && pAcc->AccessDisable) 
            (*pAcc->AccessDisable)(pAcc->arg);
          pceAcc = pceAcc->next;
      }
      if (pScrn->busAccess)
          ((BusAccPtr)pScrn->busAccess)->set_f(pScrn->busAccess);
      while (peAcc) {
          pAcc = peAcc->pAccess;
          if (pAcc && pAcc->AccessEnable) 
            (*pAcc->AccessEnable)(pAcc->arg);
          peAcc = peAcc->next;
      }
      pScrn->CurrentAccess->pMemAccess = (EntityAccessPtr) pScrn->access;
      PROCESS_Q;
      return;

    case NONE:
      if (pScrn->busAccess) {
          SETUP_Q;
          ((BusAccPtr)pScrn->busAccess)->set_f(pScrn->busAccess);
          PROCESS_Q;
      }
      return;
    }
}

void
xf86SetCurrentAccess(Bool Enable, ScrnInfoPtr pScrn)
{
    EntityAccessPtr pceAcc2 = NULL;
    register EntityAccessPtr pceAcc = NULL;
    register xf86AccessPtr pAcc;

    
    switch(pScrn->resourceType) {
    case IO:
      pceAcc = pScrn->CurrentAccess->pIoAccess;
      break;
    case MEM:
      pceAcc = pScrn->CurrentAccess->pMemAccess;
      break;
    case MEM_IO:
      pceAcc = pScrn->CurrentAccess->pMemAccess;
      pceAcc2 = pScrn->CurrentAccess->pIoAccess;
      break;
    default:
      break;
    }

    while (pceAcc) {
      pAcc = pceAcc->pAccess;
      if ( pAcc) {
          if (!Enable) {
            if (pAcc->AccessDisable) 
                (*pAcc->AccessDisable)(pAcc->arg);
          } else {
            if (pAcc->AccessEnable) 
                (*pAcc->AccessEnable)(pAcc->arg);
          }
      }
      pceAcc = pceAcc->next;
      if (!pceAcc) {
          pceAcc = pceAcc2;
          pceAcc2 = NULL;
      }
    }
}

void
xf86SetAccessFuncs(EntityInfoPtr pEnt, xf86SetAccessFuncPtr funcs,
               xf86SetAccessFuncPtr oldFuncs)
{
    AccessFuncPtr rac;

    if (!xf86Entities[pEnt->index]->rac)
      xf86Entities[pEnt->index]->rac = xnfcalloc(1,sizeof(AccessFuncRec));

    rac = xf86Entities[pEnt->index]->rac;

    if (funcs->mem == funcs->io_mem && funcs->mem && funcs->io)
      xf86Entities[pEnt->index]->entityProp |= NO_SEPARATE_MEM_FROM_IO;
    if (funcs->io == funcs->io_mem && funcs->mem && funcs->io)
      xf86Entities[pEnt->index]->entityProp |= NO_SEPARATE_IO_FROM_MEM;
    
    rac->mem_new = funcs->mem;
    rac->io_new = funcs->io;
    rac->io_mem_new = funcs->io_mem;
    
    rac->old = oldFuncs;
}

/*
 * Conflict checking
 */

static memType
getMask(memType val)
{
    memType mask = 0;
    memType tmp = 0;
    
    mask=~mask;
    tmp = ~((~tmp) >> 1);
    
    while (!(val & tmp)) {
      mask = mask >> 1;
      val = val << 1;
    }
    return mask;
}

/*
 * checkConflictBlock() -- check for conflicts of a block resource range.
 * If conflict is found return end of conflicting range. Else return 0.
 */
static memType
checkConflictBlock(resRange *range, resPtr pRes)
{
    memType val,tmp,prev;
    int i;
    
    switch (pRes->res_type & ResExtMask) {
    case ResBlock:
      if (range->rBegin < pRes->block_end &&
          range->rEnd > pRes->block_begin) {
#ifdef DEBUG
          ErrorF("b-b conflict w: %lx %lx\n",
               pRes->block_begin,pRes->block_end);
#endif
          return pRes->block_end < range->rEnd ?
            pRes->block_end : range->rEnd;
      }
      return 0;
    case ResSparse:
      if (pRes->sparse_base > range->rEnd) return 0;
      
      val = (~pRes->sparse_mask | pRes->sparse_base) & getMask(range->rEnd);
#ifdef DEBUG
      ErrorF("base = 0x%lx, mask = 0x%lx, begin = 0x%lx, end = 0x%lx ,"
             "val = 0x%lx\n",
            pRes->sparse_base, pRes->sparse_mask, range->rBegin,
            range->rEnd, val);
#endif
      i = sizeof(memType) * 8;
      tmp = prev = pRes->sparse_base;
      
      while (i) {
          tmp |= 1<< (--i) & val;
          if (tmp > range->rEnd)
            tmp = prev;
          else
            prev = tmp;
      }
      if (tmp >= range->rBegin) {
#ifdef DEBUG
          ErrorF("conflict found at: 0x%lx\n",tmp);
          ErrorF("b-d conflict w: %lx %lx\n",
               pRes->sparse_base,pRes->sparse_mask);
#endif
          return tmp;
      }
      else
          return 0;
    }
    return 0;
}

/*
 * checkConflictSparse() -- check for conflicts of a sparse resource range.
 * If conflict is found return base of conflicting region. Else return 0.
 */
#define mt_max ~(memType)0
#define length sizeof(memType) * 8
static memType
checkConflictSparse(resRange *range, resPtr pRes)
{
    memType val, tmp, prev;
    int i;
    
    switch (pRes->res_type & ResExtMask) {
    case ResSparse:
      tmp = pRes->sparse_mask & range->rMask;
      if ((tmp & pRes->sparse_base) == (tmp & range->rBase)) {
#ifdef DEBUG
          ErrorF("s-b conflict w: %lx %lx\n",
               pRes->sparse_base,pRes->sparse_mask);
#endif
          return pRes->sparse_mask;
      }
      return 0;

    case ResBlock:
      if (pRes->block_end < range->rBase) return 0;
      
      val = (~range->rMask | range->rBase) & getMask(pRes->block_end);
      i = length;
      tmp = prev = range->rBase;
      
      while (i) {
#ifdef DEBUG
          ErrorF("tmp = 0x%lx\n",tmp);
#endif
          tmp |= 1<< (--i) & val;
          if (tmp > pRes->block_end)
            tmp = prev;
          else
            prev = tmp;
      }
      if (tmp < pRes->block_begin) 
          return 0;
      else {
          /*
           * now we subdivide the block region in sparse regions
           * with base values = 2^n and find the smallest mask.
           * This might be done in a simpler way....
           */
          memType mask, m_mask = 0, base = pRes->block_begin;
          int i;      
          while (base < pRes->block_end) {
            for (i = 1; i < length; i++)
                if ( base != (base & (mt_max << i))) break;
            mask = mt_max >> (length - i);
            do mask >>= 1;
            while ((mask + base + 1) > pRes->block_end);
            /* m_mask and are _inverted_ sparse masks */ 
            m_mask = mask > m_mask ? mask : m_mask;
            base = base + mask + 1;
          }
#ifdef DEBUG
          ErrorF("conflict found at: 0x%lx\n",tmp);
          ErrorF("b-b conflict w: %lx %lx\n",
               pRes->block_begin,pRes->block_end);
#endif
          return ~m_mask; 
      }
    }
    return 0;
}
#undef mt_max
#undef length

/*
 * needCheck() -- this function decides whether to check for conflicts
 * depending on the types of the resource ranges and their locations
 */
static Bool
needCheck(resPtr pRes, unsigned long type, int entityIndex, xf86State state)
{
    /* the same entity shouldn't conflict with itself */
    ScrnInfoPtr pScrn;
    int i;
    BusType loc = BUS_NONE;
    BusType r_loc = BUS_NONE;

    /* Ignore overlapped ranges that have been nullified */
    if ((pRes->res_type & ResOverlap) && (pRes->block_begin > pRes->block_end))
      return FALSE;
    
    if ((pRes->res_type & ResTypeMask) != (type & ResTypeMask))
        return FALSE;

    /*
     * Resources set by BIOS (ResBios) are allowed to conflict
     * with resources marked (ResBios).
     */
    if (pRes->res_type & type & ResBios)
      return FALSE;
    
    /*If requested, skip over estimated resources */
    if (pRes->res_type & type & ResEstimated)
      return FALSE;
      
    if (type & pRes->res_type & ResUnused)
      return FALSE;

    if (state == OPERATING) {
      if (type & ResDisableOpr || pRes->res_type & ResDisableOpr)
          return FALSE;
      if (type & pRes->res_type & ResUnusedOpr) return FALSE;
      /*
       * Maybe we should have ResUnused set The resUnusedOpr
       * bit, too. This way we could avoid this confusion
       */
      if ((type & ResUnusedOpr && pRes->res_type & ResUnused) ||
          (type & ResUnused && pRes->res_type & ResUnusedOpr))
          return FALSE;
    }
    
    if (entityIndex > -1)
      loc = xf86Entities[entityIndex]->busType;
    if (pRes->entityIndex > -1)
      r_loc = xf86Entities[pRes->entityIndex]->busType;

    switch (type & ResAccMask) {
    case ResExclusive:
      switch (pRes->res_type & ResAccMask) {
      case ResExclusive:
          break;
      case ResShared:
          /* ISA buses are only locally exclusive on a PCI system */
          if (loc == BUS_ISA && r_loc == BUS_PCI)
            return FALSE;
          break;
      }
      break;
    case ResShared:
      switch (pRes->res_type & ResAccMask) {
      case ResExclusive:
          /* ISA buses are only locally exclusive on a PCI system */
          if (loc == BUS_PCI && r_loc == BUS_ISA) 
            return FALSE;
          break;
      case ResShared:
          return FALSE;
      }
      break;
    case ResAny:
      break;
    }
    
    if (pRes->entityIndex == entityIndex) return FALSE;

    if (pRes->entityIndex > -1 &&
      (pScrn = xf86FindScreenForEntity(entityIndex))) {
      for (i = 0; i < pScrn->numEntities; i++)
          if (pScrn->entityList[i] == pRes->entityIndex) return FALSE;
    }
    return TRUE;
}

/*
 * checkConflict() - main conflict checking function which all other
 * function call.
 */
static memType
checkConflict(resRange *rgp, resPtr pRes, int entityIndex,
            xf86State state, Bool ignoreIdentical)
{
    memType ret;
    
    while(pRes) {
      if (!needCheck(pRes,rgp->type, entityIndex ,state)) { 
          pRes = pRes->next;                    
          continue;                             
      }
      switch (rgp->type & ResExtMask) {
      case ResBlock:
          if (rgp->rEnd < rgp->rBegin) {
            xf86Msg(X_ERROR,"end of block range 0x%lx < begin 0x%lx\n",
                  rgp->rEnd,rgp->rBegin);
            return 0;
          }
          if ((ret = checkConflictBlock(rgp, pRes))) {
            if (!ignoreIdentical || (rgp->rBegin != pRes->block_begin)
                || (rgp->rEnd != pRes->block_end))
                return ret;
          }
    break;
      case ResSparse:
          if ((rgp->rBase & rgp->rMask) != rgp->rBase) {
            xf86Msg(X_ERROR,"sparse io range (base: 0x%lx  mask: 0x%lx)"
                  "doesn't satisfy (base & mask = mask)\n",
                  rgp->rBase, rgp->rMask);
            return 0;
          }
          if ((ret = checkConflictSparse(rgp, pRes))) {
            if (!ignoreIdentical || (rgp->rBase != pRes->sparse_base)
                || (rgp->rMask != pRes->sparse_mask))
                return ret;
          }
          break;
      }
      pRes = pRes->next;
    }
    return 0;
}

/*
 * ChkConflict() -- used within xxxBus ; find conflict with any location.
 */
memType
ChkConflict(resRange *rgp, resPtr res, xf86State state)
{
    return checkConflict(rgp, res, -2, state,FALSE);
}

/*
 * xf86ChkConflict() - This function is the low level interface to
 * the resource broker that gets exported. Tests all resources ie.
 * performs test with SETUP flag.
 */
memType
xf86ChkConflict(resRange *rgp, int entityIndex)
{
    return checkConflict(rgp, Acc, entityIndex, SETUP,FALSE);
}

/*
 * Resources List handling
 */

resPtr
xf86JoinResLists(resPtr rlist1, resPtr rlist2)
{
    resPtr pRes;

    if (!rlist1)
      return rlist2;

    if (!rlist2)
      return rlist1;

    for (pRes = rlist1; pRes->next; pRes = pRes->next)
      ;
    pRes->next = rlist2;
    return rlist1;
}

resPtr
xf86AddResToList(resPtr rlist, resRange *range, int entityIndex)
{
    resPtr new;

    switch (range->type & ResExtMask) {
    case ResBlock:
      if (range->rEnd < range->rBegin) {
            xf86Msg(X_ERROR,"end of block range 0x%lx < begin 0x%lx\n",
                  range->rEnd,range->rBegin);
            return rlist;
      }
      break;
    case ResSparse:
      if ((range->rBase & range->rMask) != range->rBase) {
          xf86Msg(X_ERROR,"sparse io range (base: 0x%lx  mask: 0x%lx)"
                "doesn't satisfy (base & mask = mask)\n",
                range->rBase, range->rMask);
          return rlist;
      }
      break;
    }
    
    new = xnfalloc(sizeof(resRec));
    /* 
     * Only background resources may be registered with ResBios 
     * and ResEstimated set. Other resources only set it for
     * testing.
     */
    if (entityIndex != (-1)) 
        range->type &= ~(ResBios | ResEstimated);
    new->val = *range;
    new->entityIndex = entityIndex;
    new->next = rlist;
    return new;
}

void
xf86FreeResList(resPtr rlist)
{
    resPtr pRes;

    if (!rlist)
      return;

    for (pRes = rlist->next; pRes; rlist = pRes, pRes = pRes->next)
      xfree(rlist);
    xfree(rlist);
}

resPtr
xf86DupResList(const resPtr rlist)
{
    resPtr pRes, ret, prev, new;

    if (!rlist)
      return NULL;

    ret = xnfalloc(sizeof(resRec));
    *ret = *rlist;
    prev = ret;
    for (pRes = rlist->next; pRes; pRes = pRes->next) {
      new = xnfalloc(sizeof(resRec));
      *new = *pRes;
      prev->next = new;
      prev = new;
    }
    return ret;
}

void
xf86PrintResList(int verb, resPtr list)
{
    int i = 0;
    const char *s, *r;
    resPtr tmp = list;
    unsigned long type;
    
    if (!list)
      return;

    type = ResMem;
    r = "M";
    while (1) {
      while (list) {
          if ((list->res_type & ResPhysMask) == type) {
            switch (list->res_type & ResExtMask) {
            case ResBlock:
                xf86ErrorFVerb(verb,
                           "\t[%d] %d\t%ld\t0x%08lx - 0x%08lx (0x%lx)",
                           i, list->entityIndex,
                           (list->res_type & ResDomain) >> 24,
                           list->block_begin, list->block_end,
                           list->block_end - list->block_begin + 1);
                break;
            case ResSparse:
                xf86ErrorFVerb(verb, "\t[%d] %d\t%ld\t0x%08lx - 0x%08lx ",
                           i, list->entityIndex,
                           (list->res_type & ResDomain) >> 24,
                           list->sparse_base,list->sparse_mask);
                break;
            default:
                list = list->next;
                continue;
            }
            xf86ErrorFVerb(verb, " %s", r);
            switch (list->res_type & ResAccMask) {
            case ResExclusive:
                if (list->res_type & ResUnused)
                  s = "x";
                else
                  s = "X";
                break;
            case ResShared:
                if (list->res_type & ResUnused)
                  s = "s";
                else
                  s = "S";
                break;
            default:
                s = "?";
            }
            xf86ErrorFVerb(verb, "%s", s);
            switch (list->res_type & ResExtMask) {
            case ResBlock:
                s = "[B]";
                break;
            case ResSparse:
                s = "[S]";
                break;
            default:
                s = "[?]";
            }
            xf86ErrorFVerb(verb, "%s", s);
            if (list->res_type & ResEstimated)
                xf86ErrorFVerb(verb, "E");
            if (list->res_type & ResOverlap)
                xf86ErrorFVerb(verb, "O");
            if (list->res_type & ResInit)
                xf86ErrorFVerb(verb, "t");
            if (list->res_type & ResBios)
                xf86ErrorFVerb(verb, "(B)");
            if (list->res_type & ResBus)
                xf86ErrorFVerb(verb, "(b)");
            if (list->res_type & ResOprMask) {
                switch (list->res_type & ResOprMask) {
                case ResUnusedOpr:
                  s = "(OprU)";
                  break;
                case ResDisableOpr:
                  s = "(OprD)";
                  break;
                default:
                  s = "(Opr?)";
                  break;
                }
                xf86ErrorFVerb(verb, "%s", s);
            }
            xf86ErrorFVerb(verb, "\n");
            i++;
          }
          list = list->next;
      }
      if (type == ResIo) break;
      type = ResIo;
      r = "I";
      list = tmp;
    }
}

resPtr
xf86AddRangesToList(resPtr list, resRange *pRange, int entityIndex)
{
    while(pRange && pRange->type != ResEnd) {
      list = xf86AddResToList(list,pRange,entityIndex);
      pRange++;
    }
    return list;
}

void
xf86ResourceBrokerInit(void)
{
    resPtr resPci;

    osRes = NULL;

    /* Get the addressable ranges */
    ResRange = xf86BusAccWindowsFromOS();
    xf86MsgVerb(X_INFO, 3, "Addressable bus resource ranges are\n");
    xf86PrintResList(3, ResRange);

    /* Get the ranges used exclusively by the system */
    osRes = xf86AccResFromOS(osRes);
    xf86MsgVerb(X_INFO, 3, "OS-reported resource ranges:\n");
    xf86PrintResList(3, osRes);

    /* Bus dep initialization */
    resPci = ResourceBrokerInitPci(&osRes);
    Acc = xf86JoinResLists(xf86DupResList(osRes), resPci);
    
    xf86MsgVerb(X_INFO, 3, "All system resource ranges:\n");
    xf86PrintResList(3, Acc);

}

#define MEM_ALIGN (1024 * 1024)

/*
 * RemoveOverlaps() -- remove overlaps between resources of the
 * same kind.
 * Beware: This function doesn't check for access attributes.
 * At resource broker initialization this is no problem as this
 * only deals with exclusive resources.
 */
#if 0
void
RemoveOverlaps(resPtr target, resPtr list, Bool pow2Alignment, Bool useEstimated)
{
    resPtr pRes;
    memType size, newsize, adjust;

    if (!target)
      return;
    
    for (pRes = list; pRes; pRes = pRes->next) {
      if (pRes != target
          && ((pRes->res_type & ResTypeMask) ==
            (target->res_type & ResTypeMask))
          && pRes->block_begin <= target->block_end
          && pRes->block_end >= target->block_begin) {
          /* Possibly ignore estimated resources */
          if (!useEstimated && (pRes->res_type & ResEstimated)) continue;
          /*
           * Target should be a larger region than pRes.  If pRes fully
           * contains target, don't do anything unless target can overlap.
           */
          if (pRes->block_begin <= target->block_begin &&
            pRes->block_end >= target->block_end) {
            if (target->res_type & ResOverlap) {
                /* Nullify range but keep its ResOverlap bit on */
                target->block_end = target->block_begin - 1;
                return;
            }
            continue;
          }
          /*
           * In cases where the target and pRes have the same starting
           * address, reduce the size of the target (given it's an estimate).
           */
          if (pRes->block_begin == target->block_begin) {
            if (target->res_type & ResOverlap)
                target->block_end = target->block_begin - 1;
            else
                target->block_end = pRes->block_end;
          }
          /* Otherwise, trim target to remove the overlap */
          else if (pRes->block_begin <= target->block_end) {
            target->block_end = pRes->block_begin - 1;
          } else if (!pow2Alignment &&
                   pRes->block_end >= target->block_begin) {
            target->block_begin = pRes->block_end + 1;
          }
          if (pow2Alignment) {
            /*
             * Align to a power of two.  This requires finding the
             * largest power of two that is smaller than the adjusted
             * size.
             */
            size = target->block_end - target->block_begin + 1;
            newsize = 1UL << (sizeof(memType) * 8 - 1);
            while (!(newsize & size))
                newsize >>= 1;
            target->block_end = target->block_begin + newsize - 1;
          } else if (target->block_end > MEM_ALIGN) {
            /* Align the end to MEM_ALIGN */
            if ((adjust = (target->block_end + 1) % MEM_ALIGN))
                target->block_end -= adjust;
          }
      }
    }
}
#else

void
RemoveOverlaps(resPtr target, resPtr list, Bool pow2Alignment, Bool useEstimated)
{
    resPtr pRes;
    memType size, newsize, adjust;

    if (!target)
      return;
    
    if (!(target->res_type & ResEstimated)   /* Don't touch sure resources */
      && !(target->res_type & ResOverlap)) /* Unless they may overlap    */
      return;

    for (pRes = list; pRes; pRes = pRes->next) {
      if (pRes == target
          || ((pRes->res_type & ResTypeMask) !=
            (target->res_type & ResTypeMask))
          || pRes->block_begin > target->block_end
          || pRes->block_end < target->block_begin)
          continue;

      if (pRes->block_begin <= target->block_begin) {
          /* Possibly ignore estimated resources */
          if (!useEstimated && (pRes->res_type & ResEstimated))
            continue;
          
          /* Special cases */
          if (pRes->block_end >= target->block_end) {
            /*
             * If pRes fully contains target, don't do anything
             * unless target can overlap.
             */
            if (target->res_type & ResOverlap) {
                /* Nullify range but keep its ResOverlap bit on */
                target->block_end = target->block_begin - 1;
                return;
            } else
                continue;
          } else {
#if 0 /* Don't trim start address - we trust what we got */
            /*
             * If !pow2Alignment trim start address: !pow2Alingment
             * is only set when estimated OS addresses are handled.
             * In cases where the target and pRes have the same
             * starting address, reduce the size of the target
             * (given it's an estimate).
             */
            if (!pow2Alignment)
                target->block_begin = pRes->block_end + 1;
            else 
#endif
            if (pRes->block_begin == target->block_begin)
                target->block_end = pRes->block_end;
            else
                continue;
          }
      } else {
          /* Trim target to remove the overlap */
            target->block_end = pRes->block_begin - 1;
      }
      if (pow2Alignment) {
          /*
           * Align to a power of two.  This requires finding the
           * largest power of two that is smaller than the adjusted
           * size.
           */
          size = target->block_end - target->block_begin + 1;
          newsize = 1UL << (sizeof(memType) * 8 - 1);
          while (!(newsize & size))
            newsize >>= 1;
          target->block_end = target->block_begin + newsize - 1;
      } else if (target->block_end > MEM_ALIGN) {
          /* Align the end to MEM_ALIGN */
          if ((adjust = (target->block_end + 1) % MEM_ALIGN))
            target->block_end -= adjust;
      }
    }
}

#endif

/*
 * Resource request code
 */

#define ALIGN(x,a) ((x) + a) &~(a)

resRange 
xf86GetBlock(unsigned long type, memType size,
       memType window_start, memType window_end,
       memType align_mask, resPtr avoid)
{
    memType min, max, tmp;
    resRange r = {ResEnd,0,0};
    resPtr res_range = ResRange;
    
    if (!size) return r;
    if (window_end < window_start || (window_end - window_start) < (size - 1)) {
      ErrorF("Requesting insufficient memory window!:"
             " start: 0x%lx end: 0x%lx size 0x%lx\n",
             window_start,window_end,size);
      return r;
    }
    type = (type & ~(ResExtMask | ResBios | ResEstimated)) | ResBlock;
    
    while (res_range) {
      if ((type & ResTypeMask) == (res_range->res_type & ResTypeMask)) {
          if (res_range->block_begin > window_start)
            min = res_range->block_begin;
          else
            min = window_start;
          if (res_range->block_end < window_end)
            max = res_range->block_end;
          else
            max = window_end;
          min = ALIGN(min,align_mask);
          /* do not produce an overflow! */
          while (min < max && (max - min) >= (size - 1)) {
            RANGE(r,min,min + size - 1,type);
            tmp = ChkConflict(&r,Acc,SETUP);
            if (!tmp) {
                tmp = ChkConflict(&r,avoid,SETUP);
                if (!tmp) {
                  return r;
                } 
            }
            min = ALIGN(tmp,align_mask);
          }
      }
      res_range = res_range->next;
    }
    RANGE(r,0,0,ResEnd);
    return r;
}

#define mt_max ~(memType)0
#define length sizeof(memType) * 8
/*
 * make_base() -- assign the lowest bits to the bits set in mask.
 *                example: mask 011010 val 0000110 -> 011000 
 */
static memType
make_base(memType val, memType mask)
{
    int i,j = 0;
    memType ret = 0
      ;
    for (i = 0;i<length;i++) {
      if ((1 << i) & mask) {
          ret |= (((val >> j) & 1) << i);
          j++;
      }
    }
    return ret;
}

/*
 * make_base() -- assign the bits set in mask to the lowest bits.
 *                example: mask 011010 , val 010010 -> 000011
 */
static memType
unmake_base(memType val, memType mask)
{
    int i,j = 0;
    memType ret = 0;
    
    for (i = 0;i<length;i++) {
      if ((1 << i) & mask) {
          ret |= (((val >> i) & 1) << j);
          j++;
      }
    }
    return ret;
}

static memType
fix_counter(memType val, memType old_mask, memType mask)
{
    mask = old_mask & mask;
    
    val = make_base(val,old_mask);
    return unmake_base(val,mask);
}

resRange
xf86GetSparse(unsigned long type,  memType fixed_bits,
        memType decode_mask, memType address_mask, resPtr avoid)
{
    resRange r = {ResEnd,0,0};
    memType new_mask;
    memType mask1;
    memType base;
    memType counter = 0;
    memType counter1;
    memType max_counter = ~(memType)0;
    memType max_counter1;
    memType conflict = 0;
    
    /* for sanity */
    type = (type & ~(ResExtMask | ResBios | ResEstimated)) | ResSparse;

    /*
     * a sparse address consists of 3 parts:
     * fixed_bits:   F bits which hard decoded by the hardware
     * decode_bits:  D bits which are used to decode address
     *                 but which may be set by software
     * address_bits: A bits which are used to address the
     *                 sparse range.
     * the decode_mask marks all decode bits while the address_mask
     * masks out all address_bits:
     *                F D A
     * decode_mask:   0 1 0
     * address_mask:  1 1 0
     */
    decode_mask &= address_mask;
    new_mask = decode_mask;

    /*
     * We start by setting the decode_mask bits to different values
     * when a conflict is found the address_mask of the conflicting
     * resource is returned. We remove those bits from decode_mask
     * that are also set in the returned address_mask as they always
     * conflict with resources which use them as address masks.
     * The resoulting mask is stored in new_mask.
     * We continue until no conflict is found or until we have
     * tried all possible settings of new_mask.
     */
    while (1) {
      base = make_base(counter,new_mask) | fixed_bits;
      RANGE(r,base,address_mask,type);
      conflict = ChkConflict(&r,Acc,SETUP);
      if (!conflict) {
          conflict = ChkConflict(&r,avoid,SETUP);
          if (!conflict) {
            return r;
          }
      }
      counter = fix_counter(counter,new_mask,conflict);
      max_counter = fix_counter(max_counter,new_mask,conflict);
      new_mask &= conflict;
      counter ++;
      if (counter > max_counter) break;
    }
    if (!new_mask && (new_mask == decode_mask)) {
      RANGE(r,0,0,ResEnd);
      return r;
    }
    /*
     * if we haven't been successful we also try to modify those
     * bits in decode_mask that are not at the same time set in
     * new mask. These bits overlap with address_bits of some
     * resources. If a conflict with a resource of this kind is
     * found (ie. returned_mask & mask1 != mask1) with
     * mask1 = decode_mask & ~new_mask we cannot
     * use our choice of bits in the new_mask part. We try
     * another choice.
     */
    max_counter = fix_counter(mt_max,mt_max,new_mask);
    mask1 = decode_mask & ~new_mask;
    max_counter1 = fix_counter(mt_max,mt_max,mask1);
    counter = 0;
    
    while (1) {
      counter1 = 0;
      while (1) {
          base = make_base(counter1,mask1);
          RANGE(r,base,address_mask,type);
          conflict = ChkConflict(&r,Acc,SETUP);
          if (!conflict) {
            conflict = ChkConflict(&r,avoid,SETUP);
            if (!conflict) {
                return r;
            }
          }
          counter1 ++;
          if ((mask1 & conflict) != mask1 || counter1 > max_counter1)
            break;
      }
      counter ++;
      if (counter > max_counter) break;
    }
    RANGE(r,0,0,ResEnd);
    return r;
}

#undef length
#undef mt_max

/*
 * Resource registrarion
 */

static resList
xf86GetResourcesImplicitly(int entityIndex)
{
    if (entityIndex >= xf86NumEntities) return NULL;
    
    switch (xf86Entities[entityIndex]->bus.type) {
    case BUS_ISA:
    case BUS_NONE:
    case BUS_SBUS:
      return NULL;
    case BUS_PCI:
      return GetImplicitPciResources(entityIndex);
    case BUS_last:
      return NULL;
    }
    return NULL;
}

static void
convertRange2Host(int entityIndex, resRange *pRange)
{
    if (pRange->type & ResBus) {
      switch (xf86Entities[entityIndex]->busType) {
      case BUS_PCI:
          pciConvertRange2Host(entityIndex,pRange);
          break;
      case BUS_ISA:
          isaConvertRange2Host(pRange);
          break;
      default:
          break;
      }

      pRange->type &= ~ResBus;
    }
}

/*
 * xf86RegisterResources() -- attempts to register listed resources.
 * If list is NULL it tries to obtain resources implicitly. Function
 * returns a resPtr listing all resources not successfully registered.
 */

resPtr
xf86RegisterResources(int entityIndex, resList list, unsigned long access)
{
    resPtr res = NULL;
    resRange range;
    resList list_f = NULL;

    if (!list) {
      list = xf86GetResourcesImplicitly(entityIndex);
      /* these resources have to be in host address space already */
      if (!list) return NULL;
      list_f = list;
    }
    
    while(list->type != ResEnd) {
      range = *list;

      convertRange2Host(entityIndex,&range);

      if ((access != ResNone) && (access & ResAccMask)) {
          range.type = (range.type & ~ResAccMask) | (access & ResAccMask);
      }
      range.type &= ~ResEstimated;  /* Not allowed for drivers */
#if !((defined(__alpha__) || (defined(__ia64__))) && defined(linux))
      /* On Alpha Linux, do not check for conflicts, trust the kernel. */
      if (checkConflict(&range, Acc, entityIndex, SETUP,TRUE)) 
          res = xf86AddResToList(res,&range,entityIndex);
      else
#endif
      {
          Acc = xf86AddResToList(Acc,&range,entityIndex);
      }
      list++;
    }
    if (list_f)
      xfree(list_f);

#ifdef DEBUG
    xf86MsgVerb(X_INFO, 3,"Resources after driver initialization\n");
    xf86PrintResList(3, Acc);
    if (res) xf86MsgVerb(X_INFO, 3,
                   "Failed Resources after driver initialization "
                   "for Entity: %i\n",entityIndex);
    xf86PrintResList(3, res);
#endif
    return res;
    
}

static void
busTypeSpecific(EntityPtr pEnt, xf86State state, xf86AccessPtr *acc_mem,
            xf86AccessPtr *acc_io, xf86AccessPtr *acc_mem_io)
{
    pciAccPtr *ppaccp;
    
    switch (pEnt->bus.type) {
    case BUS_ISA:
    case BUS_SBUS:
          *acc_mem = *acc_io = *acc_mem_io = &AccessNULL;
          break;
      break;
    case BUS_PCI:
      ppaccp = xf86PciAccInfo;
      while (*ppaccp) {
          if ((*ppaccp)->busnum == pEnt->pciBusId.bus
            && (*ppaccp)->devnum == pEnt->pciBusId.device
            && (*ppaccp)->funcnum == pEnt->pciBusId.func) {
            *acc_io = &(*ppaccp)->ioAccess;
            *acc_mem = &(*ppaccp)->memAccess;
            *acc_mem_io = &(*ppaccp)->io_memAccess;
            break;
          }
          ppaccp++;
      }
      break;
    default:
      *acc_mem = *acc_io = *acc_mem_io = NULL;
      break;
    }
    return;
}

static void
setAccess(EntityPtr pEnt, xf86State state)
{

    xf86AccessPtr acc_mem, acc_io, acc_mem_io;
    xf86AccessPtr org_mem = NULL, org_io = NULL, org_mem_io = NULL;
    int prop;
    
    busTypeSpecific(pEnt,state,&acc_mem,&acc_io,&acc_mem_io);

    /* The replacement function needs to handle _all_ shared resources */
    /* unless they are handeled locally and disabled otherwise         */
    if (pEnt->rac) {
      if (pEnt->rac->io_new) {
          org_io = acc_io;
          acc_io = pEnt->rac->io_new;
      }
      if (pEnt->rac->mem_new) {
          org_mem = acc_mem;
          acc_mem = pEnt->rac->mem_new;
      }     
      if (pEnt->rac->io_mem_new) {
          org_mem_io = acc_mem_io;
          acc_mem_io = pEnt->rac->io_mem_new;
      }   
    }
    
    if (state == OPERATING) {
      prop = pEnt->entityProp;
      switch(pEnt->entityProp & NEED_SHARED) {
      case NEED_SHARED:
          pEnt->access->rt = MEM_IO;
          break;
      case NEED_IO_SHARED:
          pEnt->access->rt = IO;
          break;
      case NEED_MEM_SHARED:
          pEnt->access->rt = MEM;
          break;
      default:
          pEnt->access->rt = NONE;
      }
    } else {
      prop = NEED_SHARED | NEED_MEM | NEED_IO;
      pEnt->access->rt = MEM_IO;
    }
    
    switch(pEnt->access->rt) {
    case IO:
      pEnt->access->pAccess = acc_io;
      break;
    case MEM:
      pEnt->access->pAccess = acc_mem;
      break;
    case MEM_IO:
      pEnt->access->pAccess = acc_mem_io;
      break;
    default: /* no conflicts at all */
      pEnt->access->pAccess =  NULL; /* remove from RAC */
      break;
    }

    if (org_io) {
      /* does the driver want the old access func? */
      if (pEnt->rac->old) {
          /* give it to the driver, leave state disabled */
          pEnt->rac->old->io = org_io;
      } else if (org_io->AccessEnable) {
          /* driver doesn't want it - enable generic access */
          org_io->AccessEnable(org_io->arg);
      }
    }

    if (org_mem_io) {
      /* does the driver want the old access func? */
      if (pEnt->rac->old) {
          /* give it to the driver, leave state disabled */
          pEnt->rac->old->io_mem = org_mem_io;
      } else if (org_mem_io->AccessEnable) {
          /* driver doesn't want it - enable generic access */
          org_mem_io->AccessEnable(org_mem_io->arg);
      }
    }

    if (org_mem) {
      /* does the driver want the old access func? */
      if (pEnt->rac->old) {
          /* give it to the driver, leave state disabled */
          pEnt->rac->old->mem = org_mem;
      } else if (org_mem->AccessEnable) {
          /* driver doesn't want it - enable generic access */
          org_mem->AccessEnable(org_mem->arg);
      }
    }

    if (!(prop & NEED_MEM_SHARED)){
      if (prop & NEED_MEM) {
          if (acc_mem && acc_mem->AccessEnable)
            acc_mem->AccessEnable(acc_mem->arg);
      } else {
          if (acc_mem && acc_mem->AccessDisable)
            acc_mem->AccessDisable(acc_mem->arg);
      }
    }

    if (!(prop & NEED_IO_SHARED)) {
      if (prop & NEED_IO) {
          if (acc_io && acc_io->AccessEnable)
          acc_io->AccessEnable(acc_io->arg);
      } else {
          if (acc_io && acc_io->AccessDisable)
            acc_io->AccessDisable(acc_io->arg);
      }
    }

    /* disable shared resources */
    if (pEnt->access->pAccess 
      && pEnt->access->pAccess->AccessDisable)
      pEnt->access->pAccess->AccessDisable(pEnt->access->pAccess->arg);

    /*
     * If device is not under access control it is enabled.
     * If it needs bus routing do it here as it isn't bus
     * type specific. Any conflicts should be checked at this
     * stage
     */
    if (!pEnt->access->pAccess
      && (pEnt->entityProp & (state == SETUP ? NEED_VGA_ROUTED_SETUP :
                        NEED_VGA_ROUTED)))
      ((BusAccPtr)pEnt->busAcc)->set_f(pEnt->busAcc);
}

    
/*
 * xf86EnterServerState() -- set state the server is in.
 */

typedef enum { TRI_UNSET, TRI_TRUE, TRI_FALSE } TriState;

static void
SetSIGIOForState(xf86State state)
{
    static int sigio_state;
    static TriState sigio_blocked = TRI_UNSET;

    if ((state == SETUP) && (sigio_blocked != TRI_TRUE)) {
        sigio_state = xf86BlockSIGIO();
      sigio_blocked = TRI_TRUE;
    } else if ((state == OPERATING) && (sigio_blocked != TRI_UNSET)) {
        xf86UnblockSIGIO(sigio_state);
        sigio_blocked = TRI_FALSE;
    }
}

void
xf86EnterServerState(xf86State state)
{
    EntityPtr pEnt;
    ScrnInfoPtr pScrn;
    int i,j;
    int needVGA = 0;
    resType rt;
    /* 
     * This is a good place to block SIGIO during SETUP state.
     * SIGIO should be blocked in SETUP state otherwise (u)sleep()
     * might get interrupted early. 
     * We take care not to call xf86BlockSIGIO() twice. 
     */
    SetSIGIOForState(state);
#ifdef DEBUG
    if (state == SETUP)
      ErrorF("Entering SETUP state\n");
    else
      ErrorF("Entering OPERATING state\n");
#endif

    /* When servicing a dumb framebuffer we don't need to do anything */
    if (doFramebufferMode) return;

    for (i=0; i<xf86NumScreens; i++) {
      pScrn = xf86Screens[i];
      j = pScrn->entityList[pScrn->numEntities - 1];
      pScrn->access = xf86Entities[j]->access;
      
      for (j = 0; j<xf86Screens[i]->numEntities; j++) {
          pEnt = xf86Entities[xf86Screens[i]->entityList[j]];
          if (pEnt->entityProp & (state == SETUP ? NEED_VGA_ROUTED_SETUP
                            : NEED_VGA_ROUTED)) 
            xf86Screens[i]->busAccess = pEnt->busAcc;
      }
      if (xf86Screens[i]->busAccess)
          needVGA ++;
    }
    
    /*
     * if we just have one screen we don't have RAC.
     * Therefore just enable the screen and return.
     */
    if (!needRAC) {
      xf86EnableAccess(xf86Screens[0]);
      notifyStateChange(NOTIFY_ENABLE);
      return;
    }
    
    if (state == SETUP)
      notifyStateChange(NOTIFY_SETUP_TRANSITION);
    else
      notifyStateChange(NOTIFY_OPERATING_TRANSITION);
    
    clearAccess();
    for (i=0; i<xf86NumScreens;i++) {

      rt = NONE;
      
      for (j = 0; j<xf86Screens[i]->numEntities; j++) {
          pEnt = xf86Entities[xf86Screens[i]->entityList[j]];
          setAccess(pEnt,state);

          if (pEnt->access->rt != NONE) {
            if (rt != NONE && rt != pEnt->access->rt)
                rt = MEM_IO;
            else
                rt = pEnt->access->rt;
          }
      }
      xf86Screens[i]->resourceType = rt;
      if (rt == NONE) {
          xf86Screens[i]->access = NULL;
          if (needVGA < 2)
            xf86Screens[i]->busAccess = NULL;
      }
      
#ifdef DEBUG
      if (xf86Screens[i]->busAccess)
          ErrorF("Screen %i setting vga route\n",i);
#endif
      switch (rt) {
      case MEM_IO:
          xf86MsgVerb(X_INFO, 3, "Screen %i shares mem & io resources\n",i);
          break;
      case IO:
          xf86MsgVerb(X_INFO, 3, "Screen %i shares io resources\n",i);
          break;
      case MEM:
          xf86MsgVerb(X_INFO, 3, "Screen %i shares mem resources\n",i);
          break;
      default:
          xf86MsgVerb(X_INFO, 3, "Entity %i shares no resources\n",i);
          break;
      }
    }
    if (state == SETUP)
      notifyStateChange(NOTIFY_SETUP);
    else
      notifyStateChange(NOTIFY_OPERATING);
}

/*
 * xf86SetOperatingState() -- Set ResOperMask for resources listed.
 */
resPtr
xf86SetOperatingState(resList list, int entityIndex, int mask)
{
    resPtr acc;
    resPtr r_fail = NULL;
    resRange range;
    
    while (list->type != ResEnd) {
      range = *list;
      convertRange2Host(entityIndex,&range);

      acc = Acc;
      while (acc) {
#define MASK (ResTypeMask | ResExtMask)
          if ((acc->entityIndex == entityIndex) 
            && (acc->val.a == range.a) && (acc->val.b == range.b)
            && ((acc->val.type & MASK) == (range.type & MASK)))
            break;
#undef MASK
          acc = acc->next;
      }
      if (acc)
          acc->val.type = (acc->val.type & ~ResOprMask)
            | (mask & ResOprMask);
      else {
          r_fail = xf86AddResToList(r_fail,&range,entityIndex);
      }
      list ++;
    }
    
     return r_fail;
}

/*
 * Stage specific code
 */
 /*
  * ProcessEstimatedConflicts() -- Do something about driver-registered
  * resources that conflict with estimated resources.  For now, just register
  * them with a logged warning.
  */
#ifdef REDUCER
static void
ProcessEstimatedConflicts(void)
{
    if (!AccReducers)
      return;

    /* Temporary */
    xf86MsgVerb(X_WARNING, 3,
            "Registering the following despite conflicts with estimated"
            " resources:\n");
    xf86PrintResList(3, AccReducers);
    Acc = xf86JoinResLists(Acc, AccReducers);
    AccReducers = NULL;
}
#endif

/*
 * xf86ClaimFixedResources() -- This function gets called from the
 * driver Probe() function to claim fixed resources.
 */
static void
resError(resList list)
{
    FatalError("A driver tried to allocate the %s %sresource at \n"
             "0x%lx:0x%lx which conflicted with another resource. Send the\n"
             "output of the server to %s. Please \n"
             "specify your computer hardware as closely as possible.\n",
             ResIsBlock(list)?"Block":"Sparse",
             ResIsMem(list)?"Mem":"Io",
             ResIsBlock(list)?list->rBegin:list->rBase,
             ResIsBlock(list)?list->rEnd:list->rMask,BUILDERADDR);
}

/*
 * xf86ClaimFixedResources() is used to allocate non-relocatable resources.
 * This should only be done by a driver's Probe() function.
 */
void
xf86ClaimFixedResources(resList list, int entityIndex)
{
    resPtr ptr = NULL;
    resRange range;     

    if (!list) return;
    
    while (list->type !=ResEnd) {
      range = *list;

      convertRange2Host(entityIndex,&range);

      range.type &= ~ResEstimated;  /* Not allowed for drivers */
      switch (range.type & ResAccMask) {
      case ResExclusive:
          if (!xf86ChkConflict(&range, entityIndex)) {
            Acc = xf86AddResToList(Acc, &range, entityIndex);
#ifdef REDUCER
          } else {
            range.type |= ResEstimated;
            if (!xf86ChkConflict(&range, entityIndex) &&
                !checkConflict(&range, AccReducers, entityIndex,
                           SETUP, FALSE)) {
                range.type &= ~(ResEstimated | ResBios);
                AccReducers =
                  xf86AddResToList(AccReducers, &range, entityIndex);
#endif
            } else resError(&range); /* no return */
#ifdef REDUCER
          }
#endif
          break;
      case ResShared:
          /* at this stage the resources are just added to the
           * EntityRec. After the Probe() phase this list is checked by
           * xf86PostProbe(). All resources which don't
           * conflict with already allocated ones are allocated
           * and removed from the EntityRec. Thus a non-empty resource
           * list in the EntityRec indicates resource conflicts the
           * driver should either handle or fail.
           */
          if (xf86Entities[entityIndex]->active)
            ptr = xf86AddResToList(ptr,&range,entityIndex);
          break;
      }
      list++;
    }
    xf86Entities[entityIndex]->resources =
      xf86JoinResLists(xf86Entities[entityIndex]->resources,ptr);
    xf86MsgVerb(X_INFO, 3,
      "resource ranges after xf86ClaimFixedResources() call:\n");
    xf86PrintResList(3,Acc);
#ifdef REDUCER
    ProcessEstimatedConflicts();
#endif
#ifdef DEBUG
    if (ptr) {
      xf86MsgVerb(X_INFO, 3, "to be registered later:\n");
      xf86PrintResList(3,ptr);
    }
#endif
}

static void
checkRoutingForScreens(xf86State state)
{
    resList list = resVgaUnusedExclusive;
    resPtr pResVGA = NULL;
    resPtr pResVGAHost;
    pointer vga = NULL;
    int i,j;
    int entityIndex;
    EntityPtr pEnt;
    resPtr pAcc;
    resRange range;

    /*
     * find devices that need VGA routed: ie the ones that have
     * registered VGA resources without ResUnused. ResUnused
     * doesn't conflict with itself therefore use it here.
     */
    while (list->type != ResEnd) { /* create resPtr from resList for VGA */
      range = *list;
      range.type &= ~(ResBios | ResEstimated); /* if set remove them */
      pResVGA = xf86AddResToList(pResVGA, &range, -1);
      list++;
    }

    for (i = 0; i < xf86NumScreens; i++) {
      for (j = 0; j < xf86Screens[i]->numEntities; j++) {
          entityIndex = xf86Screens[i]->entityList[j];
          pEnt = xf86Entities[entityIndex];
          pAcc = Acc;
          vga = NULL;
          pResVGAHost = xf86DupResList(pResVGA);
          xf86ConvertListToHost(entityIndex,pResVGAHost);
          while (pAcc) {
            if (pAcc->entityIndex == entityIndex)
                if (checkConflict(&pAcc->val, pResVGAHost,
                              entityIndex, state, FALSE)) {
                  if (vga && vga != pEnt->busAcc) {
                      xf86Msg(X_ERROR, "Screen %i needs vga routed to"
                            "different buses - deleting\n",i);
                      xf86DeleteScreen(i--,0);
                  }
#ifdef DEBUG
                  {
                      resPtr rlist = xf86AddResToList(NULL,&pAcc->val,
                                              pAcc->entityIndex);
                      xf86MsgVerb(X_INFO,3,"====== %s\n",
                              state == OPERATING ? "OPERATING"
                              : "SETUP");
                      xf86MsgVerb(X_INFO,3,"%s Resource:\n",
                              (pAcc->val.type) & ResMem ? "Mem" :"Io");
                      xf86PrintResList(3,rlist);
                      xf86FreeResList(rlist);
                      xf86MsgVerb(X_INFO,3,"Conflicts with:\n");
                      xf86PrintResList(3,pResVGAHost);
                      xf86MsgVerb(X_INFO,3,"=====\n");
                  }
#endif
                  vga = pEnt->busAcc;
                  pEnt->entityProp |= (state == SETUP
                      ? NEED_VGA_ROUTED_SETUP : NEED_VGA_ROUTED);
                  if (state == OPERATING) {
                      if (pAcc->val.type & ResMem)
                        pEnt->entityProp |= NEED_VGA_MEM;
                      else
                        pEnt->entityProp |= NEED_VGA_IO;
                  }
                }
            pAcc = pAcc->next;
          }
          if (vga)
            xf86MsgVerb(X_INFO, 3,"Setting vga for screen %i.\n",i);
          xf86FreeResList(pResVGAHost);
      }
    }
    xf86FreeResList(pResVGA);
}

/*
 * xf86PostProbe() -- Allocate all non conflicting resources
 * This function gets called by xf86Init().
 */
void
xf86PostProbe(void)
{
    memType val;
    int i,j;
    resPtr resp, acc, tmp, resp_x, *pprev_next;

    if (fbSlotClaimed) {
        if (pciSlotClaimed || isaSlotClaimed 
#if defined(__sparc__) && !defined(__OpenBSD__)
          || sbusSlotClaimed
#endif
          ) { 
          FatalError("Cannot run in framebuffer mode. Please specify busIDs "
                   "       for all framebuffer devices\n");
          return;
      } else  {
          xf86Msg(X_INFO,"Running in FRAMEBUFFER Mode\n");
          xf86AccessRestoreState();
          notifyStateChange(NOTIFY_ENABLE);
          doFramebufferMode = TRUE;

          return;
      }
    }
    /* don't compare against ResInit - remove it from clone.*/
    acc = tmp = xf86DupResList(Acc);
    pprev_next = &acc;
    while (tmp) {
      if (tmp->res_type & ResInit) {
          (*pprev_next) = tmp->next;
          xfree(tmp);
      } else 
          pprev_next = &(tmp->next);
      tmp = (*pprev_next);
    }

    for (i=0; i<xf86NumEntities; i++) {
      resp = xf86Entities[i]->resources;
      xf86Entities[i]->resources = NULL;
      resp_x = NULL;
      while (resp) {
          if (! (val = checkConflict(&resp->val,acc,i,SETUP,FALSE)))  {
              resp->res_type &= ~(ResBios); /* just used for chkConflict() */
            tmp = resp_x;
            resp_x = resp;
            resp = resp->next;
            resp_x->next = tmp;
#ifdef REDUCER
          } else {
            resp->res_type |= ResEstimated;
            if (!checkConflict(&resp->val, acc, i, SETUP, FALSE)) {
                resp->res_type &= ~(ResEstimated | ResBios);
                tmp = AccReducers;
                AccReducers = resp;
                resp = resp->next;
                AccReducers->next = tmp;
#endif
            } else {
                xf86MsgVerb(X_INFO, 3, "Found conflict at: 0x%lx\n",val);
                resp->res_type &= ~ResEstimated;
                tmp = xf86Entities[i]->resources;
                xf86Entities[i]->resources = resp;
                resp = resp->next;
                xf86Entities[i]->resources->next = tmp;
            }
#ifdef REDUCER
          }
#endif
      }
      xf86JoinResLists(Acc,resp_x);
#ifdef REDUCER
      ProcessEstimatedConflicts();
#endif
    }
    xf86FreeResList(acc);
#if !(defined(__alpha__) && defined(linux)) && \
    !(defined(__ia64__) && defined(linux)) && \
    !(defined(__sparc64__) && defined(__OpenBSD__))
    /* 
     * No need to validate on Alpha Linux or OpenBSD/sparc64, 
     * trust the kernel.
     */
    ValidatePci();
#endif
    
    xf86MsgVerb(X_INFO, 3, "resource ranges after probing:\n");
    xf86PrintResList(3, Acc);
    checkRoutingForScreens(SETUP);

    for (i = 0; i < xf86NumScreens; i++) {
      for (j = 0; j<xf86Screens[i]->numEntities; j++) {
          EntityPtr pEnt = xf86Entities[xf86Screens[i]->entityList[j]];
          if ((pEnt->entityProp & NEED_VGA_ROUTED_SETUP) &&
            ((xf86Screens[i]->busAccess = pEnt->busAcc)))
            break;
      }
    }
}

static void
checkRequiredResources(int entityIndex)
{
    resRange range;
    resPtr pAcc = Acc;
    const EntityPtr pEnt = xf86Entities[entityIndex];
    while (pAcc) {
      if (pAcc->entityIndex == entityIndex) {
          range = pAcc->val;
          /*  ResAny to find conflicts with anything. */
          range.type = (range.type & ~ResAccMask) | ResAny | ResBios;
          if (checkConflict(&range,Acc,entityIndex,OPERATING,FALSE))
            switch (pAcc->res_type & ResPhysMask) {
            case ResMem:
                pEnt->entityProp |= NEED_MEM_SHARED;
                break;
            case ResIo:
                pEnt->entityProp |= NEED_IO_SHARED;
                break;
            }
          if (!(pAcc->res_type & ResOprMask)) {
            switch (pAcc->res_type & ResPhysMask) {
            case ResMem:
                pEnt->entityProp |= NEED_MEM;
                break;
            case ResIo:
                pEnt->entityProp |= NEED_IO;
                break;
            }
          }
      }
      pAcc = pAcc->next;
    }
    
    /* check if we can separately enable mem/io resources */
    /* XXX we still need to find out how to set this yet  */
    if ( ((pEnt->entityProp & NO_SEPARATE_MEM_FROM_IO)
        && (pEnt->entityProp & NEED_MEM_SHARED))
       || ((pEnt->entityProp & NO_SEPARATE_IO_FROM_MEM)
           && (pEnt->entityProp & NEED_IO_SHARED)) )
      pEnt->entityProp |= NEED_SHARED;
    /*
     * After we have checked all resources of an entity agains any
     * other resource we know if the entity need this resource type
     * (ie. mem/io) at all. if not we can disable this type completely,
     * so no need to share it either. 
     */
    if ((pEnt->entityProp & NEED_MEM_SHARED)
      && (!(pEnt->entityProp & NEED_MEM))
      && (!(pEnt->entityProp & NO_SEPARATE_MEM_FROM_IO)))
      pEnt->entityProp &= ~(unsigned long)NEED_MEM_SHARED;

    if ((pEnt->entityProp & NEED_IO_SHARED)
      && (!(pEnt->entityProp & NEED_IO))
      && (!(pEnt->entityProp & NO_SEPARATE_IO_FROM_MEM)))
      pEnt->entityProp &= ~(unsigned long)NEED_IO_SHARED;
}

void
xf86PostPreInit()
{
  if (doFramebufferMode) return;

    if (xf86NumScreens > 1)
      needRAC = TRUE;

#ifdef XFree86LOADER
    xf86MsgVerb(X_INFO, 3, "do I need RAC?");
    
    if (needRAC) {
      xf86ErrorFVerb(3, "  Yes, I do.\n");
      
      if (!xf86LoadOneModule("rac",NULL))
          FatalError("Cannot load RAC module\n");
    } else
      xf86ErrorFVerb(3, "  No, I don't.\n");
#endif    
      
    xf86MsgVerb(X_INFO, 3, "resource ranges after preInit:\n");
    xf86PrintResList(3, Acc);
}

void
xf86PostScreenInit(void)
{
    int i,j;
    ScreenPtr pScreen;
    unsigned int flags;
    int nummem = 0, numio = 0;
#ifdef XFree86LOADER
      pointer xf86RACInit = NULL;
#endif

      if (doFramebufferMode) {
          SetSIGIOForState(OPERATING);
          return;
      }

#ifdef XFree86LOADER
      if (needRAC) {
          xf86RACInit = LoaderSymbol("xf86RACInit");
          if (!xf86RACInit)
            FatalError("Cannot resolve symbol \"xf86RACInit\"\n");
      }
#endif
#ifdef DEBUG
    ErrorF("PostScreenInit  generation: %i\n",serverGeneration);
#endif
    if (serverGeneration == 1) {
      checkRoutingForScreens(OPERATING);
      for (i=0; i<xf86NumEntities; i++) {
          checkRequiredResources(i);
      }
      
      /*
       * after removing NEED_XXX_SHARED from entities that
       * don't need need XXX resources at all we might have
       * a single entity left that has NEED_XXX_SHARED set.
       * In this case we can delete that, too.
       */
      for (i = 0; i < xf86NumEntities; i++) {
          if (xf86Entities[i]->entityProp & NEED_MEM_SHARED)
            nummem++;
          if (xf86Entities[i]->entityProp & NEED_IO_SHARED)
            numio++;
      }
      for (i = 0; i < xf86NumEntities; i++) {
          if (nummem < 2)
            xf86Entities[i]->entityProp &= ~NEED_MEM_SHARED;
          if (numio < 2)
            xf86Entities[i]->entityProp &= ~NEED_IO_SHARED;
      }
    }
    
    if (xf86Screens && needRAC) {
      int needRACforVga = 0;

      for (i = 0; i < xf86NumScreens; i++) {
          for (j = 0; j < xf86Screens[i]->numEntities; j++) {
            if (xf86Entities[xf86Screens[i]->entityList[j]]->entityProp
                & NEED_VGA_ROUTED) {
                needRACforVga ++;
                break; /* only count each screen once */
            }
          }
      }
      
      for (i = 0; i < xf86NumScreens; i++) {
          Bool needRACforMem = FALSE, needRACforIo = FALSE;
          
          for (j = 0; j < xf86Screens[i]->numEntities; j++) {
            if (xf86Entities[xf86Screens[i]->entityList[j]]->entityProp
                & NEED_MEM_SHARED)
                needRACforMem = TRUE;
            if (xf86Entities[xf86Screens[i]->entityList[j]]->entityProp
                & NEED_IO_SHARED)
                needRACforIo = TRUE;
            /*
             * We may need RAC although we don't share any resources
             * as we need to route VGA to the correct bus. This can
             * only be done simultaniously for MEM and IO.
             */
            if (needRACforVga > 1) {
                if (xf86Entities[xf86Screens[i]->entityList[j]]->entityProp
                  & NEED_VGA_MEM)
                  needRACforMem = TRUE;
                if (xf86Entities[xf86Screens[i]->entityList[j]]->entityProp
                  & NEED_VGA_IO)
                  needRACforIo = TRUE;          
            }
          }
            
          pScreen = xf86Screens[i]->pScreen;
          flags = 0;
          if (needRACforMem) {
            flags |= xf86Screens[i]->racMemFlags;
            xf86ErrorFVerb(3, "Screen %d is using RAC for mem\n", i);
          }
          if (needRACforIo) {
            flags |= xf86Screens[i]->racIoFlags;
            xf86ErrorFVerb(3, "Screen %d is using RAC for io\n", i);
          }
          
#ifdef XFree86LOADER
            ((Bool(*)(ScreenPtr,unsigned int))xf86RACInit)
                (pScreen,flags);
#else
          xf86RACInit(pScreen,flags);
#endif
      }
    }
    
    xf86EnterServerState(OPERATING);
    
}

/*
 * Sets
 */


static resPtr
decomposeSparse(resRange range)
{
    resRange new;
    resPtr ret = NULL;
    memType val = range.rBegin;
    int i = 0;
    
    new.type = (range.type & ~ResExtMask) | ResSparse;

    while (1) {
      if (val & 0x01) {
          new.rBase = (val << i);
          new.rMask = ~((1 << i) - 1);
          ret = xf86AddResToList(ret,&new,-1);
          val ++;
      }
      i++;
      val >>= 1;
      if ((((val + 1) << i) - 1) > range.rEnd)
          break;
    }
    i--;
    val <<= 1;
    
    while (1) {
      if((((val + 1) << i) - 1)> range.rEnd) {
          if (--i < 0) break;
          val <<= 1;
      } else {
          new.rBase = (val << i);
          new.rMask = ~((1 << i) - 1);
          val++;
          ret = xf86AddResToList(ret,&new,-1);
      }
    }
    return ret;
}
    
static Bool
x_isSubsetOf(resRange range, resPtr list1, resPtr list2)
{
    resRange range1, range2;
    memType m1_A_m2;
    Bool ret;
    resPtr list;
    
    if (list1) {
      list = list1;
      if ((range.type & ResTypeMask) == (list->res_type & ResTypeMask)) {
          switch (range.type & ResExtMask) {
          case ResBlock:
            if ((list->res_type & ResExtMask) == ResBlock) {
                if (range.rBegin >= list->block_begin
                  && range.rEnd <= list->block_end)
                  return TRUE;
                else if (range.rBegin < list->block_begin
                       && range.rEnd > list->block_end) {
                  RANGE(range1, range.rBegin, list->block_begin - 1,
                        range.type);
                  RANGE(range2, list->block_end + 1, range.rEnd,
                        range.type);
                  return (x_isSubsetOf(range1,list->next,list2) &&
                        x_isSubsetOf(range2,list->next,list2));
                }
                else if (range.rBegin >= list->block_begin
                       && range.rBegin <= list->block_end) {
                  RANGE(range1, list->block_end + 1, range.rEnd,
                        range.type);
                  return (x_isSubsetOf(range1,list->next,list2));
                } else if (range.rEnd >= list->block_begin
                         && range.rEnd <= list->block_end) {
                  RANGE(range1,range.rBegin, list->block_begin - 1,
                        range.type);
                  return (x_isSubsetOf(range1,list->next,list2));
                } 
            }
            break;
          case ResSparse:
            if ((list->res_type & ResExtMask) == ResSparse) {
                memType test;
                int i;
                
                m1_A_m2 = range.rMask & list->sparse_mask;
                if ((range.rBase ^ list->sparse_base) & m1_A_m2)
                  break;
                /*
                 * We use the following system:
                 * let 0 ^= mask:1 base:0, 1 ^= mask:1 base:1,
                 * X mask:0 ; S: set TSS: test set for subset
                 * NTSS: new test set after test
                 *    S: 1   0   1   0   X   X   0   1   X
                 *  TSS: 1   0   0   1   1   0   X   X   X
                 *    T: 0   0   1   1   0   0   0   0   0
                 * NTSS: 1   0  0/X  1/X 1   0   1   0   X
                 *    R: 0   0   0   0   0   0   1   1   0
                 * If R != 0 TSS and S are disjunct
                 * If R == 0 TSS is subset of S
                 * If R != 0 NTSS contains elements from TSS
                 * which are not also members of S.
                 * If a T is set one of the correspondig bits
                 * in NTSS must be set to the specified value
                 * all other are X
                 */
                test = list->sparse_mask & ~range.rMask;
                if (test == 0)
                  return TRUE;
                for (i = 0; i < sizeof(memType); i++) {
                  if ((test >> i) & 0x1) {
                      RANGE(range1, ((range.rBase & list->sparse_base)
                          | (range.rBase & ~list->sparse_mask)
                          | ((~list->sparse_base & list->sparse_mask)
                             & ~range.rMask)) & range1.rMask,
                          ((range.rMask | list->sparse_mask) & ~test)
                          | (1 << i), range.type);
                      return (x_isSubsetOf(range1,list->next,list2));
                  }
                }
            }
            break;
          }
      }
      return (x_isSubsetOf(range,list->next,list2));
    } else if (list2) {
      resPtr tmpList = NULL;
      switch (range.type & ResExtMask) {
      case ResBlock:
          tmpList = decomposeSparse(range);
          while (tmpList) {
            if (!x_isSubsetOf(tmpList->val,list2,NULL)) {
                xf86FreeResList(tmpList);
                return FALSE;
            }
            tmpList = tmpList->next;
          }
          xf86FreeResList(tmpList);
          return TRUE;
          break;
      case ResSparse:
          while (list2) {
            tmpList = xf86JoinResLists(tmpList,decomposeSparse(list2->val));
            list2 = list2->next;
          }
          ret = x_isSubsetOf(range,tmpList,NULL);
          xf86FreeResList(tmpList);
          return ret;
          break;
      }
    } else
      return FALSE;

    return FALSE;
}

Bool
xf86IsSubsetOf(resRange range, resPtr list)
{
    resPtr dup = xf86DupResList(list);
    resPtr r_sp = NULL, r = NULL, tmp = NULL;
    Bool ret = FALSE;
    
    while (dup) {
      tmp = dup;
      dup = dup->next;
      switch (tmp->res_type & ResExtMask) {
      case ResBlock:
          tmp->next = r;
          r = tmp;
          break;
      case ResSparse:
          tmp->next = r_sp;
          r_sp = tmp;
          break;
      }
    }
    
    switch (range.type & ResExtMask) {
    case ResBlock:
      ret = x_isSubsetOf(range,r,r_sp);
      break;
    case ResSparse:
      ret = x_isSubsetOf(range,r_sp,r);
      break;
    }
    xf86FreeResList(r);
    xf86FreeResList(r_sp);
    
    return ret;
}

Bool
xf86IsListSubsetOf(resPtr list, resPtr BaseList)
{
    while (list) {
      if (! xf86IsSubsetOf(list->val,BaseList))
          return FALSE;
      list = list->next;
    }
    return TRUE;
}

resPtr
findIntersect(resRange Range, resPtr list)
{
    resRange range;
    resPtr new = NULL;
    
    while (list) {
          if ((Range.type & ResTypeMask) == (list->res_type & ResTypeMask)) {
            switch (Range.type & ResExtMask) {
            case ResBlock:
                switch (list->res_type & ResExtMask) {
                case ResBlock:
                  if (Range.rBegin >= list->block_begin)
                      range.rBegin = Range.rBegin;
                  else
                      range.rBegin = list->block_begin;
                  if (Range.rEnd <= list->block_end)
                      range.rEnd = Range.rEnd;
                  else 
                      range.rEnd = list->block_end;
                  if (range.rEnd > range.rBegin) {
                      range.type = Range.type;
                      new = xf86AddResToList(new,&range,-1);
                  }
                  break;
                case ResSparse:
                  new = xf86JoinResLists(new,xf86FindIntersectOfLists(new,decomposeSparse(list->val)));
                  break;
                }
                break;
            case ResSparse:
                switch (list->res_type & ResExtMask) {
                case ResSparse:
                  if (!((~(range.rBase ^ list->sparse_base)
                      & (range.rMask & list->sparse_mask)))) {
                      RANGE(range, (range.rBase & list->sparse_base)
                          | (~range.rMask & list->sparse_base)
                          | (~list->sparse_mask & range.rBase),
                          range.rMask | list->sparse_mask,
                          Range.type);
                      new = xf86AddResToList(new,&range,-1);
                  }
                  break;
                case ResBlock:
                  new = xf86JoinResLists(new,xf86FindIntersectOfLists(
                      decomposeSparse(range),list));
                  break;
                }
            }
          }
      list = list->next;
    }
    return new;
}
    
resPtr
xf86FindIntersectOfLists(resPtr l1, resPtr l2)
{
    resPtr ret = NULL;

    while (l1) {
      ret = xf86JoinResLists(ret,findIntersect(l1->val,l2));
      l1 = l1->next;
    }
    return ret;
}

#if 0 /* Not used */
static resPtr
xf86FindComplement(resRange Range)
{
    resRange range;
    memType tmp;
    resPtr new = NULL;
    int i;
    
    switch (Range.type & ResExtMask) {
    case ResBlock:
      if (Range.rBegin > 0) {
          RANGE(range, 0, Range.rBegin - 1, Range.type);
          new = xf86AddResToList(new,&range,-1);
      }
      if (Range.rEnd < (memType)~0) {
          RANGE(range,Range.rEnd + 1, (memType)~0, Range.type);
          new = xf86AddResToList(new,&range,-1);
      }
      break;
    case ResSparse:
      tmp = Range.rMask;
      for (i = 0; i < sizeof(memType); i++) {
          if (tmp & 0x1) {
            RANGE(range,(~Range.rMask & range.rMask),(1 << i), Range.type);
            new = xf86AddResToList(new,&range,-1);
          }
      }
      break;
    default:
      break;
    }
    return new;
}
#endif

resPtr
xf86ExtractTypeFromList(resPtr list, unsigned long type)
{
    resPtr ret = NULL;
    
    while (list) {
      if ((list->res_type & ResTypeMask) == type)
          ret = xf86AddResToList(ret,&(list->val),list->entityIndex);
      list = list->next;
    }
    return ret;
}

/*------------------------------------------------------------*/
static void CheckGenericGA(void);

/*
 * xf86FindPrimaryDevice() - Find the display device which
 * was active when the server was started.
 */
void
xf86FindPrimaryDevice()
{
    /* if no VGA device is found check for primary PCI device */
    if (primaryBus.type == BUS_NONE && xorgHWAccess)
        CheckGenericGA();
    if (primaryBus.type != BUS_NONE) {
      char *bus;
      char *loc = xnfcalloc(1,9);
      if (loc == NULL) return;

      switch (primaryBus.type) {
      case BUS_PCI:
          bus = "PCI";
          sprintf(loc," %2.2x:%2.2x:%1.1x",primaryBus.id.pci.bus,
          primaryBus.id.pci.device,primaryBus.id.pci.func);
          break;
      case BUS_ISA:
          bus = "ISA";
          loc[0] = '\0';
          break;
      case BUS_SBUS:
          bus = "SBUS";
          sprintf(loc," %2.2x",primaryBus.id.sbus.fbNum);
          break;
      default:
          bus = "";
          loc[0] = '\0';
      }
      
      xf86MsgVerb(X_INFO, 2, "Primary Device is: %s%s\n",bus,loc);
      xfree(loc);
    }
    
}

#if !defined(__sparc__) && !defined(__powerpc__) && !defined(__mips__)
#include "vgaHW.h"
#include "compiler.h"
#endif

/*
 * CheckGenericGA() - Check for presence of a VGA device.
 */
static void
CheckGenericGA()
{
/* This needs to be changed for multiple domains */
#if !defined(__sparc__) && !defined(__powerpc__) && !defined(__mips__) && !defined(__ia64__)
    IOADDRESS GenericIOBase = VGAHW_GET_IOBASE();
    CARD8 CurrentValue, TestValue;

    /* VGA CRTC registers are not used here, so don't bother unlocking them */

    /* VGA has one more read/write attribute register than EGA */
    (void) inb(GenericIOBase + VGA_IN_STAT_1_OFFSET);  /* Reset flip-flop */
    outb(VGA_ATTR_INDEX, 0x14 | 0x20);
    CurrentValue = inb(VGA_ATTR_DATA_R);
    outb(VGA_ATTR_DATA_W, CurrentValue ^ 0x0F);
    outb(VGA_ATTR_INDEX, 0x14 | 0x20);
    TestValue = inb(VGA_ATTR_DATA_R);
    outb(VGA_ATTR_DATA_W, CurrentValue);

    if ((CurrentValue ^ 0x0F) == TestValue) {
      primaryBus.type = BUS_ISA;
    }
#endif
}

Bool
xf86NoSharedResources(int screenIndex,resType res)
{
    int j;
    
    if (screenIndex > xf86NumScreens)
      return TRUE;

    for (j = 0; j < xf86Screens[screenIndex]->numEntities; j++) {
      switch (res) {
      case IO:
      if ( xf86Entities[xf86Screens[screenIndex]->entityList[j]]->entityProp
           & NEED_IO_SHARED)
        return FALSE;
      break;
      case MEM:
      if ( xf86Entities[xf86Screens[screenIndex]->entityList[j]]->entityProp
           & NEED_MEM_SHARED)
        return FALSE;
      break;
      case MEM_IO:
      if ( xf86Entities[xf86Screens[screenIndex]->entityList[j]]->entityProp
           & NEED_SHARED)
        return FALSE;
      break;
      case NONE:
      break;
      }
    }
    return TRUE;
}

void
xf86ConvertListToHost(int entityIndex, resPtr list)
{
    while (list) {
      convertRange2Host(entityIndex, &list->val);
      list = list->next;
    }
}

void
xf86RegisterStateChangeNotificationCallback(xf86StateChangeNotificationCallbackFunc func, pointer arg)
{
    StateChangeNotificationPtr ptr =
      (StateChangeNotificationPtr)xnfalloc(sizeof(StateChangeNotificationRec));

    ptr->func = func;
    ptr->arg = arg;
    ptr->next = StateChangeNotificationList;
    StateChangeNotificationList = ptr;
}

Bool
xf86DeregisterStateChangeNotificationCallback(xf86StateChangeNotificationCallbackFunc func)
{
    StateChangeNotificationPtr *ptr = &StateChangeNotificationList;
    StateChangeNotificationPtr tmp;
    
    while (*ptr) {
      if ((*ptr)->func == func) {
          tmp = (*ptr);
          (*ptr) = (*ptr)->next;
          xfree(tmp);
          return TRUE;
      }
      ptr = &((*ptr)->next);
    }
    return FALSE;
}

static void
notifyStateChange(xf86NotifyState state)
{
    StateChangeNotificationPtr ptr = StateChangeNotificationList;
    while (ptr) {
      ptr->func(state,ptr->arg);
      ptr = ptr->next;
    }
}

#ifdef async
Bool
xf86QueueAsyncEvent(void (*func)(pointer),pointer arg)
{
    AsyncQPtr new;
    
    if (!AsyncQ) return FALSE;

    new = (AsyncQPtr)xfnalloc(sizeof(AsyncQRec));
    new->func = func;
    new->arg = arg;
    (*AsyncQPtr)->next = new;
    AsyncQPtr = &new;
    return TRUE;
}
#endif

/* Multihead accel sharing accessor functions and entity Private handling */

int
xf86GetLastScrnFlag(int entityIndex)
{
    if(entityIndex < xf86NumEntities) {
        return(xf86Entities[entityIndex]->lastScrnFlag);
    } else {
        return -1;
    }
}

void
xf86SetLastScrnFlag(int entityIndex, int scrnIndex)
{
    if(entityIndex < xf86NumEntities) {
        xf86Entities[entityIndex]->lastScrnFlag = scrnIndex;
    }
}

Bool
xf86IsEntityShared(int entityIndex)
{
    if(entityIndex < xf86NumEntities) {
        if(xf86Entities[entityIndex]->entityProp & IS_SHARED_ACCEL) {
          return TRUE;
      }
    }
    return FALSE;
}

void
xf86SetEntityShared(int entityIndex)
{
    if(entityIndex < xf86NumEntities) {
        xf86Entities[entityIndex]->entityProp |= IS_SHARED_ACCEL;
    }
}

Bool
xf86IsEntitySharable(int entityIndex)
{
    if(entityIndex < xf86NumEntities) {
        if(xf86Entities[entityIndex]->entityProp & ACCEL_IS_SHARABLE) {
          return TRUE;
      }
    }
    return FALSE;
}

void
xf86SetEntitySharable(int entityIndex)
{
    if(entityIndex < xf86NumEntities) {
        xf86Entities[entityIndex]->entityProp |= ACCEL_IS_SHARABLE;
    }
}

Bool
xf86IsPrimInitDone(int entityIndex)
{
    if(entityIndex < xf86NumEntities) {
        if(xf86Entities[entityIndex]->entityProp & SA_PRIM_INIT_DONE) {
          return TRUE;
      }
    }
    return FALSE;
}

void
xf86SetPrimInitDone(int entityIndex)
{
    if(entityIndex < xf86NumEntities) {
        xf86Entities[entityIndex]->entityProp |= SA_PRIM_INIT_DONE;
    }
}

void
xf86ClearPrimInitDone(int entityIndex)
{
    if(entityIndex < xf86NumEntities) {
        xf86Entities[entityIndex]->entityProp &= ~SA_PRIM_INIT_DONE;
    }
}


/*
 * Allocate a private in the entities.
 */

int
xf86AllocateEntityPrivateIndex(void)
{
    int idx, i;
    EntityPtr pEnt;
    DevUnion *nprivs;

    idx = xf86EntityPrivateCount++;
    for (i = 0; i < xf86NumEntities; i++) {
      pEnt = xf86Entities[i];
      nprivs = xnfrealloc(pEnt->entityPrivates,
                      xf86EntityPrivateCount * sizeof(DevUnion));
      /* Zero the new private */
      bzero(&nprivs[idx], sizeof(DevUnion));
      pEnt->entityPrivates = nprivs;
    }
    return idx;
}

DevUnion *
xf86GetEntityPrivate(int entityIndex, int privIndex)
{
    if (entityIndex >= xf86NumEntities || privIndex >= xf86EntityPrivateCount)
      return NULL;

    return &(xf86Entities[entityIndex]->entityPrivates[privIndex]);
}


Generated by  Doxygen 1.6.0   Back to index