428261197a
Tested by ajacoutot@, krw@, shadchin@ and jasper@ on various configurations including multihead with both zaphod and xrandr.
672 lines
17 KiB
C
672 lines
17 KiB
C
/*
|
|
* 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).
|
|
*/
|
|
|
|
/*
|
|
* 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"
|
|
|
|
/* Bus-specific headers */
|
|
|
|
#include "xf86Bus.h"
|
|
|
|
#define XF86_OS_PRIVS
|
|
#include "xf86_OSproc.h"
|
|
#include "xf86VGAarbiter.h"
|
|
|
|
/* Entity data */
|
|
EntityPtr *xf86Entities = NULL; /* Bus slots claimed by drivers */
|
|
int xf86NumEntities = 0;
|
|
static int xf86EntityPrivateCount = 0;
|
|
|
|
BusRec primaryBus = { BUS_NONE, { 0 } };
|
|
|
|
/**
|
|
* Call the driver's correct probe function.
|
|
*
|
|
* If the driver implements the \c DriverRec::PciProbe entry-point and an
|
|
* appropriate PCI device (with matching Device section in the xorg.conf file)
|
|
* is found, it is called. If \c DriverRec::PciProbe or no devices can be
|
|
* successfully probed with it (e.g., only non-PCI devices are available),
|
|
* the driver's \c DriverRec::Probe function is called.
|
|
*
|
|
* \param drv Driver to probe
|
|
*
|
|
* \return
|
|
* If a device can be successfully probed by the driver, \c TRUE is
|
|
* returned. Otherwise, \c FALSE is returned.
|
|
*/
|
|
Bool
|
|
xf86CallDriverProbe( DriverPtr drv, Bool detect_only )
|
|
{
|
|
Bool foundScreen = FALSE;
|
|
|
|
if (drv->PciProbe != NULL) {
|
|
if (xf86DoConfigure && xf86DoConfigurePass1) {
|
|
assert(detect_only);
|
|
foundScreen = xf86PciAddMatchingDev(drv);
|
|
}
|
|
else {
|
|
assert(! detect_only);
|
|
foundScreen = xf86PciProbeDev(drv);
|
|
}
|
|
}
|
|
|
|
if (!foundScreen && (drv->Probe != NULL)) {
|
|
xf86Msg( X_WARNING, "Falling back to old probe method for %s\n",
|
|
drv->driverName);
|
|
foundScreen = (*drv->Probe)(drv, (detect_only) ? PROBE_DETECT
|
|
: PROBE_DEFAULT);
|
|
}
|
|
|
|
return foundScreen;
|
|
}
|
|
|
|
/**
|
|
* @return TRUE if all buses are configured and set up correctly and FALSE
|
|
* otherwise.
|
|
*/
|
|
Bool
|
|
xf86BusConfig(void)
|
|
{
|
|
screenLayoutPtr layout;
|
|
int i, j;
|
|
|
|
/* Enable full I/O access */
|
|
if (xorgHWAccess)
|
|
xorgHWAccess = xf86EnableIO();
|
|
|
|
/*
|
|
* Now call each of the Probe functions. Each successful probe will
|
|
* result in an extra entry added to the xf86Screens[] list for each
|
|
* instance of the hardware found.
|
|
*/
|
|
for (i = 0; i < xf86NumDrivers; i++) {
|
|
xorgHWFlags flags;
|
|
if (!xorgHWAccess) {
|
|
if (!xf86DriverList[i]->driverFunc
|
|
|| !xf86DriverList[i]->driverFunc(NULL,
|
|
GET_REQUIRED_HW_INTERFACES,
|
|
&flags)
|
|
|| NEED_IO_ENABLED(flags))
|
|
continue;
|
|
}
|
|
|
|
xf86CallDriverProbe(xf86DriverList[i], FALSE);
|
|
}
|
|
|
|
/* If nothing was detected, return now */
|
|
if (xf86NumScreens == 0) {
|
|
xf86Msg(X_ERROR, "No devices detected.\n");
|
|
return FALSE;
|
|
}
|
|
|
|
xf86VGAarbiterInit();
|
|
|
|
/*
|
|
* Match up the screens found by the probes against those specified
|
|
* in the config file. Remove the ones that won't be used. Sort
|
|
* them in the order specified.
|
|
*
|
|
* What is the best way to do this?
|
|
*
|
|
* For now, go through the screens allocated by the probes, and
|
|
* look for screen config entry which refers to the same device
|
|
* section as picked out by the probe.
|
|
*
|
|
*/
|
|
for (i = 0; i < xf86NumScreens; i++) {
|
|
for (layout = xf86ConfigLayout.screens; layout->screen != NULL;
|
|
layout++) {
|
|
Bool found = FALSE;
|
|
for (j = 0; j < xf86Screens[i]->numEntities; j++) {
|
|
|
|
GDevPtr dev = xf86GetDevFromEntity(
|
|
xf86Screens[i]->entityList[j],
|
|
xf86Screens[i]->entityInstanceList[j]);
|
|
if (dev == layout->screen->device) {
|
|
/* A match has been found */
|
|
xf86Screens[i]->confScreen = layout->screen;
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (found) break;
|
|
}
|
|
if (layout->screen == NULL) {
|
|
/* No match found */
|
|
xf86Msg(X_ERROR,
|
|
"Screen %d deleted because of no matching config section.\n", i);
|
|
xf86DeleteScreen(i--, 0);
|
|
}
|
|
}
|
|
|
|
/* If no screens left, return now. */
|
|
if (xf86NumScreens == 0) {
|
|
xf86Msg(X_ERROR,
|
|
"Device(s) detected, but none match those in the config file.\n");
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* 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(__sparc))
|
|
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) {
|
|
free(s);
|
|
return BUS_NONE;
|
|
}
|
|
if (!xf86NameCmp(p, "pci") || !xf86NameCmp(p, "agp"))
|
|
ret = BUS_PCI;
|
|
if (!xf86NameCmp(p, "sbus"))
|
|
ret = BUS_SBUS;
|
|
if (ret != BUS_NONE)
|
|
if (retID)
|
|
*retID = busID + strlen(p) + 1;
|
|
free(s);
|
|
return ret;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
Bool
|
|
xf86IsEntityPrimary(int entityIndex)
|
|
{
|
|
EntityPtr pEnt = xf86Entities[entityIndex];
|
|
|
|
if (primaryBus.type != pEnt->bus.type) return FALSE;
|
|
|
|
switch (pEnt->bus.type) {
|
|
case BUS_PCI:
|
|
return pEnt->bus.id.pci == primaryBus.id.pci;
|
|
case BUS_SBUS:
|
|
return pEnt->bus.id.sbus.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)) {
|
|
ErrorF("Requested Entity already in use!\n");
|
|
return;
|
|
}
|
|
|
|
pScrn->numEntities++;
|
|
pScrn->entityList = xnfrealloc(pScrn->entityList,
|
|
pScrn->numEntities * sizeof(int));
|
|
pScrn->entityList[pScrn->numEntities - 1] = entityIndex;
|
|
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;
|
|
|
|
for (i = 0; i < pScrn->numEntities; i++) {
|
|
if (pScrn->entityList[i] == entityIndex) {
|
|
for (i++; i < pScrn->numEntities; i++)
|
|
pScrn->entityList[i-1] = pScrn->entityList[i];
|
|
pScrn->numEntities--;
|
|
xf86Entities[entityIndex]->inUse = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* xf86ClearEntitiesForScreen() - called when a screen is deleted
|
|
* to mark it's entities unused. Called by xf86DeleteScreen().
|
|
*/
|
|
void
|
|
xf86ClearEntityListForScreen(int scrnIndex)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
|
|
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 */
|
|
}
|
|
free(pScrn->entityList);
|
|
free(pScrn->entityInstanceList);
|
|
pScrn->entityList = NULL;
|
|
pScrn->entityInstanceList = NULL;
|
|
}
|
|
|
|
/*
|
|
* 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 == -1)
|
|
return NULL;
|
|
|
|
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->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];
|
|
}
|
|
|
|
/*
|
|
* xf86AccessEnter() -- gets called to save the text mode VGA IO
|
|
* resources when reentering the server after a VT switch.
|
|
*/
|
|
void
|
|
xf86AccessEnter(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < xf86NumEntities; i++)
|
|
if (xf86Entities[i]->entityEnter)
|
|
xf86Entities[i]->entityEnter(i,xf86Entities[i]->private);
|
|
|
|
xf86EnterServerState(SETUP);
|
|
}
|
|
|
|
void
|
|
xf86AccessLeave(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < xf86NumEntities; i++)
|
|
if (xf86Entities[i]->entityLeave)
|
|
xf86Entities[i]->entityLeave(i,xf86Entities[i]->private);
|
|
}
|
|
|
|
/*
|
|
* xf86EnterServerState() -- set state the server is in.
|
|
*/
|
|
|
|
typedef enum { TRI_UNSET, TRI_TRUE, TRI_FALSE } TriState;
|
|
|
|
void
|
|
xf86EnterServerState(xf86State state)
|
|
{
|
|
static int sigio_state;
|
|
static TriState sigio_blocked = TRI_UNSET;
|
|
|
|
/*
|
|
* 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.
|
|
*/
|
|
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;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* xf86PostProbe() -- Allocate all non conflicting resources
|
|
* This function gets called by xf86Init().
|
|
*/
|
|
void
|
|
xf86PostProbe(void)
|
|
{
|
|
int i;
|
|
|
|
if (fbSlotClaimed && (pciSlotClaimed
|
|
#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
|
|
|| sbusSlotClaimed
|
|
#endif
|
|
))
|
|
FatalError("Cannot run in framebuffer mode. Please specify busIDs "
|
|
" for all framebuffer devices\n");
|
|
|
|
for (i = 0; i < xf86NumEntities; i++)
|
|
if (xf86Entities[i]->entityInit)
|
|
xf86Entities[i]->entityInit(i,xf86Entities[i]->private);
|
|
}
|
|
|
|
void
|
|
xf86PostScreenInit(void)
|
|
{
|
|
xf86VGAarbiterWrapFunctions();
|
|
xf86EnterServerState(OPERATING);
|
|
}
|
|
|
|
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 */
|
|
memset(&nprivs[idx], 0, 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]);
|
|
}
|
|
|