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 /* RTEMS port by Till Straumann, <strauman@slac.stanford.edu>
11  * 3/2002
12  *
13  */
14 
15 #include <epicsStdio.h>
16 #include <epicsExit.h>
17 #include <rtems.h>
18 #include <bsp.h>
19 #include "devLibVME.h"
20 #include <epicsInterrupt.h>
21 
22 #if defined(__PPC__) || defined(__mcf528x__)
23 
24 #if defined(__PPC__)
25 #include <bsp/VME.h>
26 #include <bsp/bspExt.h>
27 #endif
28 
29 
30 typedef void myISR (void *pParam);
31 
32 static myISR *isrFetch(unsigned vectorNumber, void **parg);
33 
34 /*
35  * this routine needs to be in the symbol table
36  * for this code to work correctly
37  */
38 static void unsolicitedHandlerEPICS(int vectorNumber);
39 
40 static myISR *defaultHandlerAddr[]={
42 };
43 
44 /*
45  * Make sure that the CR/CSR addressing mode is defined.
46  * (it may not be in some BSPs).
47  */
48 #ifndef VME_AM_CSR
49 # define VME_AM_CSR (0x2f)
50 #endif
51 
52 /*
53  * we use a translation between an EPICS encoding
54  * and a vxWorks encoding here
55  * to reduce dependency of drivers on vxWorks
56  *
57  * we assume that the BSP are configured to use these
58  * address modes by default
59  */
60 #define EPICSAddrTypeNoConvert -1
62  = {
63  VME_AM_SUP_SHORT_IO,
64  VME_AM_STD_SUP_DATA,
65  VME_AM_EXT_SUP_DATA,
68  };
69 
70 /*
71  * maps logical address to physical address, but does not detect
72  * two device drivers that are using the same address range
73  */
74 static long rtemsDevMapAddr (epicsAddressType addrType, unsigned options,
75  size_t logicalAddress, size_t size, volatile void **ppPhysicalAddress);
76 
77 /*
78  * a bus error safe "wordSize" read at the specified address which returns
79  * unsuccessful status if the device isnt present
80  */
81 static long rtemsDevReadProbe (unsigned wordSize, volatile const void *ptr, void *pValue);
82 
83 /*
84  * a bus error safe "wordSize" write at the specified address which returns
85  * unsuccessful status if the device isnt present
86  */
87 static long rtemsDevWriteProbe (unsigned wordSize, volatile void *ptr, const void *pValue);
88 
89 static long rtemsDevConnectInterruptVME (
90  unsigned vectorNumber,
91  void (*pFunction)(),
92  void *parameter);
93 
94 static long rtemsDevDisconnectInterruptVME (
95  unsigned vectorNumber,
96  void (*pFunction)()
97 );
98 
99 static long rtemsDevEnableInterruptLevelVME (unsigned level);
100 
101 static long rtemsDevDisableInterruptLevelVME (unsigned level);
102 
103 static int rtemsDevInterruptInUseVME (unsigned vectorNumber);
104 
105 /* RTEMS specific init */
106 
107 /*devA24Malloc and devA24Free are not implemented*/
108 static void *devA24Malloc(size_t size) { return 0;}
109 static void devA24Free(void *pBlock) {};
110 static long rtemsDevInit(void);
111 
112 /*
113  * used by bind in devLib.c
114  */
115 static devLibVME rtemsVirtualOS = {
116  rtemsDevMapAddr, rtemsDevReadProbe, rtemsDevWriteProbe,
117  rtemsDevConnectInterruptVME, rtemsDevDisconnectInterruptVME,
118  rtemsDevEnableInterruptLevelVME, rtemsDevDisableInterruptLevelVME,
119  devA24Malloc,devA24Free,rtemsDevInit,rtemsDevInterruptInUseVME
120 };
121 devLibVME *pdevLibVME = &rtemsVirtualOS;
122 
123 /* RTEMS specific initialization */
124 static long
125 rtemsDevInit(void)
126 {
127  /* assume the vme bridge has been initialized by bsp */
128  /* init BSP extensions [memProbe etc.] */
129  return bspExtInit();
130 }
131 
132 /*
133  * devConnectInterruptVME
134  *
135  * wrapper to minimize driver dependency on OS
136  */
137 static long rtemsDevConnectInterruptVME (
138  unsigned vectorNumber,
139  void (*pFunction)(),
140  void *parameter)
141 {
142  int status;
143 
144 
145  if (devInterruptInUseVME(vectorNumber)) {
146  return S_dev_vectorInUse;
147  }
148  status = BSP_installVME_isr(
149  vectorNumber,
150  pFunction,
151  parameter);
152  if (status) {
153  return S_dev_vecInstlFail;
154  }
155 
156  return 0;
157 }
158 
159 /*
160  *
161  * devDisconnectInterruptVME()
162  *
163  * wrapper to minimize driver dependency on OS
164  *
165  * The parameter pFunction should be set to the C function pointer that
166  * was connected. It is used as a key to prevent a driver from removing
167  * an interrupt handler that was installed by another driver
168  *
169  */
170 static long rtemsDevDisconnectInterruptVME (
171  unsigned vectorNumber,
172  void (*pFunction)()
173 )
174 {
175  void (*psub)();
176  void *arg;
177  int status;
178 
179  /*
180  * If pFunction not connected to this vector
181  * then they are probably disconnecting from the wrong vector
182  */
183  psub = isrFetch(vectorNumber, &arg);
184  if(psub != pFunction){
185  return S_dev_vectorNotInUse;
186  }
187 
188  status = BSP_removeVME_isr(
189  vectorNumber,
190  psub,
191  arg) ||
192  BSP_installVME_isr(
193  vectorNumber,
194  (BSP_VME_ISR_t)unsolicitedHandlerEPICS,
195  (void*)vectorNumber);
196  if(status){
197  return S_dev_vecInstlFail;
198  }
199 
200  return 0;
201 }
202 
203 /*
204  * enable VME interrupt level
205  */
206 static long rtemsDevEnableInterruptLevelVME (unsigned level)
207 {
208  return BSP_enableVME_int_lvl(level);
209 }
210 
211 /*
212  * disable VME interrupt level
213  */
214 static long rtemsDevDisableInterruptLevelVME (unsigned level)
215 {
216  return BSP_disableVME_int_lvl(level);
217 }
218 
219 /*
220  * rtemsDevMapAddr ()
221  */
222 static long rtemsDevMapAddr (epicsAddressType addrType, unsigned options,
223  size_t logicalAddress, size_t size, volatile void **ppPhysicalAddress)
224 {
225  long status;
226 
227  if (ppPhysicalAddress==NULL) {
228  return S_dev_badArgument;
229  }
230 
232  {
233  *ppPhysicalAddress = (void *) logicalAddress;
234  }
235  else
236  {
237  status = BSP_vme2local_adrs(EPICStovxWorksAddrType[addrType],
238  logicalAddress, (unsigned long *)ppPhysicalAddress);
239  if (status) {
240  return S_dev_addrMapFail;
241  }
242  }
243 
244  return 0;
245 }
246 
247 /*
248  * a bus error safe "wordSize" read at the specified address which returns
249  * unsuccessful status if the device isnt present
250  */
251 rtems_status_code bspExtMemProbe(void *addr, int write, int size, void *pval);
252 static long rtemsDevReadProbe (unsigned wordSize, volatile const void *ptr, void *pValue)
253 {
254  long status;
255 
256  /*
257  * this global variable exists in the nivxi library
258  */
259  status = bspExtMemProbe ((void*)ptr, 0/*read*/, wordSize, pValue);
260  if (status!=RTEMS_SUCCESSFUL) {
261  return S_dev_noDevice;
262  }
263 
264  return 0;
265 }
266 
267 /*
268  * a bus error safe "wordSize" write at the specified address which returns
269  * unsuccessful status if the device isnt present
270  */
271 static long rtemsDevWriteProbe (unsigned wordSize, volatile void *ptr, const void *pValue)
272 {
273  long status;
274 
275  /*
276  * this global variable exists in the nivxi library
277  */
278  status = bspExtMemProbe ((void*)ptr, 1/*write*/, wordSize, (void*)pValue);
279  if (status!=RTEMS_SUCCESSFUL) {
280  return S_dev_noDevice;
281  }
282 
283  return 0;
284 }
285 
286 /*
287  * isrFetch()
288  */
289 static myISR *isrFetch(unsigned vectorNumber, void **parg)
290 {
291  /*
292  * fetch the handler or C stub attached at this vector
293  */
294  return (myISR *) BSP_getVME_isr(vectorNumber,parg);
295 }
296 
297 /*
298  * determine if a VME interrupt vector is in use
299  */
300 static int rtemsDevInterruptInUseVME (unsigned vectorNumber)
301 {
302  int i;
303  myISR *psub;
304  void *arg;
305 
306  psub = isrFetch (vectorNumber,&arg);
307 
308  if (!psub)
309  return FALSE;
310 
311  /*
312  * its a C routine. Does it match a default handler?
313  */
314  for (i=0; i<NELEMENTS(defaultHandlerAddr); i++) {
315  if (defaultHandlerAddr[i] == psub) {
316  return FALSE;
317  }
318  }
319 
320  return TRUE;
321 }
322 
323 
324 /*
325  * unsolicitedHandlerEPICS()
326  * what gets called if they disconnect from an
327  * interrupt and an interrupt arrives on the
328  * disconnected vector
329  *
330  * NOTE: RTEMS may pass additional arguments - hope
331  * this doesn't disturb this handler...
332  *
333  * A cleaner way would be having a OS dependent
334  * macro to declare handler prototypes...
335  *
336  */
337 static void unsolicitedHandlerEPICS(int vectorNumber)
338 {
339  /*
340  * call epicInterruptContextMessage()
341  * and not errMessage()
342  * so we are certain that printf()
343  * does not get called at interrupt level
344  *
345  * NOTE: current RTEMS implementation only
346  * allows a static string to be passed
347  */
349  "Interrupt to EPICS disconnected vector"
350  );
351 }
352 
353 #else /* !defined(__PPC__) && !defined(__mcf528x__) */
354 
355 /* No known VME interface here, provide a dummy */
357 
358 #endif /* defined(__PPC__) || defined(__mcf528x__) */
359 
360 /*
361  * Some vxWorks convenience routines
362  */
363 void
364 bcopyLongs(char *source, char *destination, int nlongs)
365 {
366  const long *s = (long *)source;
367  long *d = (long *)destination;
368  while(nlongs--)
369  *d++ = *s++;
370 }
#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
void unsolicitedHandlerEPICS(int vectorNumber)
Definition: devLibVMEOSD.c:430
void myISR(void *pParam)
Definition: devLibVMEOSD.c:32
#define S_dev_noDevice
No device at specified address.
Definition: devLib.h:92
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_vecInstlFail
Interrupt vector install failed.
Definition: devLib.h:60
Extended replacement for the Posix exit and atexit routines.
LIBCOM_API void epicsInterruptContextMessage(const char *message)
Definition: osdInterrupt.c:53
#define NELEMENTS(A)
Definition: aToIPAddr.c:21
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
#define EPICSAddrTypeNoConvert
Definition: devLibVMEOSD.c:77
#define S_dev_badArgument
Bad function argument.
Definition: devLib.h:122
void bcopyLongs(char *source, char *destination, int nlongs)
Definition: devLibVMEOSD.c:364
#define S_dev_addrMapFail
Unable to map address.
Definition: devLib.h:78
#define VME_AM_CSR
Definition: devLibVMEOSD.c:65
API for accessing hardware devices, mosty over VMEbus.