This is Unofficial EPICS BASE Doxygen Site
devLibVME.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2010 Brookhaven Science Associates, as Operator of
3 * Brookhaven National Laboratory.
4 * Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
5 * National Laboratory.
6 * Copyright (c) 2002 The Regents of the University of California, as
7 * Operator of Los Alamos National Laboratory.
8 * EPICS BASE is distributed subject to a Software License Agreement found
9 * in file LICENSE that is included with this distribution.
10 \*************************************************************************/
11 /* devLib.c - support for allocation of common device resources */
12 
13 /*
14  * Original Author: Marty Kraimer
15  * Author: Jeff Hill
16  * Date: 03-10-93
17  *
18  * NOTES:
19  * .01 06-14-93 joh needs devAllocInterruptVector() routine
20  */
21 
22 #include <string.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 
26 #include "dbDefs.h"
27 #include "epicsMutex.h"
28 #include "errlog.h"
29 #include "ellLib.h"
30 
31 #define NO_DEVLIB_COMPAT
32 #include "devLibVME.h"
33 #include "devLibVMEImpl.h"
34 
35 static ELLLIST addrAlloc[atLast];
36 static ELLLIST addrFree[atLast];
37 
38 static size_t addrLast[atLast] = {
39  0xffff,
40  0xffffff,
41  0xffffffff,
42  0xffffff,
43  0xffffff,
44  };
45 
46 static unsigned addrHexDig[atLast] = {
47  4,
48  6,
49  8,
50  6,
51  6
52  };
53 
54 static long addrFail[atLast] = {
60  };
61 
62 static epicsMutexId addrListLock;
63 static char devLibInitFlag;
64 
65 const char *epicsAddressTypeName[]
66  = {
67  "VME A16",
68  "VME A24",
69  "VME A32",
70  "ISA",
71  "VME CR/CSR"
72  };
73 
74 typedef struct{
76  const char *pOwnerName;
77  volatile void *pPhysical;
78  /*
79  * first, last is used here instead of base, size
80  * so that we can store a block that is the maximum size
81  * available in type size_t
82  */
83  size_t begin;
84  size_t end;
85 }rangeItem;
86 
87 /*
88  * These routines are not exported
89  */
90 
91 static long devLibInit(void);
92 
93 static long addrVerify(
94  epicsAddressType addrType,
95  size_t base,
96  size_t size);
97 
98 static long blockFind (
99  epicsAddressType addrType,
100  const rangeItem *pRange,
101  /* size needed */
102  size_t requestSize,
103  /* n ls bits zero in base addr */
104  unsigned alignment,
105  /* base address found */
106  size_t *pFirst);
107 
108 static void report_conflict(
109  epicsAddressType addrType,
110  size_t base,
111  size_t size,
112  const char *pOwnerName);
113 
114 static void report_conflict_device(
115  epicsAddressType addrType,
116  const rangeItem *pRange);
117 
118 static void devInsertAddress(
119  ELLLIST *pRangeList,
120  rangeItem *pNewRange);
121 
122 static long devListAddressMap(
123  ELLLIST *pRangeList);
124 
125 static long devCombineAdjacentBlocks(
126  ELLLIST *pRangeList,
127  rangeItem *pRange);
128 
129 static long devInstallAddr(
130  rangeItem *pRange, /* item on the free list to be split */
131  const char *pOwnerName,
132  epicsAddressType addrType,
133  size_t base,
134  size_t size,
135  volatile void **ppPhysicalAddress);
136 
137 #define SUCCESS 0
138 
139 /*
140  * devBusToLocalAddr()
141  */
143  epicsAddressType addrType,
144  size_t busAddr,
145  volatile void **ppLocalAddress)
146 {
147  long status;
148  volatile void *localAddress;
149 
150  /*
151  * Make sure that devLib has been intialized
152  */
153  if (!devLibInitFlag) {
154  status = devLibInit();
155  if(status){
156  return status;
157  }
158  }
159 
160  /*
161  * Make sure we have a valid bus address
162  */
163  status = addrVerify (addrType, busAddr, 4);
164  if (status) {
165  return status;
166  }
167 
168  /*
169  * Call the virtual os routine to map the bus address to a CPU address
170  */
171  status = (*pdevLibVME->pDevMapAddr) (addrType, 0, busAddr, 4, &localAddress);
172  if (status) {
173  errPrintf (status, __FILE__, __LINE__, "%s bus address =0X%X\n",
174  epicsAddressTypeName[addrType], (unsigned int)busAddr);
175  return status;
176  }
177 
178  /*
179  * Return the local CPU address if the pointer is supplied
180  */
181  if (ppLocalAddress) {
182  *ppLocalAddress = localAddress;
183  }
184 
185  return SUCCESS;
186 
187 }/*end devBusToLocalAddr()*/
188 
189 
190 /*
191  * devRegisterAddress()
192  */
194  const char *pOwnerName,
195  epicsAddressType addrType,
196  size_t base,
197  size_t size,
198  volatile void **ppPhysicalAddress)
199 {
200  rangeItem *pRange;
201  long s;
202 
203  if (!devLibInitFlag) {
204  s = devLibInit();
205  if(s){
206  return s;
207  }
208  }
209 
210  s = addrVerify (addrType, base, size);
211  if (s) {
212  return s;
213  }
214 
215  if (size == 0) {
216  return S_dev_lowValue;
217  }
218 
219 #ifdef DEBUG
220  printf ("Req Addr 0X%X Size 0X%X\n", base, size);
221 #endif
222 
223  epicsMutexMustLock(addrListLock);
224  pRange = (rangeItem *) ellFirst(&addrFree[addrType]);
225  while (TRUE) {
226  if (pRange->begin > base) {
227  pRange = NULL;
228 # ifdef DEBUG
229  printf ("Unable to locate a free block\n");
230  devListAddressMap (&addrFree[addrType]);
231 # endif
232  break;
233  }
234  else if (base + (size - 1) <= pRange->end) {
235 # ifdef DEBUG
236  printf ("Found free block Begin 0X%X End 0X%X\n",
237  pRange->begin, pRange->end);
238 # endif
239  break;
240  }
241 
242  pRange = (rangeItem *) ellNext (&pRange->node);
243  }
244  epicsMutexUnlock(addrListLock);
245 
246  if (pRange==NULL) {
247  report_conflict (addrType, base, size, pOwnerName);
248  return S_dev_addressOverlap;
249  }
250 
251  s = devInstallAddr(
252  pRange, /* item on the free list to be split */
253  pOwnerName,
254  addrType,
255  base,
256  size,
257  ppPhysicalAddress);
258 
259  return s;
260 }
261 
262 /*
263  * devReadProbe()
264  *
265  * a bus error safe "wordSize" read at the specified address which returns
266  * unsuccessful status if the device isnt present
267  */
268 long devReadProbe (unsigned wordSize, volatile const void *ptr, void *pValue)
269 {
270  long status;
271 
272  if (!devLibInitFlag) {
273  status = devLibInit();
274  if (status) {
275  return status;
276  }
277  }
278 
279  return (*pdevLibVME->pDevReadProbe) (wordSize, ptr, pValue);
280 }
281 
282 /*
283  * devWriteProbe
284  *
285  * a bus error safe "wordSize" write at the specified address which returns
286  * unsuccessful status if the device isnt present
287  */
288 long devWriteProbe (unsigned wordSize, volatile void *ptr, const void *pValue)
289 {
290  long status;
291 
292  if (!devLibInitFlag) {
293  status = devLibInit();
294  if (status) {
295  return status;
296  }
297  }
298 
299  return (*pdevLibVME->pDevWriteProbe) (wordSize, ptr, pValue);
300 }
301 
302 /*
303  * devInstallAddr()
304  */
305 static long devInstallAddr (
306  rangeItem *pRange, /* item on the free list to be split */
307  const char *pOwnerName,
308  epicsAddressType addrType,
309  size_t base,
310  size_t size,
311  volatile void **ppPhysicalAddress)
312 {
313  volatile void *pPhysicalAddress;
314  rangeItem *pNewRange;
315  size_t reqEnd = base + (size-1);
316  long status;
317 
318  /*
319  * does it start below the specified block
320  */
321  if (base < pRange->begin) {
322  return S_dev_badArgument;
323  }
324 
325  /*
326  * does it end above the specified block
327  */
328  if (reqEnd > pRange->end) {
329  return S_dev_badArgument;
330  }
331 
332  /*
333  * always map through the virtual os in case the memory
334  * management is set up there
335  */
336  status = (*pdevLibVME->pDevMapAddr) (addrType, 0, base,
337  size, &pPhysicalAddress);
338  if (status) {
339  errPrintf (status, __FILE__, __LINE__, "%s base=0X%X size = 0X%X",
340  epicsAddressTypeName[addrType], (unsigned int)base, (unsigned int)size);
341  return status;
342  }
343 
344  /*
345  * set the callers variable if the pointer is supplied
346  */
347  if (ppPhysicalAddress) {
348  *ppPhysicalAddress = pPhysicalAddress;
349  }
350 
351  /*
352  * does it start at the beginning of the block
353  */
354  if (pRange->begin == base) {
355  if (pRange->end == reqEnd) {
356  epicsMutexMustLock(addrListLock);
357  ellDelete(&addrFree[addrType], &pRange->node);
358  epicsMutexUnlock(addrListLock);
359  free ((void *)pRange);
360  }
361  else {
362  pRange->begin = base + size;
363  }
364  }
365  /*
366  * does it end at the end of the block
367  */
368  else if (pRange->end == reqEnd) {
369  pRange->end = base-1;
370  }
371  /*
372  * otherwise split the item on the free list
373  */
374  else {
375 
376  pNewRange = (rangeItem *) calloc (1, sizeof(*pRange));
377  if(!pNewRange){
378  return S_dev_noMemory;
379  }
380 
381  pNewRange->begin = base + size;
382  pNewRange->end = pRange->end;
383  pNewRange->pOwnerName = "<fragmented block>";
384  pNewRange->pPhysical = NULL;
385  pRange->end = base - 1;
386 
387  /*
388  * add the node after the old item on the free list
389  * (blocks end up ordered by address)
390  */
391  epicsMutexMustLock(addrListLock);
392  ellInsert(&addrFree[addrType], &pRange->node, &pNewRange->node);
393  epicsMutexUnlock(addrListLock);
394  }
395 
396  /*
397  * allocate a new address range entry and add it to
398  * the list
399  */
400  pNewRange = (rangeItem *)calloc (1, sizeof(*pRange));
401  if (!pNewRange) {
402  return S_dev_noMemory;
403  }
404 
405  pNewRange->begin = base;
406  pNewRange->end = reqEnd;
407  pNewRange->pOwnerName = pOwnerName;
408  pNewRange->pPhysical = pPhysicalAddress;
409 
410  devInsertAddress (&addrAlloc[addrType], pNewRange);
411 
412  return SUCCESS;
413 }
414 
415 /*
416  * report_conflict()
417  */
418 static void report_conflict (
419  epicsAddressType addrType,
420  size_t base,
421  size_t size,
422  const char *pOwnerName
423 )
424 {
425  const rangeItem *pRange;
426 
427  errPrintf (
429  __FILE__,
430  __LINE__,
431  "%10s 0X%08X - OX%08X Requested by %s",
432  epicsAddressTypeName[addrType],
433  (unsigned int)base,
434  (unsigned int)(base+size-1),
435  pOwnerName);
436 
437  pRange = (rangeItem *) ellFirst(&addrAlloc[addrType]);
438  while (pRange) {
439 
440  if (pRange->begin <= base + (size-1) && pRange->end >= base) {
441  report_conflict_device (addrType, pRange);
442  }
443 
444  pRange = (rangeItem *) pRange->node.next;
445  }
446 }
447 
448 /*
449  * report_conflict_device()
450  */
451 static void report_conflict_device(epicsAddressType addrType, const rangeItem *pRange)
452 {
453  errPrintf (
455  __FILE__,
456  __LINE__,
457  "%10s 0X%08X - 0X%08X Owned by %s",
458  epicsAddressTypeName[addrType],
459  (unsigned int)pRange->begin,
460  (unsigned int)pRange->end,
461  pRange->pOwnerName);
462 }
463 
464 /*
465  * devUnregisterAddress()
466  */
468  epicsAddressType addrType,
469  size_t baseAddress,
470  const char *pOwnerName)
471 {
472  rangeItem *pRange;
473  int s;
474 
475  if (!devLibInitFlag) {
476  s = devLibInit();
477  if(s) {
478  return s;
479  }
480  }
481 
482  s = addrVerify (addrType, baseAddress, 1);
483  if (s != SUCCESS) {
484  return s;
485  }
486 
487  epicsMutexMustLock(addrListLock);
488  pRange = (rangeItem *) ellFirst(&addrAlloc[addrType]);
489  while (pRange) {
490  if (pRange->begin == baseAddress) {
491  break;
492  }
493  if (pRange->begin > baseAddress) {
494  pRange = NULL;
495  break;
496  }
497  pRange = (rangeItem *) ellNext(&pRange->node);
498  }
499  epicsMutexUnlock(addrListLock);
500 
501  if (!pRange) {
502  return S_dev_addressNotFound;
503  }
504 
505  if (strcmp(pOwnerName,pRange->pOwnerName)) {
507  errPrintf (
508  s,
509  __FILE__,
510  __LINE__,
511  "unregister address for %s at 0X%X failed because %s owns it",
512  pOwnerName,
513  (unsigned int)baseAddress,
514  pRange->pOwnerName);
515  return s;
516  }
517 
518  epicsMutexMustLock(addrListLock);
519  ellDelete (&addrAlloc[addrType], &pRange->node);
520  epicsMutexUnlock(addrListLock);
521 
522  pRange->pOwnerName = "<released fragment>";
523  devInsertAddress (&addrFree[addrType], pRange);
524  s = devCombineAdjacentBlocks (&addrFree[addrType], pRange);
525  if(s){
526  errMessage (s, "devCombineAdjacentBlocks error");
527  return s;
528  }
529 
530  return SUCCESS;
531 }
532 
533 /*
534  * devCombineAdjacentBlocks()
535  */
536 static long devCombineAdjacentBlocks(
537  ELLLIST *pRangeList,
538  rangeItem *pRange)
539 {
540  rangeItem *pBefore;
541  rangeItem *pAfter;
542 
543  pBefore = (rangeItem *) ellPrevious (&pRange->node);
544  pAfter = (rangeItem *) ellNext (&pRange->node);
545 
546  /*
547  * combine adjacent blocks
548  */
549  if (pBefore) {
550  if (pBefore->end == pRange->begin-1) {
551  epicsMutexMustLock(addrListLock);
552  pRange->begin = pBefore->begin;
553  ellDelete (pRangeList, &pBefore->node);
554  epicsMutexUnlock(addrListLock);
555  free ((void *)pBefore);
556  }
557  }
558 
559  if (pAfter) {
560  if (pAfter->begin == pRange->end+1) {
561  epicsMutexMustLock(addrListLock);
562  pRange->end = pAfter->end;
563  ellDelete (pRangeList, &pAfter->node);
564  epicsMutexUnlock(addrListLock);
565  free((void *)pAfter);
566  }
567  }
568 
569  return SUCCESS;
570 }
571 
572 /*
573  * devInsertAddress()
574  */
575 static void devInsertAddress(
576 ELLLIST *pRangeList,
577 rangeItem *pNewRange)
578 {
579  rangeItem *pBefore;
580  rangeItem *pAfter;
581 
582  epicsMutexMustLock(addrListLock);
583  pAfter = (rangeItem *) ellFirst (pRangeList);
584  while (pAfter) {
585  if (pNewRange->end < pAfter->begin) {
586  break;
587  }
588  pAfter = (rangeItem *) ellNext (&pAfter->node);
589  }
590 
591  if (pAfter) {
592  pBefore = (rangeItem *) ellPrevious (&pAfter->node);
593  ellInsert (pRangeList, &pBefore->node, &pNewRange->node);
594  }
595  else {
596  ellAdd (pRangeList, &pNewRange->node);
597  }
598  epicsMutexUnlock(addrListLock);
599 }
600 
601 /*
602  * devAllocAddress()
603  */
605  const char *pOwnerName,
606  epicsAddressType addrType,
607  size_t size,
608  unsigned alignment, /* n ls bits zero in base addr*/
609  volatile void ** pLocalAddress )
610 {
611  int s;
612  rangeItem *pRange;
613  size_t base = 0;
614 
615  if (!devLibInitFlag) {
616  s = devLibInit();
617  if(s){
618  return s;
619  }
620  }
621 
622  s = addrVerify (addrType, 0, size);
623  if(s){
624  return s;
625  }
626 
627  if (size == 0) {
628  return S_dev_lowValue;
629  }
630 
631  epicsMutexMustLock(addrListLock);
632  pRange = (rangeItem *) ellFirst (&addrFree[addrType]);
633  while (pRange) {
634  if ((pRange->end - pRange->begin) + 1 >= size){
635  s = blockFind (
636  addrType,
637  pRange,
638  size,
639  alignment,
640  &base);
641  if (s==SUCCESS) {
642  break;
643  }
644  }
645  pRange = (rangeItem *) pRange->node.next;
646  }
647  epicsMutexUnlock(addrListLock);
648 
649  if(!pRange){
651  errMessage(s, epicsAddressTypeName[addrType]);
652  return s;
653  }
654 
655  s = devInstallAddr (pRange, pOwnerName, addrType, base,
656  size, pLocalAddress);
657 
658  return s;
659 }
660 
661 /*
662  * addrVerify()
663  *
664  * care has been taken here not to overflow type size_t
665  */
666 static long addrVerify(epicsAddressType addrType, size_t base, size_t size)
667 {
668  if (addrType>=atLast) {
669  return S_dev_uknAddrType;
670  }
671 
672  if (size == 0) {
673  return addrFail[addrType];
674  }
675 
676  if (size-1 > addrLast[addrType]) {
677  return addrFail[addrType];
678  }
679 
680  if (base > addrLast[addrType]) {
681  return addrFail[addrType];
682  }
683 
684  if (size - 1 > addrLast[addrType] - base) {
685  return addrFail[addrType];
686  }
687 
688  return SUCCESS;
689 }
690 
691 /*
692  * devLibInit()
693  */
694 static long devLibInit (void)
695 {
696  rangeItem *pRange;
697  int i;
698 
699 
700  if(devLibInitFlag) return(SUCCESS);
701  if(!pdevLibVME) {
702  epicsPrintf ("pdevLibVME is NULL\n");
703  return S_dev_internal;
704  }
705 
706  if (NELEMENTS(addrAlloc) != NELEMENTS(addrFree)) {
707  return S_dev_internal;
708  }
709 
710  addrListLock = epicsMutexMustCreate();
711 
712  epicsMutexMustLock(addrListLock);
713  for (i=0; i<NELEMENTS(addrAlloc); i++) {
714  ellInit (&addrAlloc[i]);
715  ellInit (&addrFree[i]);
716  }
717 
718  for (i=0; i<NELEMENTS(addrAlloc); i++) {
719  pRange = (rangeItem *) malloc (sizeof(*pRange));
720  if (!pRange) {
721  return S_dev_noMemory;
722  }
723  pRange->pOwnerName = "<Vacant>";
724  pRange->pPhysical = NULL;
725  pRange->begin = 0;
726  pRange->end = addrLast[i];
727  ellAdd (&addrFree[i], &pRange->node);
728  }
729  epicsMutexUnlock(addrListLock);
730  devLibInitFlag = TRUE;
731  return pdevLibVME->pDevInit();
732 }
733 
734 /*
735  * devAddressMap()
736  */
737 long devAddressMap(void)
738 {
739  return devListAddressMap(addrAlloc);
740 }
741 
742 /*
743  * devListAddressMap()
744  */
745 static long devListAddressMap(ELLLIST *pRangeList)
746 {
747  rangeItem *pri;
748  int i;
749  long s;
750 
751  if (!devLibInitFlag) {
752  s = devLibInit ();
753  if (s) {
754  return s;
755  }
756  }
757 
758  epicsMutexMustLock(addrListLock);
759  for (i=0; i<NELEMENTS(addrAlloc); i++) {
760  pri = (rangeItem *) ellFirst(&pRangeList[i]);
761  if (pri) {
762  printf ("%s Address Map\n", epicsAddressTypeName[i]);
763  }
764  while (pri) {
765  printf ("\t0X%0*lX - 0X%0*lX physical base %p %s\n",
766  addrHexDig[i],
767  (unsigned long) pri->begin,
768  addrHexDig[i],
769  (unsigned long) pri->end,
770  pri->pPhysical,
771  pri->pOwnerName);
772  pri = (rangeItem *) ellNext (&pri->node);
773  }
774  }
775  epicsMutexUnlock(addrListLock);
776 
777  return SUCCESS;
778 }
779 
780 
781 /*
782  *
783  * blockFind()
784  *
785  * Find unoccupied block in a large block
786  *
787  */
788 static long blockFind (
789  epicsAddressType addrType,
790  const rangeItem *pRange,
791  /* size needed */
792  size_t requestSize,
793  /* n ls bits zero in base addr */
794  unsigned alignment,
795  /* base address found */
796  size_t *pBase)
797 {
798  int s = SUCCESS;
799  size_t bb;
800  size_t mask;
801  size_t newBase;
802  size_t newSize;
803 
804  /*
805  * align the block base
806  */
807  mask = devCreateMask (alignment);
808  newBase = pRange->begin;
809  if ( mask & newBase ) {
810  newBase |= mask;
811  newBase++;
812  }
813 
814  if ( requestSize == 0) {
815  return S_dev_badRequest;
816  }
817 
818  /*
819  * align size of block
820  */
821  newSize = requestSize;
822  if (mask & newSize) {
823  newSize |= mask;
824  newSize++;
825  }
826 
827  if (pRange->end - pRange->begin + 1 < newSize) {
828  return S_dev_badRequest;
829  }
830 
831  bb = pRange->begin;
832  while (bb <= (pRange->end + 1) - newSize) {
833  s = devNoResponseProbe (addrType, bb, newSize);
834  if (s==SUCCESS) {
835  *pBase = bb;
836  return SUCCESS;
837  }
838  bb += newSize;
839  }
840 
841  return s;
842 }
843 
844 /*
845  * devNoResponseProbe()
846  */
848  size_t base, size_t size)
849 {
850  volatile void *pPhysical;
851  size_t probe;
852  size_t byteNo;
853  unsigned wordSize;
854  union {
855  char charWord;
856  short shortWord;
857  int intWord;
858  long longWord;
859  }allWordSizes;
860  long s;
861 
862  if (!devLibInitFlag) {
863  s = devLibInit();
864  if (s) {
865  return s;
866  }
867  }
868 
869  byteNo = 0;
870  while (byteNo < size) {
871 
872  probe = base + byteNo;
873 
874  /*
875  * for all word sizes
876  */
877  for (wordSize=1; wordSize<=sizeof(allWordSizes); wordSize <<= 1) {
878  /*
879  * only check naturally aligned words
880  */
881  if ( (probe&(wordSize-1)) != 0 ) {
882  break;
883  }
884 
885  if (byteNo+wordSize>size) {
886  break;
887  }
888 
889  /*
890  * every byte in the block must
891  * map to a physical address
892  */
893  s = (*pdevLibVME->pDevMapAddr) (addrType, 0, probe, wordSize, &pPhysical);
894  if (s!=SUCCESS) {
895  return s;
896  }
897 
898  /*
899  * verify that no device is present
900  */
901  s = (*pdevLibVME->pDevReadProbe)(wordSize, pPhysical, &allWordSizes);
902  if (s==SUCCESS) {
903  return S_dev_addressOverlap;
904  }
905  }
906  byteNo++;
907  }
908  return SUCCESS;
909 }
910 
912 unsigned vectorNumber,
913 void (*pFunction)(void *),
914 void *parameter )
915 {
916  long status;
917 
918  if (!devLibInitFlag) {
919  status = devLibInit();
920  if (status) {
921  return status;
922  }
923  }
924 
925  return (*pdevLibVME->pDevConnectInterruptVME) (vectorNumber,
926  pFunction, parameter);
927 }
928 
930 unsigned vectorNumber,
931 void (*pFunction)(void *) )
932 {
933  long status;
934 
935  if (!devLibInitFlag) {
936  status = devLibInit();
937  if (status) {
938  return status;
939  }
940  }
941 
942  return (*pdevLibVME->pDevDisconnectInterruptVME) (vectorNumber, pFunction);
943 }
944 
945 int devInterruptInUseVME (unsigned level)
946 {
947  long status;
948 
949  if (!devLibInitFlag) {
950  status = devLibInit();
951  if (status) {
952  return status;
953  }
954  }
955 
956  return (*pdevLibVME->pDevInterruptInUseVME) (level);
957 }
958 
959 long devEnableInterruptLevelVME (unsigned level)
960 {
961  long status;
962 
963  if (!devLibInitFlag) {
964  status = devLibInit();
965  if (status) {
966  return status;
967  }
968  }
969 
970  return (*pdevLibVME->pDevEnableInterruptLevelVME) (level);
971 }
972 
973 long devDisableInterruptLevelVME (unsigned level)
974 {
975  long status;
976 
977  if (!devLibInitFlag) {
978  status = devLibInit();
979  if (status) {
980  return status;
981  }
982  }
983 
984  return (*pdevLibVME->pDevDisableInterruptLevelVME) (level);
985 }
986 
987 /*
988  * devConnectInterrupt ()
989  *
990  * !! DEPRECATED !!
991  */
993 epicsInterruptType intType,
994 unsigned vectorNumber,
995 void (*pFunction)(void *),
996 void *parameter)
997 {
998  long status;
999 
1000  if (!devLibInitFlag) {
1001  status = devLibInit();
1002  if (status) {
1003  return status;
1004  }
1005  }
1006 
1007  switch(intType){
1008  case intVME:
1009  case intVXI:
1010  return (*pdevLibVME->pDevConnectInterruptVME) (vectorNumber,
1011  pFunction, parameter);
1012  default:
1013  return S_dev_uknIntType;
1014  }
1015 }
1016 
1017 /*
1018  *
1019  * devDisconnectInterrupt()
1020  *
1021  * !! DEPRECATED !!
1022  */
1024 epicsInterruptType intType,
1025 unsigned vectorNumber,
1026 void (*pFunction)(void *)
1027 )
1028 {
1029  long status;
1030 
1031  if (!devLibInitFlag) {
1032  status = devLibInit();
1033  if (status) {
1034  return status;
1035  }
1036  }
1037 
1038  switch(intType){
1039  case intVME:
1040  case intVXI:
1041  return (*pdevLibVME->pDevDisconnectInterruptVME) (vectorNumber,
1042  pFunction);
1043  default:
1044  return S_dev_uknIntType;
1045  }
1046 }
1047 
1048 /*
1049  * devEnableInterruptLevel()
1050  *
1051  * !! DEPRECATED !!
1052  */
1054 epicsInterruptType intType,
1055 unsigned level)
1056 {
1057  long status;
1058 
1059  if (!devLibInitFlag) {
1060  status = devLibInit();
1061  if (status) {
1062  return status;
1063  }
1064  }
1065 
1066  switch(intType){
1067  case intVME:
1068  case intVXI:
1069  return (*pdevLibVME->pDevEnableInterruptLevelVME) (level);
1070  default:
1071  return S_dev_uknIntType;
1072  }
1073 }
1074 
1075 /*
1076  * devDisableInterruptLevel()
1077  *
1078  * !! DEPRECATED !!
1079  */
1081 epicsInterruptType intType,
1082 unsigned level)
1083 {
1084  long status;
1085 
1086  if (!devLibInitFlag) {
1087  status = devLibInit();
1088  if (status) {
1089  return status;
1090  }
1091  }
1092 
1093  switch(intType){
1094  case intVME:
1095  case intVXI:
1096  return (*pdevLibVME->pDevDisableInterruptLevelVME) (level);
1097  default:
1098  return S_dev_uknIntType;
1099  }
1100 }
1101 
1102 /*
1103  * locationProbe
1104  *
1105  * !! DEPRECATED !!
1106  */
1107 long locationProbe (epicsAddressType addrType, char *pLocation)
1108 {
1109  return devNoResponseProbe (addrType, (size_t) pLocation, sizeof(long));
1110 }
1111 
1112 /******************************************************************************
1113  *
1114  * The follwing may, or may not be present in the BSP for the CPU in use.
1115  *
1116  */
1117 /******************************************************************************
1118  *
1119  * Routines to use to allocate and free memory present in the A24 region.
1120  *
1121  ******************************************************************************/
1122 
1123 int devLibA24Debug = 0; /* Debugging flag */
1124 
1125 void *devLibA24Calloc(size_t size)
1126 {
1127  void *ret;
1128 
1129  ret = devLibA24Malloc(size);
1130 
1131  if (ret == NULL)
1132  return (NULL);
1133 
1134  memset(ret, 0x00, size);
1135  return(ret);
1136 }
1137 
1138 void *devLibA24Malloc(size_t size)
1139 {
1140  void *ret;
1141 
1142  if (devLibA24Debug)
1143  epicsPrintf ("devLibA24Malloc(%u) entered\n", (unsigned int)size);
1144 
1145  ret = pdevLibVME->pDevA24Malloc(size);
1146  return(ret);
1147 }
1148 
1149 void devLibA24Free(void *pBlock)
1150 {
1151  if (devLibA24Debug)
1152  epicsPrintf("devLibA24Free(%p) entered\n", pBlock);
1153 
1154  pdevLibVME->pDevA24Free(pBlock);
1155 }
long(* pDevInit)(void)
Init devLib.
Definition: devLibVMEImpl.h:67
long(* pDevEnableInterruptLevelVME)(unsigned level)
Enable VME interrupt level to CPU.
Definition: devLibVMEImpl.h:57
long devReadProbe(unsigned wordSize, volatile const void *ptr, void *pValue)
Probe the bus for reading from a specific address.
Definition: devLibVME.c:268
long devDisableInterruptLevelVME(unsigned level)
Disable a VME interrupt level.
Definition: devLibVME.c:973
long devEnableInterruptLevel(epicsInterruptType intType, unsigned level)
Definition: devLibVME.c:1053
int devLibA24Debug
Definition: devLibVME.c:1123
#define S_dev_addressNotFound
Specified device address unregistered.
Definition: devLib.h:90
pvd::Status status
size_t end
Definition: devLibVME.c:84
long(* pDevDisconnectInterruptVME)(unsigned vectorNumber, void(*pFunction)(void *))
Disconnect ISR from a VME interrupt vector.
Definition: devLibVMEImpl.h:53
int i
Definition: scan.c:967
#define S_dev_deviceDoesNotFit
Unable to locate address space for device.
Definition: devLib.h:114
#define S_dev_addressOverlap
Specified device address overlaps another device.
Definition: devLib.h:74
long devUnregisterAddress(epicsAddressType addrType, size_t baseAddress, const char *pOwnerName)
Release a bus address range previously registered.
Definition: devLibVME.c:467
long devDisableInterruptLevel(epicsInterruptType intType, unsigned level)
Definition: devLibVME.c:1080
long devBusToLocalAddr(epicsAddressType addrType, size_t busAddr, volatile void **ppLocalAddress)
Translate a bus address to a pointer the CPU can use.
Definition: devLibVME.c:142
#define printf
Definition: epicsStdio.h:41
#define S_dev_uknAddrType
Unrecognized address space type.
Definition: devLib.h:72
epicsAddressType
The available bus address types.
Definition: devLibVME.h:40
#define epicsMutexMustCreate()
Create an epicsMutex semaphore for use from C code.
Definition: epicsMutex.h:179
#define S_dev_lowValue
Parameter too low.
Definition: devLib.h:104
#define NULL
Definition: catime.c:38
#define errMessage(S, PM)
Definition: errlog.h:48
long devConnectInterruptVME(unsigned vectorNumber, void(*pFunction)(void *), void *parameter)
Connect an ISR up to a VME interrupt vector.
Definition: devLibVME.c:911
long(* pDevMapAddr)(epicsAddressType addrType, unsigned options, size_t logicalAddress, size_t size, volatile void **ppPhysicalAddress)
Map a bus address to the CPU&#39;s address space.
Definition: devLibVMEImpl.h:39
epicsTime begin
Definition: caConnTest.cpp:22
void epicsStdCall epicsMutexUnlock(epicsMutexId pmutexNode)
Release the semaphore.
Definition: epicsMutex.cpp:140
#define SUCCESS
Definition: devLibVME.c:137
Miscellaneous macro definitions.
#define ellPrevious(PNODE)
Find the previous node in list.
Definition: ellLib.h:104
int(* pDevInterruptInUseVME)(unsigned vectorNumber)
Check if interrupt vector has an ISR connected.
Definition: devLibVMEImpl.h:70
long devNoResponseProbe(epicsAddressType addrType, size_t base, size_t size)
Read-probe a range of bus addresses, looking for empty space.
Definition: devLibVME.c:847
long devConnectInterrupt(epicsInterruptType intType, unsigned vectorNumber, void(*pFunction)(void *), void *parameter)
Definition: devLibVME.c:992
#define S_dev_noMemory
Memory allocation failed.
Definition: devLib.h:88
A doubly-linked list library.
void ellAdd(ELLLIST *pList, ELLNODE *pNode)
Adds a node to the end of a list.
Definition: ellLib.c:24
long devEnableInterruptLevelVME(unsigned level)
Enable a VME interrupt level onto the CPU.
Definition: devLibVME.c:959
#define ellNext(PNODE)
Find the next node in list.
Definition: ellLib.h:99
#define S_dev_badISA
Invalid ISA address.
Definition: devLib.h:124
void errPrintf(long status, const char *pFileName, int lineno, const char *pformat,...)
Definition: errlog.c:383
void devLibA24Free(void *pBlock)
free() for VME drivers that support DMA.
Definition: devLibVME.c:1149
long(* pDevConnectInterruptVME)(unsigned vectorNumber, void(*pFunction)(void *), void *parameter)
Connect ISR to a VME interrupt vector.
Definition: devLibVMEImpl.h:50
APIs for the epicsMutex mutual exclusion semaphore.
#define S_dev_identifyOverlap
This device already owns the address range.
Definition: devLib.h:76
#define epicsPrintf
Definition: errlog.h:51
int devInterruptInUseVME(unsigned level)
Determine if a VME interrupt vector is in use.
Definition: devLibVME.c:945
LIBCOM_API devLibVME * pdevLibVME
Pointer to the entry table used by devLibVME routines.
Definition: devLibVMEOSD.c:12
void(* pDevA24Free)(void *pBlock)
Free a block allocated for the VME A24 address space.
Definition: devLibVMEImpl.h:64
An interface from devLibVME.c to its OS-specific implementations.
#define NELEMENTS(A)
Definition: aToIPAddr.c:21
volatile void * pPhysical
Definition: devLibVME.c:77
List node type.
Definition: ellLib.h:45
ELLNODE node
Definition: devLibVME.c:75
const char * epicsAddressTypeName[]
A string representation of each of the bus address types.
Definition: devLibVME.c:66
long(* pDevDisableInterruptLevelVME)(unsigned level)
Disable VME interrupt level to CPU.
Definition: devLibVMEImpl.h:59
#define S_dev_badA32
Invalid VME A32 address.
Definition: devLib.h:70
const char * pOwnerName
Definition: devLibVME.c:76
long devAddressMap(void)
Print a map of registered bus addresses.
Definition: devLibVME.c:737
void * devLibA24Malloc(size_t size)
malloc() for VME drivers that support DMA.
Definition: devLibVME.c:1138
size_t begin
Definition: devLibVME.c:83
struct ELLNODE * next
Pointer to next node in list.
Definition: ellLib.h:46
long(* pDevReadProbe)(unsigned wordSize, volatile const void *ptr, void *pValueRead)
Read a word, detect and protect against bus errors.
Definition: devLibVMEImpl.h:43
Invalid, must be the last entry.
Definition: devLibVME.h:46
long devDisconnectInterrupt(epicsInterruptType intType, unsigned vectorNumber, void(*pFunction)(void *))
Definition: devLibVME.c:1023
long devDisconnectInterruptVME(unsigned vectorNumber, void(*pFunction)(void *))
Disconnect an ISR from its VME interrupt vector.
Definition: devLibVME.c:929
#define S_dev_badRequest
Device does not support requested operation.
Definition: devLib.h:100
#define TRUE
Definition: dbDefs.h:27
#define S_dev_uknIntType
Unrecognized interrupt type.
Definition: devLib.h:62
#define ellInit(PLIST)
Initialize a list type.
Definition: ellLib.h:76
void * devLibA24Calloc(size_t size)
calloc() for VME drivers that support DMA.
Definition: devLibVME.c:1125
long devAllocAddress(const char *pOwnerName, epicsAddressType addrType, size_t size, unsigned alignment, volatile void **pLocalAddress)
Allocate and register an unoccupied address block.
Definition: devLibVME.c:604
void ellInsert(ELLLIST *plist, ELLNODE *pPrev, ELLNODE *pNode)
Inserts a node into a list immediately after a specific node.
Definition: ellLib.c:178
int * base
Definition: flex.c:92
#define S_dev_badArgument
Bad function argument.
Definition: devLib.h:122
#define S_dev_badA24
Invalid VME A24 address.
Definition: devLib.h:68
long devWriteProbe(unsigned wordSize, volatile void *ptr, const void *pValue)
Probe the bus for writing to a specific address.
Definition: devLibVME.c:288
void *(* pDevA24Malloc)(size_t nbytes)
Malloc a block accessible from the VME A24 address space.
Definition: devLibVMEImpl.h:62
#define devCreateMask(NBITS)
Create a bit mask for a given number of bits.
Definition: devLib.h:28
List header type.
Definition: ellLib.h:56
#define S_dev_badCRCSR
Invalid VME CR/CSR address.
Definition: devLib.h:126
#define epicsMutexMustLock(ID)
Claim a semaphore (see epicsMutexLock()).
Definition: epicsMutex.h:214
epicsInterruptType
Definition: devLibVME.h:367
void ellDelete(ELLLIST *pList, ELLNODE *pNode)
Deletes a node from a list.
Definition: ellLib.c:75
#define S_dev_internal
Internal failure.
Definition: devLib.h:82
#define S_dev_badA16
Invalid VME A16 address.
Definition: devLib.h:66
long devRegisterAddress(const char *pOwnerName, epicsAddressType addrType, size_t base, size_t size, volatile void **ppPhysicalAddress)
Register a bus address range with a name.
Definition: devLibVME.c:193
long locationProbe(epicsAddressType addrType, char *pLocation)
Definition: devLibVME.c:1107
long(* pDevWriteProbe)(unsigned wordSize, volatile void *ptr, const void *pValueWritten)
Write a word, detect and protect against bus errors.
Definition: devLibVMEImpl.h:46
API for accessing hardware devices, mosty over VMEbus.
#define ellFirst(PLIST)
Find the first node in list.
Definition: ellLib.h:89