Files
pcas/src/db/devLib.c
Janet B. Anderson afd124a431 Added cvs Id keyword
1995-02-13 21:44:49 +00:00

1313 lines
24 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* devLib.c - support for allocation of common device resources */
/* @(#)$Id$*/
/*
* Original Author: Marty Kraimer
* Author: Jeff Hill
* Date: 03-10-93
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
* .01 03-10-93 joh original
* .02 03-18-93 joh index address alloc array by fundamental type
* .03 03-23-93 joh changed input parameter to be a fund
* address type in favor of the argument
* that the BSP will be reconfigured
* to use an EPICS standard address
* mode
* .04 04-08-93 joh made unsolicitedHandlerEPICS() external
* .05 04-08-92 joh better diagnostic if we cant find
* a default interrupt handler
* .06 05-06-93 joh added new parameter to devDisconnectInterrupt().
* See comment below.
* .07 05-28-93 joh Added block probe routines
* .08 05-28-93 joh Added an argument to devRegisterAddress()
* .09 05-28-93 joh Added devAddressMap()
* .10 06-14-93 joh Added devAllocAddress()
*
* NOTES:
* .01 06-14-93 joh needs devAllocInterruptVector() routine
*/
static char *sccsID = "@(#) $Id$";
#include <vxWorks.h>
#include <types.h>
#include <iv.h>
#include <vme.h>
#include <lstLib.h>
#include <sysLib.h>
#include <sysSymTbl.h>
#include <memLib.h>
#include <intLib.h>
#include <logLib.h>
#include <string.h>
#include <stdioLib.h>
#include <stdlib.h>
#include <fast_lock.h>
#define devLibGlobal
#include <devLib.h>
LOCAL LIST addrAlloc[atLast];
LOCAL LIST addrFree[atLast];
LOCAL void *addrLast[atLast] = {
(void *) 0xffff,
(void *) 0xffffff,
(void *) 0xffffffff};
LOCAL long addrFail[atLast] = {
S_dev_badA16,
S_dev_badA24,
S_dev_badA32};
LOCAL FAST_LOCK addrListLock;
LOCAL char addrListInit;
typedef struct{
NODE node;
const char *pOwnerName;
void *pFirst;
void *pLast;
}rangeItem;
/*
* A list of the names of the unexpected interrupt handlers
* ( some of these are provided by wrs )
*/
LOCAL char *defaultHandlerNames[] = {
"_excStub",
"_excIntStub",
"_unsolicitedHandlerEPICS"};
LOCAL void *defaultHandlerAddr[NELEMENTS(defaultHandlerNames)];
/*
* These routines are not exported
*/
LOCAL void initHandlerAddrList(void);
LOCAL int vectorInUse(unsigned vectorNumber);
LOCAL long initAddrList(void);
LOCAL long addrVerify(epicsAddressType addrType, void *address);
LOCAL void (*isrFetch(unsigned vectorNumber))();
LOCAL long blockFind(
epicsAddressType addrType,
void *pBlockFirst,
void *pBlockLast,
/* size needed */
unsigned long size,
/* n ls bits zero in base addr */
unsigned alignment,
/* base address found */
void **ppBase);
LOCAL long report_conflict(
epicsAddressType addrType,
void *pFirst,
void *pLast,
const char *pOwnerName);
LOCAL long devInsertAddress(
LIST *pRangeList,
rangeItem *pNewRange);
LOCAL long devListAddressMap(
LIST *pRangeList);
LOCAL long devCombineAdjacentBlocks(
LIST *pRangeList,
rangeItem *pRange);
LOCAL long devInstallAddr(
rangeItem *pRange,
const char *pOwnerName,
epicsAddressType addrType,
void *pFirst,
void *pLast,
void **pLocalAddress);
LOCAL long blockDivide(
epicsAddressType addrType,
void *pBlockFirst,
void *pBlockLast,
/* base address found */
void **ppBase,
unsigned long requestSize
);
LOCAL long blockProbe(
epicsAddressType addrType,
void *pFirst,
void *pLast
);
long locationProbe(
epicsAddressType addrType,
void *pLocation
);
/*
* this routine needs to be in the symbol table
* for this code to work correctly
*/
void unsolicitedHandlerEPICS(int vectorNumber);
/*
* this is in veclist.c
*/
int cISRTest(void (*)(), void (**)(), void **);
#define SUCCESS 0
/*
*
* devConnectInterrupt
*
* coded to support other interrupting types in the future
*
* wrapper to minimize driver dependency on vxWorks
*/
long devConnectInterrupt(
epicsInterruptType intType,
unsigned vectorNumber,
void (*pFunction)(),
void *parameter)
{
int status;
switch(intType){
case intCPU:
case intVME:
case intVXI:
if(vectorInUse(vectorNumber)){
return S_dev_vectorInUse;
}
status = intConnect(
(void *)INUM_TO_IVEC(vectorNumber),
pFunction,
(int) parameter);
if(status<0){
return S_dev_vxWorksVecInstlFail;
}
break;
default:
return S_dev_uknIntType;
}
return SUCCESS;
}
/*
*
* devDisconnectInterrupt()
*
* wrapper to minimize driver dependency on vxWorks
*
* The parameter pFunction should be set to the C function pointer that
* was connected. It is used as a key to prevent a driver from removing
* an interrupt handler that was installed by another driver
*
*/
long devDisconnectInterrupt(
epicsInterruptType intType,
unsigned vectorNumber,
void (*pFunction)()
)
{
void (*psub)();
int status;
/*
* If pFunction not connected to this vector
* then they are probably disconnecting from the wrong vector
*/
psub = isrFetch(vectorNumber);
if(psub != pFunction){
return S_dev_vectorNotInUse;
}
switch(intType){
case intCPU:
case intVME:
case intVXI:
status = intConnect(
(void *)INUM_TO_IVEC(vectorNumber),
unsolicitedHandlerEPICS,
(int) vectorNumber);
if(status<0){
return S_dev_vxWorksVecInstlFail;
}
break;
default:
return S_dev_uknIntType;
}
return SUCCESS;
}
/*
*
* devEnableInterruptLevel()
*
* wrapper to minimize driver dependency on vxWorks
*
*/
long devEnableInterruptLevel(
epicsInterruptType intType,
unsigned level)
{
int s;
switch(intType){
case intCPU:
case intVME:
case intVXI:
s = sysIntEnable(level);
if(s<0){
return S_dev_vxWorksIntEnFail;
}
break;
default:
return S_dev_uknIntType;
}
return SUCCESS;
}
/*
*
* devDisableInterruptLevel()
*
* wrapper to minimize driver dependency on vxWorks
*
*/
long devDisableInterruptLevel(
epicsInterruptType intType,
unsigned level)
{
int s;
switch(intType){
case intCPU:
case intVME:
case intVXI:
s = sysIntDisable(level);
if(s<0){
return S_dev_vxWorksIntDissFail;
}
break;
default:
return S_dev_uknIntType;
}
return SUCCESS;
}
/*
*
* devRegisterAddress()
*
*
*/
long devRegisterAddress(
const char *pOwnerName,
epicsAddressType addrType,
void *baseAddress,
unsigned long size,
void **pLocalAddress)
{
void *pFirst;
void *pLast;
rangeItem *pRange;
long s;
if(!addrListInit){
s = initAddrList();
if(s){
return s;
}
}
s = addrVerify(addrType, (void *) size);
if(s){
return s;
}
if(size == 0){
return S_dev_lowValue;
}
pFirst = baseAddress;
pLast = pFirst + size - 1;
FASTLOCK(&addrListLock);
pRange = (rangeItem *) addrFree[addrType].node.next;
while(pRange){
if(pRange->pFirst > pLast){
pRange = NULL;
break;
}
if(pRange->pFirst <= pFirst && pRange->pLast >= pLast){
break;
}
pRange = (rangeItem *) pRange->node.next;
}
FASTUNLOCK(&addrListLock);
if(!pRange){
s = report_conflict(addrType, pFirst, pLast, pOwnerName);
if(s){
return s;
}
else{
return S_dev_internal;
}
}
s = devInstallAddr(
pRange,
pOwnerName,
addrType,
pFirst,
pLast,
pLocalAddress);
return s;
}
/*
*
* devInstallAddr()
*
*/
LOCAL long devInstallAddr(
rangeItem *pRange, /* item on the free list to be split */
const char *pOwnerName,
epicsAddressType addrType,
void *pFirst,
void *pLast,
void **pLocalAddress)
{
rangeItem *pNewRange;
int s;
if(pLocalAddress){
int s1;
int s2;
s1 = sysBusToLocalAdrs(
EPICStovxWorksAddrType[addrType],
pLast,
(char **)pLocalAddress);
s2 = sysBusToLocalAdrs(
EPICStovxWorksAddrType[addrType],
pFirst,
(char **)pLocalAddress);
if(s1 || s2){
errPrintf(
S_dev_vxWorksAddrMapFail,
__FILE__,
__LINE__,
"%s base=0X %X size = 0X %X",
epicsAddressTypeName[addrType],
pFirst,
pLast-pFirst+1);
return S_dev_vxWorksAddrMapFail;
}
}
/*
* split the item on the free list
* (when required)
*/
if(pRange->pFirst == pFirst && pRange->pLast == pLast){
FASTLOCK(&addrListLock);
lstDelete(&addrFree[addrType], &pRange->node);
FASTUNLOCK(&addrListLock);
free((void *)pRange);
}
else if(pRange->pFirst == pFirst){
pRange->pFirst = pLast+1;
}
else if(pRange->pLast == pLast){
pRange->pLast = pFirst-1;
}
else{
pNewRange = (rangeItem *) malloc(sizeof(*pRange));
if(!pNewRange){
return S_dev_noMemory;
}
pNewRange->pFirst = pLast+1;
pNewRange->pLast = pRange->pLast;
pNewRange->pOwnerName = "<fragmented block>";
pRange->pLast = pFirst-1;
/*
* add the node after the old item on the free list
* (blocks end up ordered by address)
*/
FASTLOCK(&addrListLock);
lstInsert(&addrFree[addrType], &pRange->node, &pNewRange->node);
FASTUNLOCK(&addrListLock);
}
/*
* allocate a new address range entry and add it to
* the list
*/
pNewRange = (rangeItem *)calloc(1,sizeof(*pRange));
if(!pNewRange){
return S_dev_noMemory;
}
pNewRange->pFirst = pFirst;
pNewRange->pLast = pLast;
pNewRange->pOwnerName = pOwnerName;
s = devInsertAddress(&addrAlloc[addrType], pNewRange);
if(s){
free((void *)pNewRange);
return s;
}
return SUCCESS;
}
/*
*
* report_conflict()
*
*
*/
LOCAL long report_conflict(
epicsAddressType addrType,
void *pFirst,
void *pLast,
const char *pOwnerName
)
{
rangeItem *pRange;
pRange = (rangeItem *) addrAlloc[addrType].node.next;
while(pRange){
if(pRange->pFirst <= pFirst && pRange->pLast >= pFirst){
break;
}
if(pRange->pFirst <= pLast && pRange->pLast >= pLast){
break;
}
if(pRange->pFirst > pLast){
pRange = NULL;
break;
}
pRange = (rangeItem *) pRange->node.next;
}
if(pRange){
errPrintf(
S_dev_addressOverlap,
__FILE__,
__LINE__,
"%10s 0X %08X - %08X Requested by %s",
epicsAddressTypeName[addrType],
pFirst,
pLast,
pOwnerName);
errPrintf(
S_dev_identifyOverlap,
__FILE__,
__LINE__,
"%10s 0X %08X - %08X Owned by %s",
epicsAddressTypeName[addrType],
pRange->pFirst,
pRange->pLast,
pRange->pOwnerName);
return S_dev_addressOverlap;
}
return S_dev_internal;
}
/*
*
* devUnregisterAddress()
*
*/
long devUnregisterAddress(
epicsAddressType addrType,
void *baseAddress,
const char *pOwnerName)
{
rangeItem *pRange;
int s;
if(!addrListInit){
s = initAddrList();
if(s){
return s;
}
}
s = addrVerify(addrType, baseAddress);
if(s != SUCCESS){
return s;
}
FASTLOCK(&addrListLock);
pRange = (rangeItem *) addrAlloc[addrType].node.next;
while(pRange){
if(pRange->pFirst == baseAddress){
break;
}
if(pRange->pFirst > baseAddress){
pRange = NULL;
break;
}
pRange = (rangeItem *) pRange->node.next;
}
FASTUNLOCK(&addrListLock);
if(!pRange){
return S_dev_addressNotFound;
}
if(strcmp(pOwnerName,pRange->pOwnerName)){
s = S_dev_addressOverlap;
errPrintf(
s,
__FILE__,
__LINE__,
"unregister address for %s at 0X %X failed because %s owns it",
pOwnerName,
baseAddress,
pRange->pOwnerName);
return s;
}
FASTLOCK(&addrListLock);
lstDelete(
&addrAlloc[addrType],
&pRange->node);
FASTUNLOCK(&addrListLock);
pRange->pOwnerName = "<released fragment>";
s = devInsertAddress(&addrFree[addrType], pRange);
if(s){
free((void *)pRange);
errMessage(s, "Allocated Device Address Leak");
return s;
}
s = devCombineAdjacentBlocks(&addrFree[addrType], pRange);
if(s){
errMessage(s, NULL);
return s;
}
return SUCCESS;
}
/*
*
* devCombineAdjacentBlocks()
*
*
*/
LOCAL long devCombineAdjacentBlocks(
LIST *pRangeList,
rangeItem *pRange)
{
rangeItem *pBefore;
rangeItem *pAfter;
pBefore = (rangeItem *) pRange->node.previous;
pAfter = (rangeItem *) pRange->node.next;
/*
* combine adjacent blocks
*/
if(pBefore){
if(pBefore->pLast == pRange->pFirst-1){
FASTLOCK(&addrListLock);
pRange->pFirst = pBefore->pFirst;
lstDelete(pRangeList, &pBefore->node);
FASTUNLOCK(&addrListLock);
free((void *)pBefore);
}
}
if(pAfter){
if(pAfter->pFirst-1 == pRange->pLast){
FASTLOCK(&addrListLock);
pRange->pLast = pAfter->pLast;
lstDelete(pRangeList, &pAfter->node);
FASTUNLOCK(&addrListLock);
free((void *)pAfter);
}
}
return SUCCESS;
}
/*
*
* devInsertAddress()
*
*
*/
LOCAL long devInsertAddress(
LIST *pRangeList,
rangeItem *pNewRange)
{
rangeItem *pBefore;
rangeItem *pAfter;
FASTLOCK(&addrListLock);
pAfter = (rangeItem *) pRangeList->node.next;
while(pAfter){
if(pNewRange->pLast < pAfter->pFirst){
break;
}
pAfter = (rangeItem *) pAfter->node.next;
}
if(pAfter){
pBefore = (rangeItem *) pAfter->node.previous;
lstInsert(pRangeList, &pBefore->node, &pNewRange->node);
}
else{
lstAdd(pRangeList, &pNewRange->node);
}
FASTUNLOCK(&addrListLock);
return SUCCESS;
}
/*
*
* devAllocAddress()
*
*
*/
long devAllocAddress(
const char *pOwnerName,
epicsAddressType addrType,
unsigned long size,
unsigned alignment, /* n ls bits zero in base addr*/
void **pLocalAddress)
{
int s;
rangeItem *pRange;
void *pBase;
s = addrVerify(addrType, (void *)size);
if(s){
return s;
}
if(size == 0){
return S_dev_lowValue;
}
FASTLOCK(&addrListLock);
pRange = (rangeItem *) addrFree[addrType].node.next;
while(pRange){
if(pRange->pLast-pRange->pFirst>=size-1){
void *pF;
void *pL;
s = blockFind(
addrType,
pRange->pFirst,
pRange->pLast,
size,
alignment,
&pBase);
if(!s){
break;
}
}
pRange = (rangeItem *) pRange->node.next;
}
FASTUNLOCK(&addrListLock);
if(!pRange){
s = S_dev_deviceDoesNotFit;
errMessage(s, epicsAddressTypeName[addrType]);
return s;
}
s = devInstallAddr(
pRange,
pOwnerName,
addrType,
pBase,
pBase + size - 1,
pLocalAddress);
return s;
}
/*
* addrVerify()
*/
LOCAL long addrVerify(
epicsAddressType addrType,
void *address)
{
if(addrType>=atLast){
return S_dev_uknAddrType;
}
if(address > addrLast[addrType]){
return addrFail[addrType];
}
return SUCCESS;
}
/*
* initAddrList()
*/
LOCAL long initAddrList(void)
{
rangeItem *pRange;
if(NELEMENTS(addrAlloc) != NELEMENTS(addrFree)){
return S_dev_internal;
}
if(!addrListInit){
int i;
FASTLOCKINIT(&addrListLock);
FASTLOCK(&addrListLock);
for(i=0; i<NELEMENTS(addrAlloc); i++){
lstInit(&addrAlloc[i]);
lstInit(&addrFree[i]);
}
addrListInit = TRUE;
for(i=0; i<NELEMENTS(addrAlloc); i++){
pRange = (rangeItem *)malloc(sizeof *pRange);
if(!pRange){
return S_dev_noMemory;
}
pRange->pOwnerName = "<Vacant>";
pRange->pFirst = 0;
pRange->pLast = addrLast[i];
lstAdd(&addrFree[i], &pRange->node);
}
FASTUNLOCK(&addrListLock);
}
return SUCCESS;
}
/*
* devAddressMap()
*/
long devAddressMap(void)
{
return devListAddressMap(addrAlloc);
}
/*
* devListAddressMap()
*/
LOCAL long devListAddressMap(LIST *pRangeList)
{
rangeItem *pri;
int i;
long s;
if(!addrListInit){
s = initAddrList();
if(s){
return s;
}
}
FASTLOCK(&addrListLock);
for(i=0; i<NELEMENTS(addrAlloc); i++){
pri = (rangeItem *) lstFirst(&pRangeList[i]);
if(pri){
printf("%s Address Map\n", epicsAddressTypeName[i]);
}
while(pri){
printf("0X %08X - %08X %s\n",
pri->pFirst,
pri->pLast,
pri->pOwnerName);
pri = (rangeItem *) lstNext(&pri->node);
}
}
FASTUNLOCK(&addrListLock);
return SUCCESS;
}
/*
*
* unsolicitedHandlerEPICS()
* what gets called if they disconnect from an
* interrupt and an interrupt arrives on the
* disconnected vector
*
*/
void unsolicitedHandlerEPICS(int vectorNumber)
{
/*
* call logMsg() and not errMessage()
* so we are certain that printf()
* does not get called at interrupt level
*/
logMsg(
"%s: line=%d: Interrupt to EPICS disconnected vector = 0X %X",
(int)__FILE__,
__LINE__,
vectorNumber,
NULL,
NULL,
NULL);
}
/*
*
* initHandlerAddrList()
* init list of interrupt handlers to ignore
*
*/
LOCAL
void initHandlerAddrList(void)
{
int i;
UINT8 type;
int status;
for(i=0; i<NELEMENTS(defaultHandlerNames); i++){
status =
symFindByName( sysSymTbl,
defaultHandlerNames[i],
(char **)&defaultHandlerAddr[i],
&type);
if(status != OK){
errPrintf(
S_dev_internal,
__FILE__,
__LINE__,
"initHandlerAddrList() %s not in sym table",
defaultHandlerNames[i]);
}
}
}
/*
*
* isrFetch()
*
*
*/
LOCAL
void (*isrFetch(unsigned vectorNumber))()
{
void (*psub)();
void (*pCISR)();
void *pParam;
int s;
/*
* fetch the handler or C stub attached at this vector
*/
psub = (void (*)()) intVecGet((FUNCPTR *)INUM_TO_IVEC(vectorNumber));
/*
* from libvxWorks/veclist.c
*
* checks to see if it is a C ISR
* and if so finds the function pointer and
* the parameter passed
*/
s = cISRTest(psub, &pCISR, &pParam);
if(!s){
psub = pCISR;
}
return psub;
}
/*
*
* vectorInUse()
*
*
*/
LOCAL int
vectorInUse(
unsigned vectorNumber
)
{
static int init;
int i;
void (*psub)();
if(!init){
initHandlerAddrList();
init = TRUE;
}
psub = isrFetch(vectorNumber);
/*
* its a C routine. Does it match a default handler?
*/
for(i=0; i<NELEMENTS(defaultHandlerAddr); i++){
if(defaultHandlerAddr[i] == psub){
return FALSE;
}
}
return TRUE;
}
/*
*
* blockFind()
*
* Find unoccupied block in a large block
*
*/
LOCAL long blockFind(
epicsAddressType addrType,
void *pBlockFirst,
void *pBlockLast,
unsigned long size, /* size needed */
unsigned alignment, /* n ls bits zero in base addr */
void **ppBase /* base address found */
)
{
int s;
unsigned long mask;
/*
* align the block base
*/
mask = devCreateMask(alignment);
if(mask&(long)pBlockFirst){
pBlockFirst = (void *) (mask | (unsigned long) pBlockFirst);
pBlockFirst++;
}
if(pBlockFirst == 0){
return S_dev_badRequest;
}
if(pBlockLast < pBlockFirst){
return S_dev_badRequest;
}
/*
* align size of block
*/
if(mask & size){
size |= mask;
size++;
}
if(size == 0){
return S_dev_badRequest;
}
if(pBlockLast-pBlockFirst < size-1){
return S_dev_badRequest;
}
s = blockDivide(
addrType,
pBlockFirst,
pBlockFirst + (size-1),
ppBase,
size);
return s;
}
/*
* blockDivide()
* (binary search within a block)
* End up at a valid block without stepping through
* the entire address range.
*/
LOCAL long blockDivide(
epicsAddressType addrType,
void *pBlockFirst,
void *pBlockLast,
void **ppBase, /* base address found */
unsigned long requestSize
)
{
void *pBlock;
unsigned long bs;
int s;
s = blockProbe(addrType,pBlockFirst, pBlockFirst+(requestSize-1));
if(!s){
*ppBase = pBlockFirst;
return SUCCESS;
}
/*
* prevent unsigned long overflow
*/
bs = pBlockLast - pBlockFirst + 1;
if(bs == 0){
bs = 0x80000000;
}
else{
bs = bs >> 1;
}
while(bs > requestSize){
pBlock = pBlockFirst;
while(pBlock <= pBlockLast-bs+1){
pBlock += bs;
s = blockProbe(addrType, pBlock, pBlock+(requestSize-1));
if(!s){
*ppBase = pBlock;
return SUCCESS;
}
pBlock += bs;
}
bs = bs>>1;
}
return S_dev_deviceDoesNotFit;
}
/*
* blockProbe()
*/
LOCAL long blockProbe(
epicsAddressType addrType,
void *pFirst,
void *pLast
)
{
void *pProbe;
int s;
pProbe = pFirst;
while(pProbe <= pLast){
s = locationProbe(addrType, pProbe);
if(s){
return s;
}
pProbe++;
}
return SUCCESS;
}
/*
* locationProbe
*/
long locationProbe(
epicsAddressType addrType,
void *pLocation
)
{
void *pPhysical;
int s;
/*
* every byte in the block must
* map to a physical address
*/
s = sysBusToLocalAdrs(
EPICStovxWorksAddrType[addrType],
pLocation,
(char **)&pPhysical);
if(s<0){
return S_dev_vxWorksAddrMapFail;
}
{
char *pChar;
char byte;
pChar = pPhysical;
if(devPtrAlignTest(pChar)){
s = vxMemProbe(
pChar,
READ,
sizeof(byte),
&byte);
if(s!=ERROR){
return S_dev_addressOverlap;
}
}
}
{
short *pWord;
short word;
pWord = pPhysical;
if(devPtrAlignTest(pWord)){
s = vxMemProbe(
(char *)pWord,
READ,
sizeof(word),
(char *) &word);
if(s!=ERROR){
return S_dev_addressOverlap;
}
}
}
{
long *pLongWord;
long longWord;
pLongWord = pPhysical;
if(devPtrAlignTest(pLongWord)){
s = vxMemProbe(
(char *)pLongWord,
READ,
sizeof(longWord),
(char *)&longWord);
if(s!=ERROR){
return S_dev_addressOverlap;
}
}
}
return SUCCESS;
}
/******************************************************************************
*
* The follwing may, or may not be present in the BSP for the CPU in use.
*
*/
void *sysA24Malloc(unsigned long size);
STATUS sysA24Free(void *pBlock);
/******************************************************************************
*
* Routines to use to allocate and free memory present in the A24 region.
*
******************************************************************************/
static void * (*A24MallocFunc)(size_t) = NULL;
static void (*A24FreeFunc)(void *) = NULL;
int devLibA24Debug = 0; /* Debugging flag */
void *devLibA24Calloc(size_t size)
{
void *ret;
ret = devLibA24Malloc(size);
if (ret == NULL)
return (NULL);
memset(ret, 0x00, size);
return(ret);
}
void *devLibA24Malloc(size_t size)
{
SYM_TYPE stype;
static int UsingBSP = 0;
void *ret;
if (devLibA24Debug)
logMsg("devLibA24Malloc(%d) entered\n", size, 0,0,0,0,0);
if (A24MallocFunc == NULL)
{
/* See if the sysA24Malloc() function is present. */
if(symFindByName(sysSymTbl,"_sysA24Malloc", (char**)&A24MallocFunc,&stype)==ERROR)
{ /* Could not find sysA24Malloc... use the malloc one and hope we are OK */
if (devLibA24Debug)
logMsg("devLibA24Malloc() using regular malloc\n",0,0,0,0,0,0);
A24MallocFunc = malloc;
A24FreeFunc = free;
}
else
{
if(symFindByName(sysSymTbl,"_sysA24Free", (char**)&A24FreeFunc, &stype) == ERROR)
{ /* That's strange... we have malloc, but no free! */
if (devLibA24Debug)
logMsg("devLibA24Malloc() using regular malloc\n",0,0,0,0,0,0);
A24MallocFunc = malloc;
A24FreeFunc = free;
}
else
UsingBSP = 1;
}
}
ret = A24MallocFunc(size);
if ((ret == NULL) && (UsingBSP))
errMessage(S_dev_noMemory, "devLibA24Malloc ran out of A24 memory, try sysA24MapRam(size)");
return(ret);
}
void devLibA24Free(void *pBlock)
{
if (devLibA24Debug)
logMsg("devLibA24Free(%p) entered\n", (unsigned long)pBlock,0,0,0,0,0);
A24FreeFunc(pBlock);
}