devLib2  2.12
vmesh.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2015 Michael Davidsaver
3 * Copyright (c) 2010 Brookhaven Science Associates, as Operator of
4 * Brookhaven National Laboratory.
5 * devLib2 is distributed subject to a Software License Agreement found
6 * in file LICENSE that is included with this distribution.
7 \*************************************************************************/
8 /*
9  * Author: Michael Davidsaver <mdavidsaver@gmail.com>
10  */
11 
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include <epicsVersion.h>
16 #include <epicsAssert.h>
17 #include <epicsTypes.h>
18 #include <epicsInterrupt.h>
19 #include <errlog.h>
20 #include <iocsh.h>
21 #include <epicsStdio.h>
22 #include <epicsExport.h>
23 #include <devcsr.h>
24 
25 static
26 int validate_widths(epicsUInt32 addr, int amod, int dmod, int count, volatile void** mptr)
27 {
28  epicsAddressType atype;
29  short dbytes;
30  epicsUInt32 alim;
31 
32  switch(dmod){
33  case 8:
34  case 16:
35  case 32:
36  break;
37  default:
38  fprintf(stderr, "Invalid data width %d\n",dmod);
39  return 1;
40  }
41 
42  switch(amod){
43  case 16: atype=atVMEA16; alim = 0xffff; break;
44  case 24: atype=atVMEA24; alim = 0xffffff; break;
45  case 32: atype=atVMEA32; alim = 0xffffffff; break;
46  default:
47  fprintf(stderr, "Invalid address width %d\n",amod);
48  return 1;
49  }
50 
51  dbytes=dmod/8;
52  if(dmod%8)
53  dbytes++;
54  if(dbytes <=0 || dbytes>4){
55  fprintf(stderr, "Invalid data width\n");
56  return 1;
57  }
58 
59  if( (addr > alim) ||
60  (addr+count*dbytes >= alim)) {
61  fprintf(stderr, "Address/count out of range\n");
62  return 1;
63  }
64 
66  atype, addr, mptr
67  ) ){
68  fprintf(stderr, "Invalid register address\n");
69  return 1;
70  }
71 
72  printf("Mapped to %p\n",*mptr);
73 
74  return 0;
75 }
76 
84 void vmeread(int rawaddr, int amod, int dmod, int count)
85 {
86  epicsUInt32 addr = rawaddr;
87  volatile void* mptr;
88  volatile char* dptr;
89  short dbytes;
90  int i, berr = 0;
91 
92  if(count<1) count=1;
93 
94  printf("Reading from 0x%08x A%d D%d\n",addr,amod,dmod);
95 
96  if(validate_widths(addr, amod, dmod, count, &mptr))
97  return;
98 
99  dbytes=dmod/8;
100 
101  for(i=0, dptr=mptr; i<count; i++, dptr+=dbytes) {
102  epicsUInt32 tval = -1;
103  if ((i*dbytes)%16==0)
104  printf("\n0x%08x ",i*dbytes);
105  else if ((i*dbytes)%4==0)
106  printf(" ");
107 
108  berr |= devReadProbe(dbytes, dptr, &tval);
109 
110  switch(dmod){
111  case 8: printf("%02x",(tval>>24)&0xff);break;
112  case 16: printf("%04x",(tval>>16)&0xffff);break;
113  case 32: printf("%08x",tval&0xffffffff);break;
114  default: break; /* excluded by validate_widths() */
115  }
116  }
117  printf("\n");
118  if(berr)
119  fprintf(stderr, "*** Bus errors occurred ***\n");
120 }
121 
122 static const iocshArg vmereadArg0 = { "address",iocshArgInt};
123 static const iocshArg vmereadArg1 = { "amod",iocshArgInt};
124 static const iocshArg vmereadArg2 = { "dmod",iocshArgInt};
125 static const iocshArg vmereadArg3 = { "count",iocshArgInt};
126 static const iocshArg * const vmereadArgs[4] =
127  {&vmereadArg0,&vmereadArg1,&vmereadArg2,&vmereadArg3};
128 static const iocshFuncDef vmereadFuncDef =
129  {"vmeread",4,vmereadArgs};
130 
131 static void vmereadCall(const iocshArgBuf *args)
132 {
133  vmeread(args[0].ival, args[1].ival, args[2].ival, args[3].ival);
134 }
135 
143 void vmewrite(int rawaddr, int amod, int dmod, int rawvalue)
144 {
145  epicsUInt32 addr = rawaddr, value = rawvalue;
146  volatile void* mptr;
147  long err;
148 
149  printf("Writing to 0x%08x A%d D%d value 0x%08x\n",addr,amod,dmod, (unsigned)value);
150 
151  if(validate_widths(addr, amod, dmod, 1, &mptr))
152  return;
153 
154  switch (dmod) {
155  case 8: value<<=24; break;
156  case 16: value<<=16; break;
157  case 32: break;
158  default: break; /* excluded by validate_widths() */
159  }
160 
161  err = devWriteProbe(dmod/8, mptr, &value);
162 
163  if(err)
164  fprintf(stderr, "*** Bus Error detected ***\n");
165 }
166 
167 static const iocshArg vmewriteArg0 = { "address",iocshArgInt};
168 static const iocshArg vmewriteArg1 = { "amod",iocshArgInt};
169 static const iocshArg vmewriteArg2 = { "dmod",iocshArgInt};
170 static const iocshArg vmewriteArg3 = { "count",iocshArgInt};
171 static const iocshArg * const vmewriteArgs[4] =
172  {&vmewriteArg0,&vmewriteArg1,&vmewriteArg2,&vmewriteArg3};
173 static const iocshFuncDef vmewriteFuncDef =
174  {"vmewrite",4,vmewriteArgs};
175 
176 static void vmewriteCall(const iocshArgBuf *args)
177 {
178  vmewrite(args[0].ival, args[1].ival, args[2].ival, args[3].ival);
179 }
180 
181 static volatile epicsUInt8 vmeautodisable[256];
182 
183 static const char hexchars[] = "0123456789ABCDEF";
184 
185 static
186 void vmesh_handler(void *raw)
187 {
188  volatile epicsUInt8 *ent = raw;
189  unsigned char vect = (unsigned char)(ent-vmeautodisable);
190  char msg[] = "VME IRQ on vector 0xXY\n";
191  unsigned I = sizeof(msg)-3;
192 
193  msg[I--] = hexchars[vect&0xf];
194  vect>>=4;
195  msg[I--] = hexchars[vect&0xf];
196  epicsInterruptContextMessage(msg);
197 
198  if(*ent && devDisableInterruptLevelVME(*ent))
199  epicsInterruptContextMessage("oops, can't disable level");
200 }
201 
215 void vmeirqattach(int level, int vector, const char *itype)
216 {
217  int acktype;
218  if(strcmp(itype, "rora")==0) {
219  acktype = 1;
220  } else if(strcmp(itype, "roak")==0) {
221  acktype = 0;
222  } else {
223  fprintf(stderr, "Unknown IRQ ack method '%s' (must be \"rora\" or \"roak\")\n", itype);
224  return;
225  }
226  if(level<1 || level>7) {
227  fprintf(stderr, "IRQ level %d out of range (1-7)\n", level);
228  return;
229  }
230  if(vector>255) {
231  fprintf(stderr, "IRQ vector %d out of range (1-7)\n", vector);
232  return;
233  }
234  if(vmeautodisable[vector]) {
235  fprintf(stderr, "Vector already in use\n");
236  return;
237  }
238  if(acktype)
239  iowrite8(&vmeautodisable[vector], level);
240  if(devConnectInterruptVME(vector, &vmesh_handler, (void*)&vmeautodisable[vector]))
241  fprintf(stderr, "Failed to install ISR\n");
242 }
243 
244 static const iocshArg vmeirqattachArg0 = { "level",iocshArgInt};
245 static const iocshArg vmeirqattachArg1 = { "vector",iocshArgInt};
246 static const iocshArg vmeirqattachArg2 = { "acktype",iocshArgString};
247 static const iocshArg * const vmeirqattachArgs[3] =
248  {&vmeirqattachArg0,&vmeirqattachArg1,&vmeirqattachArg2};
249 static const iocshFuncDef vmeirqattachFuncDef =
250  {"vmeirqattach",3,vmeirqattachArgs};
251 
252 static void vmeirqattachCall(const iocshArgBuf *args)
253 {
254  vmeirqattach(args[0].ival, args[1].ival, args[2].sval);
255 }
256 
262 void vmeirq(int level, int act)
263 {
264  if(level<1 || level>7) {
265  fprintf(stderr, "IRQ level %d out of range (1-7)\n", level);
266  return;
267  }
268  if(act) {
269  if(devEnableInterruptLevelVME(level))
270  fprintf(stderr, "Failed to enable level\n");
271  } else {
272  if(devDisableInterruptLevelVME(level))
273  fprintf(stderr, "Failed to disable level\n");
274  }
275 }
276 
277 static const iocshArg vmeirqArg0 = { "level",iocshArgInt};
278 static const iocshArg vmeirqArg1 = { "en/disable",iocshArgInt};
279 static const iocshArg * const vmeirqArgs[2] =
280  {&vmeirqArg0,&vmeirqArg1};
281 static const iocshFuncDef vmeirqFuncDef =
282  {"vmeirq",2,vmeirqArgs};
283 
284 static void vmeirqCall(const iocshArgBuf *args)
285 {
286  vmeirq(args[0].ival, args[1].ival);
287 }
288 
289 static void vmesh(void)
290 {
291  iocshRegister(&vmereadFuncDef,vmereadCall);
292  iocshRegister(&vmewriteFuncDef,vmewriteCall);
293  iocshRegister(&vmeirqattachFuncDef,vmeirqattachCall);
294  iocshRegister(&vmeirqFuncDef,vmeirqCall);
295 #if EPICS_VERSION==3 && EPICS_REVISION==14 && EPICS_MODIFICATION<10
297 #endif
298 }
299 epicsExportRegistrar(vmesh);
void vmeirqattach(int level, int vector, const char *itype)
Definition: vmesh.c:215
#define devBusToLocalAddr
Definition: devLibVME.h:67
void vmeread(int rawaddr, int amod, int dmod, int count)
Definition: vmesh.c:84
long devDisableInterruptLevelVME(unsigned level)
Definition: devlib_dummy.c:59
epicsExportRegistrar(vmesh)
INLINE void iowrite8(volatile void *addr, epicsUInt8 val)
Write a single byte.
Definition: epicsMMIODef.h:41
void vmeirq(int level, int act)
Definition: vmesh.c:262
void devReplaceVirtualOS(void)
Definition: devlib_compat.c:87
void vmewrite(int rawaddr, int amod, int dmod, int rawvalue)
Definition: vmesh.c:143
long devWriteProbe(unsigned wordSize, volatile void *ptr, const void *pValueWritten)
Definition: devlib_dummy.c:36
long devReadProbe(unsigned wordSize, volatile const void *ptr, void *pValueRead)
Definition: devlib_dummy.c:28