www.pudn.com > vxwork_src.rar > usrSmObj.c
/* usrSmObj.c - shared memory object initialization */
/* Copyright 1992-2002 Wind River Systems, Inc. */
/*
modification history
--------------------
01e,13feb02,mas fixed staged delay/check for slave node startup (SPR 73189)
01d,02oct01,mas added staged delay/check for slave node startup (SPR 62128)
01c,13sep01,jws fix smObjSpinTries initialization (SPR68418)
01b,20jan99,scb modified to use "sm=" before SM_ANCHOR_ADRS (23035)
01a,16feb97,ms based on old 01i version.
*/
/*
DESCRIPTION
This file is used to configure and initialize the VxWorks shared memory
object support. This file is included by usrConfig.c.
SEE ALSO: usrExtra.c
NOMANUAL
*/
/******************************************************************************
*
* usrSmObjInit - initialize shared memory objects
*
* This routine initializes the shared memory objects facility. It sets up
* the shared memory objects facility if called from processor 0.
* Then it initializes a shared memory descriptor and calls smObjAttach()
* to attach this CPU to the shared memory object facility.
*
* When the shared memory pool resides on the local CPU dual ported memory,
* SM_OBJ_MEM_ADRS must be set to NONE in configAll.h and the shared memory
* objects pool is allocated from the VxWorks system pool.
*
* RETURNS: OK, or ERROR if unsuccessful.
*
* INTERNAL
* The delayed start for slave processors used below is required. The anchor
* may not yet be mapped to the bus. So, probing of shared memory locations is
* used to overcome Bus Errors which occur on many boards if the slave accesses
* shared memory (SM) before the master has finished initializing it. The code
* here simply delays access to the SM region until the SM master has finished
* initializing it.
*
* The method used is to repetitively probe key locations in the SM region
* after delay periods until valid values are detected or a time-out occurs.
* The initial delay period is set based on processor number. (The master
* processor does not delay.) If the first probe of a location fails, an
* exponential increase in delay period is used to reduce bus contention on
* subsequent probes.
*
* This method is no better than receiving raw BERRs and does reduce bus
* contention and the number of BERRs.
*
* NOMANUAL
*/
STATUS usrSmObjInit
(
char * bootString /* boot parameter string */
)
{
char * smAnchor; /* anchor address */
char * smObjFreeAdrs; /* free pool address */
int smObjMemSize; /* pool size */
BOOT_PARAMS params; /* boot paramters */
BOOL allocatedPool; /* TRUE if pool is maloced */
SM_OBJ_PARAMS smObjParams; /* smObj setup parameters */
char bb; /* bit bucket for vxMemProbe */
int tics; /* SM probe delay period */
UINT temp; /* temp for smUtilMemProbe() */
UINT maxWait = SM_MAX_WAIT;
char * cp;
SM_OBJ_MEM_HDR * pSmObjHdr = NULL; /* ptr to SMO header */
allocatedPool = FALSE;
/* Check for hardware test and set availability */
if (SM_TAS_TYPE != SM_TAS_HARD)
{
printf ("\nError initializing shared memory objects, ");
printf ("hardware test-and-set required.\n");
return (ERROR);
}
if (smObjLibInit () == ERROR) /* initialize shared memory objects */
{
printf("\nERROR smObjLibInit : shared memory objects already initialized.\n");
return (ERROR);
}
if (bootString == NULL)
bootString = BOOT_LINE_ADRS;
/* interpret boot command */
if (usrBootLineCrack (bootString, ¶ms) != OK)
return (ERROR);
/* set processor number: may establish vme bus access, etc. */
if (_procNumWasSet != TRUE)
{
sysProcNumSet (params.procNum);
_procNumWasSet = TRUE;
}
/* if we booted via the sm device use the same anchor address for smObj */
if (strncmp (params.bootDev, "sm=", 3) == 0)
{
if (bootBpAnchorExtract (params.bootDev, &smAnchor) < 0)
{
printf ("\nError initializing shared memory objects, invalid ");
printf ("anchor address specified: \"%s\"\n", params.bootDev);
return (ERROR);
}
}
else
{
smAnchor = (char *) SM_ANCHOR_ADRS; /* default anchor */
}
/* If we are shared memory master CPU, set up shared memory object (SMO) */
if (params.procNum == SM_MASTER)
{
smObjFreeAdrs = (char *) SM_OBJ_MEM_ADRS;
smObjMemSize = SM_OBJ_MEM_SIZE;
/* allocate the shared memory object pool if needed */
if (smObjFreeAdrs == (char *) NONE)
{
/* check cache configuration - must be read and write coherent */
if (!CACHE_DMA_IS_WRITE_COHERENT() || !CACHE_DMA_IS_READ_COHERENT())
{
printf ("usrSmObjInit - cache coherent buffer not available. Giving up. \n");
return (ERROR);
}
allocatedPool = TRUE;
smObjFreeAdrs = (char *) cacheDmaMalloc (SM_OBJ_MEM_SIZE);
if (smObjFreeAdrs == NULL)
{
printf ("usrSmObjInit - cannot allocate shared memory pool. Giving up.\n");
return (ERROR);
}
}
if (!allocatedPool)
{
/* free memory pool must be behind the anchor */
smObjFreeAdrs += sizeof (SM_ANCHOR);
/* adjust pool size */
smObjMemSize = SM_OBJ_MEM_SIZE - sizeof (SM_ANCHOR);
}
/* probe anchor address */
if (vxMemProbe (smAnchor, VX_READ, sizeof (char), &bb) != OK)
{
printf ("usrSmObjInit - anchor address %#x unreachable. Giving up.\n", (unsigned int) smAnchor);
return (ERROR);
}
/* probe beginning of shared memory */
if (vxMemProbe (smObjFreeAdrs, VX_WRITE, sizeof (char), &bb) != OK)
{
printf ("usrSmObjInit - shared memory address %#x unreachable. Giving up.\n", (unsigned int) smObjFreeAdrs);
return (ERROR);
}
/* set up shared memory objects */
smObjSpinTries = SM_OBJ_MAX_TRIES; /* must do before smObjSetup() */
smObjParams.allocatedPool = allocatedPool;
smObjParams.pAnchor = (SM_ANCHOR *) smAnchor;
smObjParams.smObjFreeAdrs = (char *) smObjFreeAdrs;
smObjParams.smObjMemSize = smObjMemSize;
smObjParams.maxCpus = DEFAULT_CPUS_MAX;
smObjParams.maxTasks = SM_OBJ_MAX_TASK;
smObjParams.maxSems = SM_OBJ_MAX_SEM;
smObjParams.maxMsgQueues = SM_OBJ_MAX_MSG_Q;
smObjParams.maxMemParts = SM_OBJ_MAX_MEM_PART;
smObjParams.maxNames = SM_OBJ_MAX_NAME;
if (smObjSetup (&smObjParams) != OK)
{
if (errno == S_smObjLib_SHARED_MEM_TOO_SMALL)
printf("\nERROR smObjSetup : shared memory pool too small.\n");
if (allocatedPool)
free (smObjFreeAdrs); /* cleanup */
return (ERROR);
}
}
/*
* Else, we are not the master CPU, so wait until the anchor and SMO
* header regions are accessible (the master CPU has initialized them)
* before continuing.
*/
else
{
/* first wait for valid anchor region */
tics = params.procNum;
for (tics <<= 1; tics < maxWait; tics <<= 1)
{
smUtilDelay (NULL, tics);
if ((smUtilMemProbe (smAnchor, VX_READ, sizeof (UINT),
(char *)&temp) == OK) &&
(ntohl (temp) == SM_READY))
{
break;
}
}
if (tics >= maxWait)
{
printf ("usrSmObjInit: anchor @ %p unreachable. Giving up.\n",
smAnchor);
return (ERROR);
}
/* Finally, wait for master to init SM Object facility */
tics = params.procNum;
cp = (char *)(&((SM_ANCHOR *)smAnchor)->smObjHeader);
for (tics <<= 1; tics < maxWait; tics <<= 1)
{
if ((smUtilMemProbe (cp, VX_READ, sizeof (UINT), (char *)&temp)
== OK) &&
(temp != (UINT)~0) &&
(temp != 0))
{
break;
}
smUtilDelay (NULL, tics);
}
pSmObjHdr = SM_OFFSET_TO_LOCAL (ntohl (temp), (int)smAnchor,
SM_OBJ_MEM_HDR *);
cp = (char *)(&pSmObjHdr->initDone);
for ( ; tics < maxWait; tics <<= 1)
{
if ((smUtilMemProbe (cp, VX_READ, sizeof (UINT), (char *)&temp)
== OK) &&
(ntohl (temp) == TRUE))
{
break;
}
smUtilDelay (NULL, tics);
}
if (tics >= maxWait)
{
printf ("usrSmObjInit: Error: time out awaiting SM Object init\n");
return (ERROR);
}
}
/*
* initialize shared memory descriptor
*
* Note that SM_OBJ_MAX_TRIES is passed to smObjInit(),
* and is used to set the global int smObjSpinTries.
* This has already been done above to fix SPR68418.
*/
smObjInit (&smObjDesc, (SM_ANCHOR *) smAnchor, sysClkRateGet (),
SM_OBJ_MAX_TRIES, SM_INT_TYPE, SM_INT_ARG1,
SM_INT_ARG2, SM_INT_ARG3);
/* attach to shared memory object facility */
printf ("Attaching shared memory objects at %#x... ", (int) smAnchor);
if (smObjAttach (&smObjDesc) != OK)
{
printf ("failed: errno = %#x.\n", errno);
return (ERROR);
}
printf ("done\n");
return (OK);
}