31 #define NO_DEVLIB_COMPAT 38 static size_t addrLast[
atLast] = {
46 static unsigned addrHexDig[
atLast] = {
54 static long addrFail[
atLast] = {
63 static char devLibInitFlag;
91 static long devLibInit(
void);
93 static long addrVerify(
98 static long blockFind (
108 static void report_conflict(
112 const char *pOwnerName);
114 static void report_conflict_device(
118 static void devInsertAddress(
122 static long devListAddressMap(
125 static long devCombineAdjacentBlocks(
129 static long devInstallAddr(
131 const char *pOwnerName,
135 volatile void **ppPhysicalAddress);
145 volatile void **ppLocalAddress)
148 volatile void *localAddress;
153 if (!devLibInitFlag) {
154 status = devLibInit();
163 status = addrVerify (addrType, busAddr, 4);
173 errPrintf (status, __FILE__, __LINE__,
"%s bus address =0X%X\n",
181 if (ppLocalAddress) {
182 *ppLocalAddress = localAddress;
194 const char *pOwnerName,
198 volatile void **ppPhysicalAddress)
203 if (!devLibInitFlag) {
210 s = addrVerify (addrType, base, size);
220 printf (
"Req Addr 0X%X Size 0X%X\n", base, size);
226 if (pRange->
begin > base) {
229 printf (
"Unable to locate a free block\n");
230 devListAddressMap (&addrFree[addrType]);
234 else if (base + (size - 1) <= pRange->
end) {
236 printf (
"Found free block Begin 0X%X End 0X%X\n",
247 report_conflict (addrType, base, size, pOwnerName);
268 long devReadProbe (
unsigned wordSize,
volatile const void *ptr,
void *pValue)
272 if (!devLibInitFlag) {
273 status = devLibInit();
288 long devWriteProbe (
unsigned wordSize,
volatile void *ptr,
const void *pValue)
292 if (!devLibInitFlag) {
293 status = devLibInit();
305 static long devInstallAddr (
307 const char *pOwnerName,
311 volatile void **ppPhysicalAddress)
313 volatile void *pPhysicalAddress;
315 size_t reqEnd =
base + (size-1);
321 if (base < pRange->
begin) {
328 if (reqEnd > pRange->
end) {
337 size, &pPhysicalAddress);
339 errPrintf (status, __FILE__, __LINE__,
"%s base=0X%X size = 0X%X",
347 if (ppPhysicalAddress) {
348 *ppPhysicalAddress = pPhysicalAddress;
355 if (pRange->
end == reqEnd) {
359 free ((
void *)pRange);
368 else if (pRange->
end == reqEnd) {
376 pNewRange = (
rangeItem *) calloc (1,
sizeof(*pRange));
382 pNewRange->
end = pRange->
end;
400 pNewRange = (
rangeItem *)calloc (1,
sizeof(*pRange));
406 pNewRange->
end = reqEnd;
410 devInsertAddress (&addrAlloc[addrType], pNewRange);
418 static void report_conflict (
422 const char *pOwnerName
431 "%10s 0X%08X - OX%08X Requested by %s",
434 (
unsigned int)(base+size-1),
440 if (pRange->
begin <= base + (size-1) && pRange->
end >=
base) {
441 report_conflict_device (addrType, pRange);
457 "%10s 0X%08X - 0X%08X Owned by %s",
459 (
unsigned int)pRange->
begin,
460 (
unsigned int)pRange->
end,
470 const char *pOwnerName)
475 if (!devLibInitFlag) {
482 s = addrVerify (addrType, baseAddress, 1);
490 if (pRange->
begin == baseAddress) {
493 if (pRange->
begin > baseAddress) {
511 "unregister address for %s at 0X%X failed because %s owns it",
513 (
unsigned int)baseAddress,
523 devInsertAddress (&addrFree[addrType], pRange);
524 s = devCombineAdjacentBlocks (&addrFree[addrType], pRange);
526 errMessage (s,
"devCombineAdjacentBlocks error");
536 static long devCombineAdjacentBlocks(
550 if (pBefore->
end == pRange->
begin-1) {
555 free ((
void *)pBefore);
560 if (pAfter->
begin == pRange->
end+1) {
562 pRange->
end = pAfter->
end;
565 free((
void *)pAfter);
575 static void devInsertAddress(
585 if (pNewRange->
end < pAfter->
begin) {
605 const char *pOwnerName,
609 volatile void ** pLocalAddress )
615 if (!devLibInitFlag) {
622 s = addrVerify (addrType, 0, size);
634 if ((pRange->
end - pRange->
begin) + 1 >= size){
655 s = devInstallAddr (pRange, pOwnerName, addrType, base,
656 size, pLocalAddress);
673 return addrFail[addrType];
676 if (size-1 > addrLast[addrType]) {
677 return addrFail[addrType];
680 if (
base > addrLast[addrType]) {
681 return addrFail[addrType];
684 if (size - 1 > addrLast[addrType] -
base) {
685 return addrFail[addrType];
694 static long devLibInit (
void)
700 if(devLibInitFlag)
return(
SUCCESS);
719 pRange = (
rangeItem *) malloc (
sizeof(*pRange));
726 pRange->
end = addrLast[
i];
730 devLibInitFlag =
TRUE;
739 return devListAddressMap(addrAlloc);
745 static long devListAddressMap(
ELLLIST *pRangeList)
751 if (!devLibInitFlag) {
765 printf (
"\t0X%0*lX - 0X%0*lX physical base %p %s\n",
767 (
unsigned long) pri->
begin,
769 (
unsigned long) pri->
end,
788 static long blockFind (
808 newBase = pRange->
begin;
809 if ( mask & newBase ) {
814 if ( requestSize == 0) {
821 newSize = requestSize;
822 if (mask & newSize) {
827 if (pRange->
end - pRange->
begin + 1 < newSize) {
832 while (bb <= (pRange->
end + 1) - newSize) {
848 size_t base,
size_t size)
850 volatile void *pPhysical;
862 if (!devLibInitFlag) {
870 while (byteNo < size) {
872 probe = base + byteNo;
877 for (wordSize=1; wordSize<=
sizeof(allWordSizes); wordSize <<= 1) {
881 if ( (probe&(wordSize-1)) != 0 ) {
885 if (byteNo+wordSize>size) {
912 unsigned vectorNumber,
913 void (*pFunction)(
void *),
918 if (!devLibInitFlag) {
919 status = devLibInit();
926 pFunction, parameter);
930 unsigned vectorNumber,
931 void (*pFunction)(
void *) )
935 if (!devLibInitFlag) {
936 status = devLibInit();
949 if (!devLibInitFlag) {
950 status = devLibInit();
963 if (!devLibInitFlag) {
964 status = devLibInit();
977 if (!devLibInitFlag) {
978 status = devLibInit();
994 unsigned vectorNumber,
995 void (*pFunction)(
void *),
1000 if (!devLibInitFlag) {
1001 status = devLibInit();
1011 pFunction, parameter);
1025 unsigned vectorNumber,
1026 void (*pFunction)(
void *)
1031 if (!devLibInitFlag) {
1032 status = devLibInit();
1059 if (!devLibInitFlag) {
1060 status = devLibInit();
1086 if (!devLibInitFlag) {
1087 status = devLibInit();
1134 memset(ret, 0x00, size);
1143 epicsPrintf (
"devLibA24Malloc(%u) entered\n", (
unsigned int)size);
1152 epicsPrintf(
"devLibA24Free(%p) entered\n", pBlock);
long(* pDevInit)(void)
Init devLib.
long(* pDevEnableInterruptLevelVME)(unsigned level)
Enable VME interrupt level to CPU.
long devReadProbe(unsigned wordSize, volatile const void *ptr, void *pValue)
Probe the bus for reading from a specific address.
long devDisableInterruptLevelVME(unsigned level)
Disable a VME interrupt level.
long devEnableInterruptLevel(epicsInterruptType intType, unsigned level)
#define S_dev_addressNotFound
Specified device address unregistered.
long(* pDevDisconnectInterruptVME)(unsigned vectorNumber, void(*pFunction)(void *))
Disconnect ISR from a VME interrupt vector.
#define S_dev_deviceDoesNotFit
Unable to locate address space for device.
#define S_dev_addressOverlap
Specified device address overlaps another device.
long devUnregisterAddress(epicsAddressType addrType, size_t baseAddress, const char *pOwnerName)
Release a bus address range previously registered.
long devDisableInterruptLevel(epicsInterruptType intType, unsigned level)
long devBusToLocalAddr(epicsAddressType addrType, size_t busAddr, volatile void **ppLocalAddress)
Translate a bus address to a pointer the CPU can use.
#define S_dev_uknAddrType
Unrecognized address space type.
epicsAddressType
The available bus address types.
#define epicsMutexMustCreate()
Create an epicsMutex semaphore for use from C code.
#define S_dev_lowValue
Parameter too low.
#define errMessage(S, PM)
long devConnectInterruptVME(unsigned vectorNumber, void(*pFunction)(void *), void *parameter)
Connect an ISR up to a VME interrupt vector.
long(* pDevMapAddr)(epicsAddressType addrType, unsigned options, size_t logicalAddress, size_t size, volatile void **ppPhysicalAddress)
Map a bus address to the CPU's address space.
void epicsStdCall epicsMutexUnlock(epicsMutexId pmutexNode)
Release the semaphore.
Miscellaneous macro definitions.
#define ellPrevious(PNODE)
Find the previous node in list.
int(* pDevInterruptInUseVME)(unsigned vectorNumber)
Check if interrupt vector has an ISR connected.
long devNoResponseProbe(epicsAddressType addrType, size_t base, size_t size)
Read-probe a range of bus addresses, looking for empty space.
long devConnectInterrupt(epicsInterruptType intType, unsigned vectorNumber, void(*pFunction)(void *), void *parameter)
#define S_dev_noMemory
Memory allocation failed.
A doubly-linked list library.
void ellAdd(ELLLIST *pList, ELLNODE *pNode)
Adds a node to the end of a list.
long devEnableInterruptLevelVME(unsigned level)
Enable a VME interrupt level onto the CPU.
#define ellNext(PNODE)
Find the next node in list.
#define S_dev_badISA
Invalid ISA address.
void errPrintf(long status, const char *pFileName, int lineno, const char *pformat,...)
void devLibA24Free(void *pBlock)
free() for VME drivers that support DMA.
long(* pDevConnectInterruptVME)(unsigned vectorNumber, void(*pFunction)(void *), void *parameter)
Connect ISR to a VME interrupt vector.
APIs for the epicsMutex mutual exclusion semaphore.
#define S_dev_identifyOverlap
This device already owns the address range.
int devInterruptInUseVME(unsigned level)
Determine if a VME interrupt vector is in use.
LIBCOM_API devLibVME * pdevLibVME
Pointer to the entry table used by devLibVME routines.
void(* pDevA24Free)(void *pBlock)
Free a block allocated for the VME A24 address space.
An interface from devLibVME.c to its OS-specific implementations.
volatile void * pPhysical
const char * epicsAddressTypeName[]
A string representation of each of the bus address types.
long(* pDevDisableInterruptLevelVME)(unsigned level)
Disable VME interrupt level to CPU.
#define S_dev_badA32
Invalid VME A32 address.
long devAddressMap(void)
Print a map of registered bus addresses.
void * devLibA24Malloc(size_t size)
malloc() for VME drivers that support DMA.
struct ELLNODE * next
Pointer to next node in list.
long(* pDevReadProbe)(unsigned wordSize, volatile const void *ptr, void *pValueRead)
Read a word, detect and protect against bus errors.
Invalid, must be the last entry.
long devDisconnectInterrupt(epicsInterruptType intType, unsigned vectorNumber, void(*pFunction)(void *))
long devDisconnectInterruptVME(unsigned vectorNumber, void(*pFunction)(void *))
Disconnect an ISR from its VME interrupt vector.
#define S_dev_badRequest
Device does not support requested operation.
#define S_dev_uknIntType
Unrecognized interrupt type.
#define ellInit(PLIST)
Initialize a list type.
void * devLibA24Calloc(size_t size)
calloc() for VME drivers that support DMA.
long devAllocAddress(const char *pOwnerName, epicsAddressType addrType, size_t size, unsigned alignment, volatile void **pLocalAddress)
Allocate and register an unoccupied address block.
void ellInsert(ELLLIST *plist, ELLNODE *pPrev, ELLNODE *pNode)
Inserts a node into a list immediately after a specific node.
#define S_dev_badArgument
Bad function argument.
#define S_dev_badA24
Invalid VME A24 address.
long devWriteProbe(unsigned wordSize, volatile void *ptr, const void *pValue)
Probe the bus for writing to a specific address.
void *(* pDevA24Malloc)(size_t nbytes)
Malloc a block accessible from the VME A24 address space.
#define devCreateMask(NBITS)
Create a bit mask for a given number of bits.
#define S_dev_badCRCSR
Invalid VME CR/CSR address.
#define epicsMutexMustLock(ID)
Claim a semaphore (see epicsMutexLock()).
void ellDelete(ELLLIST *pList, ELLNODE *pNode)
Deletes a node from a list.
#define S_dev_internal
Internal failure.
#define S_dev_badA16
Invalid VME A16 address.
long devRegisterAddress(const char *pOwnerName, epicsAddressType addrType, size_t base, size_t size, volatile void **ppPhysicalAddress)
Register a bus address range with a name.
long locationProbe(epicsAddressType addrType, char *pLocation)
long(* pDevWriteProbe)(unsigned wordSize, volatile void *ptr, const void *pValueWritten)
Write a word, detect and protect against bus errors.
API for accessing hardware devices, mosty over VMEbus.
#define ellFirst(PLIST)
Find the first node in list.