This is Unofficial EPICS BASE Doxygen Site
devLibVMEOSD.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * EPICS BASE is distributed subject to a Software License Agreement found
7 * in file LICENSE that is included with this distribution.
8 \*************************************************************************/
9 /*
10  * Archictecture dependent support for common device driver resources
11  *
12  * Author: Jeff Hill
13  * Date: 10-30-98
14  */
15 
16 #include <stdlib.h>
17 
18 #include <vxWorks.h>
19 #include <types.h>
20 #include <iv.h>
21 #include <vme.h>
22 #include <sysLib.h>
23 #include <memLib.h>
24 #include <intLib.h>
25 #include <logLib.h>
26 #include <vxLib.h>
27 
28 #include "epicsFindSymbol.h"
29 #include "devLibVME.h"
30 #include "errlog.h"
31 
32 typedef void myISR (void *pParam);
33 
34 #if CPU_FAMILY != PPC
35 /*
36  * A list of the names of the unexpected interrupt handlers
37  * ( some of these are provided by wrs )
38  */
39 static char *defaultHandlerNames[] = {
40  "excStub",
41  "excIntStub",
42  "unsolicitedHandlerEPICS"};
43 
44 static myISR *defaultHandlerAddr[NELEMENTS(defaultHandlerNames)];
45 #endif
46 
47 static myISR *isrFetch(unsigned vectorNumber);
48 
49 /*
50  * this routine needs to be in the symbol table
51  * (i.e. not static) for this code to work correctly
52  */
53 void unsolicitedHandlerEPICS(int vectorNumber);
54 
55 /*
56  * this is in veclist.c
57  */
58 int cISRTest(void (*)(), void (**)(), void **);
59 
60 /*
61  * Make sure that the CR/CSR addressing mode is defined.
62  * (it may not be in older versions of vxWorks)
63  */
64 #ifndef VME_AM_CSR
65 # define VME_AM_CSR (0x2f)
66 #endif
67 
68 /*
69  * we use a translation between an EPICS encoding
70  * and a vxWorks encoding here
71  * to reduce dependency of drivers on vxWorks
72  *
73  * we assume that the BSP are configured to use these
74  * address modes by default
75  */
76 
77 #define EPICSAddrTypeNoConvert -1
78 
80  = {
81  VME_AM_SUP_SHORT_IO,
82  VME_AM_STD_SUP_DATA,
83  VME_AM_EXT_SUP_DATA,
86  };
87 
88 #if CPU_FAMILY != PPC
89 static void initHandlerAddrList(void);
90 #endif
91 
92 /*
93  * maps logical address to physical address, but does not detect
94  * two device drivers that are using the same address range
95  */
96 static long vxDevMapAddr (epicsAddressType addrType, unsigned options,
97  size_t logicalAddress, size_t size, volatile void **ppPhysicalAddress);
98 
99 /*
100  * a bus error safe "wordSize" read at the specified address which returns
101  * unsuccessful status if the device isnt present
102  */
103 static long vxDevReadProbe (unsigned wordSize, volatile const void *ptr, void *pValue);
104 
105 /*
106  * a bus error safe "wordSize" write at the specified address which returns
107  * unsuccessful status if the device isnt present
108  */
109 static long vxDevWriteProbe (unsigned wordSize, volatile void *ptr, const void *pValue);
110 
111 static void *devA24Malloc(size_t size);
112 static void devA24Free(void *pBlock);
113 
114 /* We don't know which functions are implemented in the BSP */
115 static int (*sysIntEnableFunc)(int) = NULL;
116 static int (*sysIntDisableFunc)(int) = NULL;
117 static int (*sysIntEnablePICFunc)(int) = NULL;
118 static int (*sysIntDisablePICFunc)(int) = NULL;
119 
120 static long devInit(void)
121 {
122  sysIntEnableFunc = epicsFindSymbol ("sysIntEnable");
123  sysIntDisableFunc = epicsFindSymbol ("sysIntDisable");
124  sysIntDisablePICFunc = epicsFindSymbol ("sysIntDisablePIC");
125  sysIntEnablePICFunc = epicsFindSymbol ("sysIntEnablePIC");
126  return 0;
127 }
128 
129 static long vxDevConnectInterruptVME (
130  unsigned vectorNumber,
131  void (*pFunction)(),
132  void *parameter);
133 
134 static long vxDevDisconnectInterruptVME (
135  unsigned vectorNumber,
136  void (*pFunction)()
137 );
138 
139 static long vxDevEnableInterruptLevelVME (unsigned level);
140 
141 static long vxDevDisableInterruptLevelVME (unsigned level);
142 
143 static int vxDevInterruptInUseVME (unsigned vectorNumber);
144 
145 /*
146  * used by dynamic bind in devLib.c
147  */
148 static devLibVME vxVirtualOS = {
149  vxDevMapAddr, vxDevReadProbe, vxDevWriteProbe,
150  vxDevConnectInterruptVME, vxDevDisconnectInterruptVME,
151  vxDevEnableInterruptLevelVME, vxDevDisableInterruptLevelVME,
152  devA24Malloc,devA24Free,devInit,vxDevInterruptInUseVME
153 };
154 devLibVME *pdevLibVME = &vxVirtualOS;
155 
156 /*
157  * devConnectInterruptVME
158  *
159  * wrapper to minimize driver dependency on vxWorks
160  */
161 static long vxDevConnectInterruptVME (
162  unsigned vectorNumber,
163  void (*pFunction)(),
164  void *parameter)
165 {
166  int status;
167 
168 
169  if (devInterruptInUseVME(vectorNumber)) {
170  return S_dev_vectorInUse;
171  }
172  status = intConnect(
173  (void *)INUM_TO_IVEC(vectorNumber),
174  pFunction,
175  (int) parameter);
176  if (status<0) {
177  return S_dev_vecInstlFail;
178  }
179 
180  return 0;
181 }
182 
183 /*
184  *
185  * vxDevDisconnectInterruptVME()
186  *
187  * wrapper to minimize driver dependency on vxWorks
188  *
189  * The parameter pFunction should be set to the C function pointer that
190  * was connected. It is used as a key to prevent a driver from removing
191  * an interrupt handler that was installed by another driver
192  *
193  */
194 static long vxDevDisconnectInterruptVME (
195  unsigned vectorNumber,
196  void (*pFunction)()
197 )
198 {
199  void (*psub)();
200  int status;
201 
202 # if CPU_FAMILY == PPC
203  return S_dev_vecInstlFail;
204 # endif
205 
206  /*
207  * If pFunction not connected to this vector
208  * then they are probably disconnecting from the wrong vector
209  */
210  psub = isrFetch(vectorNumber);
211  if(psub != pFunction){
212  return S_dev_vectorNotInUse;
213  }
214 
215  status = intConnect(
216  (void *)INUM_TO_IVEC(vectorNumber),
218  (int) vectorNumber);
219  if(status<0){
220  return S_dev_vecInstlFail;
221  }
222 
223  return 0;
224 }
225 
226 /*
227  * enable VME interrupt level
228  */
229 static long vxDevEnableInterruptLevelVME (unsigned level)
230 {
231  if (sysIntEnableFunc) {
232  int s;
233  s = sysIntEnableFunc (level);
234  if (s!=OK) {
235  return S_dev_intEnFail;
236  }
237  return 0;
238  } else {
239  return S_dev_intEnFail;
240  }
241 }
242 
243 /*
244  * enable ISA interrupt level
245  */
246 long devEnableInterruptLevelISA (unsigned level)
247 {
248  if (sysIntEnablePICFunc) {
249  int s;
250  s = sysIntEnablePICFunc (level);
251  if (s!=OK) {
252  return S_dev_intEnFail;
253  }
254  return 0;
255  } else {
256  return S_dev_intEnFail;
257  }
258 }
259 
260 /*
261  * disable ISA interrupt level
262  */
263 long devDisableInterruptLevelISA (unsigned level)
264 {
265  if (sysIntDisablePICFunc) {
266  int s;
267  s = sysIntDisablePICFunc (level);
268  if (s!=OK) {
269  return S_dev_intEnFail;
270  }
271  } else {
272  return S_dev_intEnFail;
273  }
274 
275  return 0;
276 }
277 
278 /*
279  * disable VME interrupt level
280  */
281 static long vxDevDisableInterruptLevelVME (unsigned level)
282 {
283  if (sysIntDisableFunc) {
284  int s;
285  s = sysIntDisableFunc (level);
286  if (s!=OK) {
287  return S_dev_intDissFail;
288  }
289  return 0;
290  } else {
291  return S_dev_intEnFail;
292  }
293 }
294 
295 /*
296  * vxDevMapAddr ()
297  */
298 static long vxDevMapAddr (epicsAddressType addrType, unsigned options,
299  size_t logicalAddress, size_t size, volatile void **ppPhysicalAddress)
300 {
301  long status;
302 
303  if (ppPhysicalAddress==NULL) {
304  return S_dev_badArgument;
305  }
306 
308  {
309  *ppPhysicalAddress = (void *) logicalAddress;
310  }
311  else
312  {
313  status = sysBusToLocalAdrs (EPICStovxWorksAddrType[addrType],
314  (char *) logicalAddress, (char **)ppPhysicalAddress);
315  if (status) {
316  return S_dev_addrMapFail;
317  }
318  }
319 
320  return 0;
321 }
322 
323 /*
324  * a bus error safe "wordSize" read at the specified address which returns
325  * unsuccessful status if the device isn't present
326  */
327 static long vxDevReadProbe (unsigned wordSize, volatile const void *ptr, void *pValue)
328 {
329  long status;
330 
331  status = vxMemProbe ((char *)ptr, VX_READ, wordSize, (char *) pValue);
332  if (status!=OK) {
333  return S_dev_noDevice;
334  }
335 
336  return 0;
337 }
338 
339 /*
340  * a bus error safe "wordSize" write at the specified address which returns
341  * unsuccessful status if the device isn't present
342  */
343 static long vxDevWriteProbe (unsigned wordSize, volatile void *ptr, const void *pValue)
344 {
345  long status;
346 
347  status = vxMemProbe ((char *)ptr, VX_WRITE, wordSize, (char *) pValue);
348  if (status!=OK) {
349  return S_dev_noDevice;
350  }
351 
352  return 0;
353 }
354 
355 /*
356  * isrFetch()
357  */
358 static myISR *isrFetch(unsigned vectorNumber)
359 {
360  myISR *psub;
361  myISR *pCISR;
362  void *pParam;
363  int s;
364 
365  /*
366  * fetch the handler or C stub attached at this vector
367  */
368  psub = (myISR *) intVecGet((FUNCPTR *)INUM_TO_IVEC(vectorNumber));
369 
370  if ( psub ) {
371  /*
372  * from libvxWorks/veclist.c
373  *
374  * checks to see if it is a C ISR
375  * and if so finds the function pointer and
376  * the parameter passed
377  */
378  s = cISRTest(psub, &pCISR, &pParam);
379  if(!s){
380  psub = pCISR;
381  }
382  }
383 
384  return psub;
385 }
386 
387 /*
388  * determine if a VME interrupt vector is in use
389  */
390 static int vxDevInterruptInUseVME (unsigned vectorNumber)
391 {
392 #if CPU_FAMILY == PPC
393  return FALSE;
394 #else
395  {
396  static int init;
397  int i;
398  myISR *psub;
399 
400  if (!init) {
401  initHandlerAddrList();
402  init = TRUE;
403  }
404 
405  psub = isrFetch (vectorNumber);
406 
407  /*
408  * its a C routine. Does it match a default handler?
409  */
410  for (i=0; i<NELEMENTS(defaultHandlerAddr); i++) {
411  if (defaultHandlerAddr[i] == psub) {
412  return FALSE;
413  }
414  }
415  }
416  return TRUE;
417 # endif
418 }
419 
420 
421 /*
422  * unsolicitedHandlerEPICS()
423  * what gets called if they disconnect from an
424  * interrupt and an interrupt arrives on the
425  * disconnected vector
426  *
427  * This routine needs to be in the symbol table
428  * (i.e. not static) for this code to work correctly
429  */
430 void unsolicitedHandlerEPICS(int vectorNumber)
431 {
432  /*
433  * call logMsg() and not errMessage()
434  * so we are certain that printf()
435  * does not get called at interrupt level
436  */
437  logMsg(
438  "%s: line=%d: Interrupt to EPICS disconnected vector = 0X %X",
439  (int)__FILE__,
440  __LINE__,
441  vectorNumber,
442  0,
443  0,
444  0);
445 }
446 
447 #if CPU_FAMILY != PPC
448 /*
449  *
450  * initHandlerAddrList()
451  * init list of interrupt handlers to ignore
452  *
453  */
454 static
455 void initHandlerAddrList(void)
456 {
457  int i;
458 
459  for (i=0; i<NELEMENTS(defaultHandlerNames); i++) {
460  defaultHandlerAddr[i] = epicsFindSymbol(defaultHandlerNames[i]);
461  if(!defaultHandlerAddr[i]) {
462  errPrintf(
464  __FILE__,
465  __LINE__,
466  "initHandlerAddrList() %s not in sym table",
467  defaultHandlerNames[i]);
468  }
469  }
470 }
471 #endif
472 
473 /******************************************************************************
474  *
475  * Routines to use to allocate and free memory present in the A24 region.
476  *
477  ******************************************************************************/
478 
479 static void * (*A24MallocFunc)(size_t) = NULL;
480 static void (*A24FreeFunc)(void *) = NULL;
481 
482 static void *devA24Malloc(size_t size)
483 {
484  static int UsingBSP = 0;
485  void *ret;
486 
487  if (A24MallocFunc == NULL)
488  {
489  /* See if the sysA24Malloc() function is present. */
490  A24MallocFunc = epicsFindSymbol("sysA24Malloc");
491  if(!A24MallocFunc) {
492  A24MallocFunc = malloc;
493  A24FreeFunc = free;
494  } else {
495  A24FreeFunc = epicsFindSymbol("sysA24Free");
496  if(!A24FreeFunc) {
497  /* That's strange... we have malloc, but no free! */
498  A24MallocFunc = malloc;
499  A24FreeFunc = free;
500  } else {
501  UsingBSP = 1;
502  }
503  }
504  }
505  ret = A24MallocFunc(size);
506 
507  if ((ret == NULL) && (UsingBSP))
508  errMessage(S_dev_noMemory, "devLibA24Malloc ran out of A24 memory, try sysA24MapRam(size)");
509 
510  return(ret);
511 }
512 
513 static void devA24Free(void *pBlock)
514 {
515  A24FreeFunc(pBlock);
516 }
#define FALSE
Definition: dbDefs.h:32
pvd::Status status
int i
Definition: scan.c:967
epicsAddressType
The available bus address types.
Definition: devLibVME.h:40
#define NULL
Definition: catime.c:38
#define errMessage(S, PM)
Definition: errlog.h:48
void unsolicitedHandlerEPICS(int vectorNumber)
Definition: devLibVMEOSD.c:430
int cISRTest(void(*)(), void(**)(), void **)
void myISR(void *pParam)
Definition: devLibVMEOSD.c:32
long devDisableInterruptLevelISA(unsigned level)
Definition: devLibVMEOSD.c:263
#define S_dev_noMemory
Memory allocation failed.
Definition: devLib.h:88
#define S_dev_noDevice
No device at specified address.
Definition: devLib.h:92
void errPrintf(long status, const char *pFileName, int lineno, const char *pformat,...)
Definition: errlog.c:383
int devInterruptInUseVME(unsigned level)
Determine if a VME interrupt vector is in use.
Definition: devLibVME.c:945
#define S_dev_vectorNotInUse
Interrupt vector not in use by caller.
Definition: devLib.h:64
#define S_dev_intDissFail
Unable to disable interrupt level.
Definition: devLib.h:86
#define S_dev_vecInstlFail
Interrupt vector install failed.
Definition: devLib.h:60
#define NELEMENTS(A)
Definition: aToIPAddr.c:21
long devEnableInterruptLevelISA(unsigned level)
Definition: devLibVMEOSD.c:246
devLibVME * pdevLibVME
Pointer to the entry table used by devLibVME routines.
Definition: devLibVMEOSD.c:12
#define TRUE
Definition: dbDefs.h:27
int EPICStovxWorksAddrType[]
Definition: devLibVMEOSD.c:80
#define S_dev_vectorInUse
Interrupt vector in use.
Definition: devLib.h:58
A table of function pointers for devLibVME implementations.
Definition: devLibVMEImpl.h:37
LIBCOM_API void *epicsStdCall epicsFindSymbol(const char *name)
Definition: osdFindSymbol.c:23
#define S_dev_intEnFail
Unable to enable interrupt level.
Definition: devLib.h:84
#define EPICSAddrTypeNoConvert
Definition: devLibVMEOSD.c:77
#define S_dev_badArgument
Bad function argument.
Definition: devLib.h:122
#define S_dev_addrMapFail
Unable to map address.
Definition: devLib.h:78
#define S_dev_internal
Internal failure.
Definition: devLib.h:82
#define VME_AM_CSR
Definition: devLibVMEOSD.c:65
API for accessing hardware devices, mosty over VMEbus.