25 static const char sccsID[] =
"@(#) $Id$";
31 #define epicsExportSharedSymbols 33 #include "epicsMutex.h" 37 #define NO_DEVLIB_COMPAT 40 static ELLLIST addrAlloc[
atLast];
41 static ELLLIST addrFree[
atLast];
43 static size_t addrLast[
atLast] = {
51 static unsigned addrHexDig[
atLast] = {
59 static long addrFail[
atLast] = {
67 static epicsMutexId addrListLock;
68 static char devLibInitFlag;
96 static long devLibInit(
void);
98 static long addrVerify(
99 epicsAddressType addrType,
103 static long blockFind (
104 epicsAddressType addrType,
113 static void report_conflict(
114 epicsAddressType addrType,
117 const char *pOwnerName);
119 static void report_conflict_device(
120 epicsAddressType addrType,
123 static void devInsertAddress(
127 static long devListAddressMap(
128 ELLLIST *pRangeList);
130 static long devCombineAdjacentBlocks(
134 static long devInstallAddr(
136 const char *pOwnerName,
137 epicsAddressType addrType,
140 volatile void **ppPhysicalAddress);
148 epicsAddressType addrType,
150 volatile void **ppLocalAddress)
153 volatile void *localAddress;
158 if (!devLibInitFlag) {
159 status = devLibInit();
168 status = addrVerify (addrType, busAddr, 4);
176 status = (*
pdevLibVirtualOS->pDevMapAddr) (addrType, 0, busAddr, 4, &localAddress);
178 errPrintf (status, __FILE__, __LINE__,
"%s bus address =0X%X\n",
186 if (ppLocalAddress) {
187 *ppLocalAddress = localAddress;
199 const char *pOwnerName,
200 epicsAddressType addrType,
203 volatile void **ppPhysicalAddress)
208 if (!devLibInitFlag) {
215 s = addrVerify (addrType, base, size);
221 return S_dev_lowValue;
225 errlogPrintf (
"Req Addr 0X%X Size 0X%X\n", base, size);
228 epicsMutexMustLock(addrListLock);
229 pRange = (
rangeItem *) ellFirst(&addrFree[addrType]);
231 if (pRange->
begin > base) {
234 errlogPrintf (
"Unable to locate a free block\n");
235 devListAddressMap (&addrFree[addrType]);
239 else if (base + (size - 1) <= pRange->
end) {
241 errlogPrintf (
"Found free block Begin 0X%X End 0X%X\n",
249 epicsMutexUnlock(addrListLock);
252 report_conflict (addrType, base, size, pOwnerName);
253 return S_dev_addressOverlap;
270 static long devInstallAddr (
272 const char *pOwnerName,
273 epicsAddressType addrType,
276 volatile void **ppPhysicalAddress)
278 volatile void *pPhysicalAddress;
280 size_t reqEnd = base + (size-1);
286 if (base < pRange->begin) {
287 return S_dev_badArgument;
293 if (reqEnd > pRange->
end) {
294 return S_dev_badArgument;
302 size, &pPhysicalAddress);
304 errPrintf (status, __FILE__, __LINE__,
"%s base=0X%X size = 0X%X",
312 if (ppPhysicalAddress) {
313 *ppPhysicalAddress = pPhysicalAddress;
319 if (pRange->
begin == base) {
320 if (pRange->
end == reqEnd) {
321 epicsMutexMustLock(addrListLock);
322 ellDelete(&addrFree[addrType], &pRange->
node);
323 epicsMutexUnlock(addrListLock);
324 free ((
void *)pRange);
327 pRange->
begin = base + size;
333 else if (pRange->
end == reqEnd) {
334 pRange->
end = base-1;
341 pNewRange = (
rangeItem *) calloc (1,
sizeof(*pRange));
343 return S_dev_noMemory;
346 pNewRange->
begin = base + size;
347 pNewRange->
end = pRange->
end;
350 pRange->
end = base - 1;
356 epicsMutexMustLock(addrListLock);
357 ellInsert(&addrFree[addrType], &pRange->
node, &pNewRange->
node);
358 epicsMutexUnlock(addrListLock);
365 pNewRange = (
rangeItem *)calloc (1,
sizeof(*pRange));
367 return S_dev_noMemory;
370 pNewRange->
begin = base;
371 pNewRange->
end = reqEnd;
375 devInsertAddress (&addrAlloc[addrType], pNewRange);
383 static void report_conflict (
384 epicsAddressType addrType,
387 const char *pOwnerName
393 S_dev_addressOverlap,
396 "%10s 0X%08X - OX%08X Requested by %s",
399 (
unsigned int)(base+size-1),
402 pRange = (
rangeItem *) ellFirst(&addrAlloc[addrType]);
405 if (pRange->
begin <= base + (size-1) && pRange->
end >= base) {
406 report_conflict_device (addrType, pRange);
416 static void report_conflict_device(epicsAddressType addrType,
const rangeItem *pRange)
419 S_dev_identifyOverlap,
422 "%10s 0X%08X - 0X%08X Owned by %s",
424 (
unsigned int)pRange->
begin,
425 (
unsigned int)pRange->
end,
433 epicsAddressType addrType,
435 const char *pOwnerName)
440 if (!devLibInitFlag) {
447 s = addrVerify (addrType, baseAddress, 1);
452 epicsMutexMustLock(addrListLock);
453 pRange = (
rangeItem *) ellFirst(&addrAlloc[addrType]);
455 if (pRange->
begin == baseAddress) {
458 if (pRange->
begin > baseAddress) {
464 epicsMutexUnlock(addrListLock);
467 return S_dev_addressNotFound;
471 s = S_dev_addressOverlap;
476 "unregister address for %s at 0X%X failed because %s owns it",
478 (
unsigned int)baseAddress,
483 epicsMutexMustLock(addrListLock);
484 ellDelete (&addrAlloc[addrType], &pRange->
node);
485 epicsMutexUnlock(addrListLock);
488 devInsertAddress (&addrFree[addrType], pRange);
489 s = devCombineAdjacentBlocks (&addrFree[addrType], pRange);
491 errMessage (s,
"devCombineAdjacentBlocks error");
501 static long devCombineAdjacentBlocks(
515 if (pBefore->
end == pRange->
begin-1) {
516 epicsMutexMustLock(addrListLock);
518 ellDelete (pRangeList, &pBefore->
node);
519 epicsMutexUnlock(addrListLock);
520 free ((
void *)pBefore);
525 if (pAfter->
begin == pRange->
end+1) {
526 epicsMutexMustLock(addrListLock);
527 pRange->
end = pAfter->
end;
528 ellDelete (pRangeList, &pAfter->
node);
529 epicsMutexUnlock(addrListLock);
530 free((
void *)pAfter);
540 static void devInsertAddress(
547 epicsMutexMustLock(addrListLock);
548 pAfter = (
rangeItem *) ellFirst (pRangeList);
550 if (pNewRange->
end < pAfter->
begin) {
558 ellInsert (pRangeList, &pBefore->
node, &pNewRange->
node);
561 ellAdd (pRangeList, &pNewRange->
node);
563 epicsMutexUnlock(addrListLock);
570 const char *pOwnerName,
571 epicsAddressType addrType,
574 volatile void ** pLocalAddress )
580 if (!devLibInitFlag) {
587 s = addrVerify (addrType, 0, size);
593 return S_dev_lowValue;
596 epicsMutexMustLock(addrListLock);
597 pRange = (
rangeItem *) ellFirst (&addrFree[addrType]);
599 if ((pRange->
end - pRange->
begin) + 1 >= size){
612 epicsMutexUnlock(addrListLock);
615 s = S_dev_deviceDoesNotFit;
620 s = devInstallAddr (pRange, pOwnerName, addrType, base,
621 size, pLocalAddress);
631 static long addrVerify(epicsAddressType addrType,
size_t base,
size_t size)
634 return S_dev_uknAddrType;
638 return addrFail[addrType];
641 if (size-1 > addrLast[addrType]) {
642 return addrFail[addrType];
645 if (base > addrLast[addrType]) {
646 return addrFail[addrType];
649 if (size - 1 > addrLast[addrType] - base) {
650 return addrFail[addrType];
659 static long devLibInit (
void)
665 if(devLibInitFlag)
return(
SUCCESS);
667 epicsPrintf (
"pdevLibVirtualOS is NULL\n");
668 return S_dev_internal;
671 if (NELEMENTS(addrAlloc) != NELEMENTS(addrFree)) {
672 return S_dev_internal;
675 addrListLock = epicsMutexMustCreate();
677 epicsMutexMustLock(addrListLock);
678 for (i=0; i<NELEMENTS(addrAlloc); i++) {
679 ellInit (&addrAlloc[i]);
680 ellInit (&addrFree[i]);
683 for (i=0; i<NELEMENTS(addrAlloc); i++) {
684 pRange = (
rangeItem *) malloc (
sizeof(*pRange));
686 return S_dev_noMemory;
691 pRange->
end = addrLast[i];
692 ellAdd (&addrFree[i], &pRange->
node);
694 epicsMutexUnlock(addrListLock);
695 devLibInitFlag = TRUE;
704 return devListAddressMap(addrAlloc);
710 static long devListAddressMap(ELLLIST *pRangeList)
715 if (!devLibInitFlag) {
716 long s = devLibInit ();
723 epicsMutexMustLock(addrListLock);
724 for (i=0; i<NELEMENTS(addrAlloc); i++) {
725 pri = (
rangeItem *) ellFirst(&pRangeList[i]);
730 errlogPrintf (
"\t0X%0*lX - 0X%0*lX physical base %p %s\n",
732 (
unsigned long) pri->
begin,
734 (
unsigned long) pri->
end,
740 epicsMutexUnlock(addrListLock);
753 static long blockFind (
754 epicsAddressType addrType,
772 mask = devCreateMask (alignment);
773 newBase = pRange->
begin;
774 if ( mask & newBase ) {
779 if ( requestSize == 0) {
780 return S_dev_badRequest;
786 newSize = requestSize;
787 if (mask & newSize) {
792 if (pRange->
end - pRange->
begin + 1 < newSize) {
793 return S_dev_badRequest;
797 while (bb <= (pRange->
end + 1) - newSize) {
809 #include <epicsExport.h>
long devAddressMap2(void)
volatile void * pPhysical
epicsExportRegistrar(devReplaceVirtualOS)
long devRegisterAddress2(const char *pOwnerName, epicsAddressType addrType, size_t base, size_t size, volatile void **ppPhysicalAddress)
devLibVirtualOS * pdevLibVirtualOS
long devUnregisterAddress2(epicsAddressType addrType, size_t baseAddress, const char *pOwnerName)
devLibVirtualOS * pdevLibVME2
void devReplaceVirtualOS(void)
long devNoResponseProbe(epicsAddressType addrType, size_t base, size_t size)
long devBusToLocalAddr2(epicsAddressType addrType, size_t busAddr, volatile void **ppLocalAddress)
long devAllocAddress2(const char *pOwnerName, epicsAddressType addrType, size_t size, unsigned alignment, volatile void **pLocalAddress)
const char * epicsAddressTypeName[]
const char * epicsAddressTypeName2[]