mrfioc2  2.3.0
evgInit.cpp
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) 2015 Paul Scherrer Institute (PSI), Villigen, Switzerland
5 * mrfioc2 is distributed subject to a Software License Agreement found
6 * in file LICENSE that is included with this distribution.
7 \*************************************************************************/
8 
9 #include <iostream>
10 #include <stdexcept>
11 #include <string>
12 #include <sstream>
13 
14 #include <epicsExit.h>
15 #include <epicsThread.h>
16 #include <epicsStdio.h> // redirects stdout/err
17 #include <epicsString.h>
18 
19 #include <iocsh.h>
20 #include <drvSup.h>
21 #include <initHooks.h>
22 #include <errlog.h>
23 
24 #include "mrf/object.h"
25 #include "mrf/databuf.h"
26 #include "mrf/pollirq.h"
27 #include "mrmpci.h"
28 
29 #include <devcsr.h>
30 /* DZ: Does Win32 have a problem with devCSRTestSlot()? */
31 #ifdef _WIN32
32 #define devCSRTestSlot(vmeEvgIDs,slot,info) (NULL)
33 
34 #include <time.h>
35 #endif
36 
37 #include <mrfcsr.h>
38 #include <mrfCommonIO.h>
39 #include <devLibPCI.h>
40 #include "plx9030.h"
41 
42 #include <epicsExport.h>
43 #include "evgRegMap.h"
44 
45 #include "evgInit.h"
46 
47 /* Bit mask used to communicate which VME interrupt levels
48  * are used. Bits are set by mrmEvgSetupVME(). Levels are
49  * enabled later during iocInit.
50  */
51 static epicsUInt8 vme_level_mask = 0;
52 
53 static const
54 struct VMECSRID vmeEvgIDs[] = {
55 /* VME-EVG-230 */
58  VMECSRANY},
59 /* VME-EVM-300 */
62  VMECSRANY},
63 VMECSR_END
64 };
65 
66 static const evgMrm::Config conf_vme_evg_230 = {
67  "VME-EVG-230",
68  2,
69  4,
70  16,
71 };
72 
73 static const evgMrm::Config conf_pci_misc = {
74  "Unknown PCI",
75  2,
76  4,
77  16,
78 };
79 
80 static const evgMrm::Config conf_cpci_evg_220 = {
81  "cPCI-EVG-220",
82  2,
83  4,
84  16,
85 };
86 
87 static const evgMrm::Config conf_cpci_evg_230 = {
88  "cPCI-EVG-230",
89  2,
90  4,
91  16,
92 };
93 
94 static const evgMrm::Config conf_cpci_evg_300 = {
95  "cPCI-EVG-300",
96  2,
97  4,
98  16,
99 };
100 
101 static const evgMrm::Config conf_mtca_evm_300 = {
102  "mTCA-EVM-300",
103  3,
104  16,
105  0,
106 };
107 
108 static bool
109 enableIRQ(mrf::Object* obj, void*) {
110  evgMrm *evg=dynamic_cast<evgMrm*>(obj);
111  if(!evg)
112  return true;
113 
114  evg->enableIRQ();
115 
116  return true;
117 }
118 
119 static bool
120 disableIRQ(mrf::Object* obj, void*)
121 {
122  evgMrm *evg=dynamic_cast<evgMrm*>(obj);
123  if(!evg)
124  return true;
125 
126  BITCLR32(evg->getRegAddr(), IrqEnable, EVG_IRQ_ENABLE);
127  return true;
128 }
129 
130 static void
131 evgShutdown(void*)
132 {
133  mrf::Object::visitObjects(&disableIRQ,0);
134 }
135 
136 static void
137 inithooks(initHookState state) {
138  epicsUInt8 lvl;
139  switch(state) {
140  case initHookAfterInterruptAccept:
141  epicsAtExit(&evgShutdown, NULL);
142  mrf::Object::visitObjects(&enableIRQ, 0);
143  for(lvl=1; lvl<=7; ++lvl) {
144  if (vme_level_mask&(1<<(lvl-1))) {
145  if(devEnableInterruptLevelVME(lvl)) {
146  printf("Failed to enable interrupt level %d\n",lvl);
147  return;
148  }
149  }
150  }
151 
152  break;
153 
154  //Enable interrupts after IOC has been started (this is need for cPCI version)
155  case initHookAtIocRun:
156  epicsAtExit(&evgShutdown, NULL);
157  mrf::Object::visitObjects(&enableIRQ, 0);
158  break;
159 
160  default:
161  break;
162  }
163 }
164 
165 void checkVersion(volatile epicsUInt8 *base, const MRFVersion& required,
166  const MRFVersion& recommended)
167 {
168  epicsUInt32 type;
169  epicsUInt32 v = READ32(base, FPGAVersion);
170 
171  type = v & FPGAVersion_TYPE_MASK;
172  type = v >> FPGAVersion_TYPE_SHIFT;
173 
174  if(type != 0x2)
175  throw std::runtime_error("Address does not correspond to an EVG");
176 
177  MRFVersion ver(v);
178 
179  if(ver < required) {
180  std::ostringstream msg;
181  msg<<"Firmware version >= "<<required<<" is required\n";
182  throw std::runtime_error(msg.str());
183 
184  } else if(ver < recommended) {
185  std::cout<<"Firmware version >= "<<recommended<<" is recommended, please consider upgrading\n";
186  }
187 }
188 
189 extern "C"
190 epicsStatus
192  const char* id, // Card Identifier
193  epicsInt32 slot, // VME slot
194  epicsUInt32 vmeAddress, // Desired VME address in A24 space
195  epicsInt32 irqLevel, // Desired interrupt level
196  epicsInt32 irqVector) // Desired interrupt vector number
197 {
198  volatile epicsUInt8* regCpuAddr = 0;
199  struct VMECSRID info;
200  bus_configuration bus;
201 
202  info.board = 0; info.revision = 0; info.vendor = 0;
203 
204  bus.busType = busType_vme;
205  bus.vme.slot = slot;
206  bus.vme.address = vmeAddress;
207  bus.vme.irqLevel = irqLevel;
208  bus.vme.irqVector = irqVector;
209 
210  try {
211  if(mrf::Object::getObject(id)){
212  printf("ID %s already in use\n",id);
213  return -1;
214  }
215 
216  /*csrCpuAddr is VME-CSR space CPU address for the board*/
217  volatile unsigned char* csrCpuAddr =
218  devCSRTestSlot(vmeEvgIDs,slot,&info);
219 
220  if(!csrCpuAddr) {
221  printf("No EVG in slot %d\n",slot);
222  return -1;
223  }
224 
225  printf("##### Setting up MRF EVG in VME Slot %d #####\n",slot);
226  printf("Found Vendor: %08x\nBoard: %08x\nRevision: %08x\n",
227  info.vendor, info.board, info.revision);
228 
229  epicsUInt32 xxx = CSRRead32(csrCpuAddr + CSR_FN_ADER(1));
230  if(xxx)
231  printf("Warning: EVG not in power on state! (%08x)\n", xxx);
232 
233  /*Setting the base address of Register Map on VME Board (EVG)*/
234  CSRSetBase(csrCpuAddr, 1, vmeAddress, VME_AM_STD_SUP_DATA);
235 
236  {
237  epicsUInt32 temp=CSRRead32((csrCpuAddr) + CSR_FN_ADER(1));
238 
239  if(temp != CSRADER((epicsUInt32)vmeAddress,VME_AM_STD_SUP_DATA)) {
240  printf("Failed to set CSR Base address in ADER1. Check VME bus and card firmware version.\n");
241  return -1;
242  }
243  }
244 
245  /* Create a static string for the card description (needed by vxWorks) */
246  char *Description = allocSNPrintf(40, "EVG-%d '%s' slot %d",
247  info.board & MRF_BID_SERIES_MASK,
248  id, slot);
249 
250  /*Register VME address and get corresponding CPU address */
251  int status = devRegisterAddress (
252  Description, // Event Generator card description
253  atVMEA24, // A24 Address space
254  vmeAddress, // Physical address of register space
255  EVG_REGMAP_SIZE, // Size of card's register space
256  (volatile void **)(void *)&regCpuAddr // Local address of card's register map
257  );
258 
259  if(status) {
260  printf("Failed to map VME address %08x\n", vmeAddress);
261  return -1;
262  }
263 
264  {
265  epicsUInt32 junk;
266  if(devReadProbe(sizeof(junk), (volatile void*)(regCpuAddr+U32_FPGAVersion), (void*)&junk)) {
267  printf("Failed to read from MRM registers (but could read CSR registers)\n");
268  return -1;
269  }
270  }
271  printf("FPGA version: %08x\n", READ32(regCpuAddr, FPGAVersion));
272  checkVersion(regCpuAddr, MRFVersion(0, 3, 0), MRFVersion(0, 3, 0));
273 
274  const evgMrm::Config *conf = &conf_vme_evg_230;
275 
276  printf("%s #Inputs FP:%u UV:%u RB:%u\n", conf->model, conf->numFrontInp,
277  conf->numUnivInp, conf->numRearInp);
278 
279  evgMrm* evg = new evgMrm(id, conf, bus, regCpuAddr, NULL);
280 
281  if(irqLevel > 0 && irqVector >= 0) {
282  /*Configure the Interrupt level and vector on the EVG board*/
283  CSRWrite8(csrCpuAddr + MRF_UCSR_DEFAULT + UCSR_IRQ_LEVEL, irqLevel&0x7);
284  CSRWrite8(csrCpuAddr + MRF_UCSR_DEFAULT + UCSR_IRQ_VECTOR, irqVector&0xff);
285 
286  printf("IRQ Level: %d\nIRQ Vector: %d\n",
287  CSRRead8(csrCpuAddr + MRF_UCSR_DEFAULT + UCSR_IRQ_LEVEL),
288  CSRRead8(csrCpuAddr + MRF_UCSR_DEFAULT + UCSR_IRQ_VECTOR)
289  );
290 
291 
292  printf("csrCpuAddr : %p\nregCpuAddr : %p\n",csrCpuAddr, regCpuAddr);
293 
294  /*Disable the interrupts and enable them at the end of iocInit via initHooks*/
295  WRITE32(regCpuAddr, IrqFlag, READ32(regCpuAddr, IrqFlag));
296  WRITE32(regCpuAddr, IrqEnable, 0);
297 
298  // VME IRQ level will be enabled later during iocInit()
299  vme_level_mask |= 1 << ((irqLevel&0x7)-1);
300 
301  /*Connect Interrupt handler to vector*/
302  if(devConnectInterruptVME(irqVector & 0xff, &evgMrm::isr_vme, evg)){
303  printf("ERROR:Failed to connect VME IRQ vector %d\n"
304  ,irqVector&0xff);
305  delete evg;
306  return -1;
307  }
308  }
309 
310  errlogFlush();
311  return 0;
312  } catch(std::exception& e) {
313  printf("Error: %s\n",e.what());
314  }
315  errlogFlush();
316  return -1;
317 } //mrmEvgSetupVME
318 
319 #ifdef __linux__
320 static char ifaceversion[] = "/sys/module/mrf/parameters/interfaceversion";
321 /* Check the interface version of the kernel module to ensure compatibility */
322 static
323 bool checkUIOVersion(int vmin, int vmax, int *actual)
324 {
325  FILE *fd;
326  int version = -1;
327 
328  fd = fopen(ifaceversion, "r");
329  if(!fd) {
330  printf("Can't open %s in order to read kernel module interface version. Kernel module not loaded or too old.\n", ifaceversion);
331  return true;
332  }
333  if(fscanf(fd, "%d", &version)!=1) {
334  fclose(fd);
335  printf("Failed to read %s in order to get the kernel module interface version.\n", ifaceversion);
336  return true;
337  }
338  fclose(fd);
339 
340  // Interface versions are *not* expected to be backwords or forwards compatible.
341  if(version<vmin || version>vmax) {
342  printf("Error: Expect MRF kernel module interface version between [%d, %d], found %d.\n", vmin, vmax, version);
343  return true;
344  }
345  if(actual)
346  *actual = version;
347  return false;
348 }
349 #else
350 static bool checkUIOVersion(int,int,int*) {return false;}
351 #endif
352 
353 
354 static const epicsPCIID
355 mrmevgs[] = {
358  DEVPCI_DEVICE_VENDOR(PCI_DEVICE_ID_MRF_CPCIEVG300, PCI_VENDOR_ID_MRF),
360  DEVPCI_END
361 };
362 
363 extern "C"
364 epicsStatus
366  const char* id, // Card Identifier
367  const char *spec, // ID spec. or Bus number
368  int d, // Device number
369  int f) // Function number
370 {
371  if(d!=0 || f!=0) {
372  std::istringstream strm(spec);
373  unsigned B =0xf;
374  strm >> B;
375  char buf[40];
376  epicsSnprintf(buf, sizeof(buf), "%x:%x.%x", B, d, f);
377  buf[sizeof(buf)-1] = '\0';
378  spec = epicsStrDup(buf);
379  fprintf(stderr, "Deprecated call. Replace with:\n"
380  " mrmEvgSetupPCI(\"%s\", \"%s\")\n",
381  id, spec);
382  }
383 
384  try {
385  if (mrf::Object::getObject(id)) {
386  printf("ID %s already in use\n", id);
387  return -1;
388  }
389 
390  /* Linux only
391  * kernel driver interface version.
392  * 0 - Broken
393  * 1 - Use of irqcontrol callback to avoid races for plx pci bridges
394  * 2 - Use of new PCI master enable register to avoid races for soft pci bridges
395  */
396  int kifacever = -1;
397  if(checkUIOVersion(1,2,&kifacever))
398  return -1;
399 
400  /* Find PCI device from devLib2 */
401  const epicsPCIDevice *cur = 0;
402  if (devPCIFindSpec(mrmevgs, spec, &cur, 0)) {
403  printf("PCI Device not found\n");
404  return -1;
405  }
406 
407  bus_configuration bus;
408 
409  bus.busType = busType_pci;
410  bus.pci.dev = cur;
411 
412  printf("Device %s %x:%x.%x\n", id, cur->bus, cur->device,
413  cur->function);
414  printf("Using IRQ %u\n", cur->irq);
415 
416  /* MMap BAR0(plx) and BAR2(EVG)*/
417  volatile epicsUInt8 *BAR_plx, *BAR_evg;
418 
419  if (devPCIToLocalAddr(cur, 0, (volatile void**) (void *) &BAR_plx, 0)) {
420  printf("Failed to map BARs 0\n");
421  return -1;
422  }
423  if (!BAR_plx) {
424  printf("BAR0 mapped to zero? (%08lx)\n",
425  (unsigned long) BAR_plx);
426  return -1;
427  }
428 
429  switch(cur->id.device) {
430  case PCI_DEVICE_ID_PLX_9030: /* cPCI-EVG-220 and cPCI-EVG-230 */
431  if (devPCIToLocalAddr(cur, 2, (volatile void**) (void *) &BAR_evg, 0)) {
432  printf("Failed to map BARs 2\n");
433  return -1;
434  }
435  if (!BAR_evg) {
436  printf("BAR2 mapped to zero? (%08lx)\n",
437  (unsigned long) BAR_evg);
438  return -1;
439  }
440 
441 #if EPICS_BYTE_ORDER == EPICS_ENDIAN_BIG
442  BITSET(LE,32, BAR_plx, LAS0BRD, LAS0BRD_ENDIAN);
443 #elif EPICS_BYTE_ORDER == EPICS_ENDIAN_LITTLE
444  BITCLR(LE,32, BAR_plx, LAS0BRD, LAS0BRD_ENDIAN);
445 #endif
446  break;
449  BAR_evg = BAR_plx;
450  /* the endianness the 300 series devices w/o PLX bridge
451  * is a little tricky to setup. byte order swapping is controlled
452  * through the EVR's Control register and access to this register
453  * is subject to byte order swapping...
454  */
455 
456  // Disable EVG and set's byte order to big endian
457  NAT_WRITE32(BAR_evg, Control, 0);
458  // Disable reception, and enable byte order swapping if necessary
459 #if EPICS_BYTE_ORDER == EPICS_ENDIAN_BIG
460  BE_WRITE32(BAR_evg, Control, 0x70000000);
461 #elif EPICS_BYTE_ORDER == EPICS_ENDIAN_LITTLE
462  BE_WRITE32(BAR_evg, Control, 0x72000000);
463 #endif
464 
465  break;
466  default:
467  printf("Unknown/unsupported PCI device 0x%04x\n", (unsigned)cur->device);
468  return -1;
469  }
470 
471  printf("FPGA version: %08x\n", READ32(BAR_evg, FPGAVersion));
472  checkVersion(BAR_evg, MRFVersion(0, 3, 0), MRFVersion(0, 8, 0));
473 
474  /*Disable the interrupts and enable them at the end of iocInit via initHooks*/
475  WRITE32(BAR_evg, IrqFlag, READ32(BAR_evg, IrqFlag));
476  WRITE32(BAR_evg, IrqEnable, 0);
477 
478  const evgMrm::Config *conf = &conf_pci_misc;
479 
480  if(cur->id.device==PCI_DEVICE_ID_MRF_CPCIEVG300) {
481  conf = &conf_cpci_evg_300;
482  } else switch(cur->id.sub_device) {
483  case PCI_SUBDEVICE_ID_MRF_PXIEVG_220: conf = &conf_cpci_evg_220; break;
484  case PCI_DEVICE_ID_MRF_PXIEVG230: conf = &conf_cpci_evg_230; break;
485  case PCI_DEVICE_ID_MRF_MTCA_EVM_300: conf = &conf_mtca_evm_300; break;
486  }
487 
488  printf("%s #Inputs FP:%u UV:%u RB:%u\n", conf->model, conf->numFrontInp,
489  conf->numUnivInp, conf->numRearInp);
490 
491  evgMrm* evg = new evgMrm(id, conf, bus, BAR_evg, cur);
492 
493  MRFVersion ver(evg->version());
494 
495 #if !defined(__linux__) && !defined(_WIN32)
496  if(cur->id.device==PCI_DEVICE_ID_PLX_9030) {
497  // Enable active high interrupt1 through the PLX to the PCI bus.
499  }
500  if(ver>=MRFVersion(0, 8, 0)) {
501  // RTOS doesn't need this, so always enable
502  WRITE32(BAR_evg, PCI_MIE, EVG_MIE_ENABLE);
503  }
504 #else
505  if(ver>=MRFVersion(0, 8, 0) && kifacever>=2) {
506  // PCI master enable supported by firmware and kernel module.
507  // the kernel will set this bit when devPCIEnableInterrupt() is called
508  } else if(cur->id.device==PCI_DEVICE_ID_PLX_9030) {
509  // PLX based devices don't need special handling
510  WRITE32(BAR_evg, PCI_MIE, EVG_MIE_ENABLE);
511  } else if(ver<MRFVersion(0, 8, 0)) {
512  // old firmware and (maybe) old kernel module.
513  // this will still work, so just complain
514  printf("Warning: this configuration of FW and SW is known to have race conditions in interrupt handling.\n"
515  " Please consider upgrading to FW version 8.\n");
516  if(kifacever<2)
517  printf(" Also upgrade the linux kernel module to interface version 2.");
518  } else if(ver>=MRFVersion(0, 8, 0) && kifacever<2) {
519  // New firmware w/ old kernel module, this won't work
520  throw std::runtime_error("FW version 8 for this device requires a linux kernel module w/ interface version 2");
521  } else {
522  throw std::logic_error("logic error in FW/kernel module compatibility check.");
523  }
524  if(devPCIEnableInterrupt(cur)) {
525  printf("Failed to enable interrupt\n");
526  return -1;
527  }
528 #endif
529 
530  int ret;
531  /*Connect Interrupt handler to isr thread*/
532  if ((ret=devPCIConnectInterrupt(cur, &evgMrm::isr_pci, (void*) evg, 0))!=0) {
533  char buf[80];
534  errSymLookup(ret, buf, sizeof(buf));
535  printf("ERROR:Failed to connect PCI interrupt. err (%d) %s\n", ret, buf);
536  delete evg;
537  return -1;
538  } else {
539  printf("PCI interrupt connected!\n");
540  }
541 
542  return 0;
543 
544  } catch (std::exception& e) {
545  printf("Error: %s\n", e.what());
546  }
547  return -1;
548 } //mrmEvgSetupPCI
549 
550 static const iocshArg mrmEvgSetupVMEArg0 = { "Card ID", iocshArgString };
551 static const iocshArg mrmEvgSetupVMEArg1 = { "Slot number", iocshArgInt };
552 static const iocshArg mrmEvgSetupVMEArg2 = { "A24 base address", iocshArgInt };
553 static const iocshArg mrmEvgSetupVMEArg3 = { "IRQ Level 1-7 (0 - disable)",
554  iocshArgInt };
555 static const iocshArg mrmEvgSetupVMEArg4 = { "IRQ Vector 0-255", iocshArgInt };
556 static const iocshArg * const mrmEvgSetupVMEArgs[5] = { &mrmEvgSetupVMEArg0,
557  &mrmEvgSetupVMEArg1,
558  &mrmEvgSetupVMEArg2,
559  &mrmEvgSetupVMEArg3,
560  &mrmEvgSetupVMEArg4 };
561 
562 static const iocshFuncDef mrmEvgSetupVMEFuncDef = { "mrmEvgSetupVME", 5,
563  mrmEvgSetupVMEArgs };
564 
565 static void
566 mrmEvgSetupVMECallFunc(const iocshArgBuf *args) {
567  mrmEvgSetupVME(args[0].sval,
568  args[1].ival,
569  args[2].ival,
570  args[3].ival,
571  args[4].ival);
572 }
573 
574 static const iocshArg mrmEvgSetupPCIArg0 = { "Card ID", iocshArgString };
575 static const iocshArg mrmEvgSetupPCIArg1 = { "spec or B board", iocshArgString };
576 static const iocshArg mrmEvgSetupPCIArg2 = { "D device", iocshArgInt };
577 static const iocshArg mrmEvgSetupPCIArg3 = { "F function", iocshArgInt };
578 
579 static const iocshArg * const mrmEvgSetupPCIArgs[4] = { &mrmEvgSetupPCIArg0,
580  &mrmEvgSetupPCIArg1, &mrmEvgSetupPCIArg2, &mrmEvgSetupPCIArg3 };
581 
582 static const iocshFuncDef mrmEvgSetupPCIFuncDef = { "mrmEvgSetupPCI", 4,
583  mrmEvgSetupPCIArgs };
584 
585 static void mrmEvgSetupPCICallFunc(const iocshArgBuf *args) {
586  mrmEvgSetupPCI(args[0].sval, args[1].sval, args[2].ival, args[3].ival);
587 
588 }
589 
590 extern "C"{
591 static void evgMrmRegistrar() {
592  initHookRegister(&inithooks);
593  iocshRegister(&mrmEvgSetupVMEFuncDef, mrmEvgSetupVMECallFunc);
594  iocshRegister(&mrmEvgSetupPCIFuncDef, mrmEvgSetupPCICallFunc);
595 }
596 
597 epicsExportRegistrar(evgMrmRegistrar);
598 }
599 
600 /*
601  * EPICS Driver Support for this module
602  */
603 static const
604 struct printreg {
605  char label[18];
606  epicsUInt32 offset;
607  int rsize;
608 } printreg[] = {
609 #define REGINFO(label, name, size) {label, U##size##_##name, size}
610  REGINFO("Status", Status, 32),
611  REGINFO("Control", Control, 32),
612  REGINFO("IrqFlag", IrqFlag, 32),
613  REGINFO("IrqEnable", IrqEnable, 32),
614  REGINFO("AcTrigControl", AcTrigControl, 32),
615  REGINFO("AcTrigMap", AcTrigMap, 32),
616  REGINFO("SwEvent", SwEvent, 32),
617  REGINFO("DataBufferControl",DataBufferControl,32),
618  REGINFO("DBusSrc", DBusSrc, 32),
619  REGINFO("FPGAVersion", FPGAVersion, 32),
620  REGINFO("ClockControl", ClockControl, 32),
621  REGINFO("SeqControl(0)", SeqControl(0), 32),
622  REGINFO("SeqControl(1)", SeqControl(1), 32),
623  REGINFO("FracSynthWord", FracSynthWord, 32),
624  REGINFO("TrigEventCtrl(0)", TrigEventCtrl(0), 32),
625  REGINFO("TrigEventCtrl(1)", TrigEventCtrl(1), 32),
626  REGINFO("TrigEventCtrl(2)", TrigEventCtrl(2), 32),
627  REGINFO("TrigEventCtrl(3)", TrigEventCtrl(3), 32),
628  REGINFO("TrigEventCtrl(4)", TrigEventCtrl(4), 32),
629  REGINFO("TrigEventCtrl(5)", TrigEventCtrl(5), 32),
630  REGINFO("TrigEventCtrl(6)", TrigEventCtrl(6), 32),
631  REGINFO("TrigEventCtrl(7)", TrigEventCtrl(7), 32),
632  REGINFO("MuxControl(0)", MuxControl(0), 32),
633  REGINFO("MuxPrescaler(0)", MuxPrescaler(0), 32),
634  REGINFO("MuxControl(1)", MuxControl(1), 32),
635  REGINFO("MuxPrescaler(1)", MuxPrescaler(1), 32),
636  REGINFO("MuxControl(2)", MuxControl(2), 32),
637  REGINFO("MuxPrescaler(2)", MuxPrescaler(2), 32),
638  REGINFO("MuxControl(3)", MuxControl(3), 32),
639  REGINFO("MuxPrescaler(3)", MuxPrescaler(3), 32),
640  REGINFO("MuxControl(4)", MuxControl(4), 32),
641  REGINFO("MuxPrescaler(4)", MuxPrescaler(4), 32),
642  REGINFO("MuxControl(5)", MuxControl(5), 32),
643  REGINFO("MuxPrescaler(5)", MuxPrescaler(5), 32),
644  REGINFO("MuxControl(6)", MuxControl(6), 32),
645  REGINFO("MuxPrescaler(6)", MuxPrescaler(6), 32),
646  REGINFO("MuxControl(7)", MuxControl(7), 32),
647  REGINFO("MuxPrescaler(7)", MuxPrescaler(7), 32),
648  REGINFO("FrontOutMap(0)", FrontOutMap(0), 16),
649  REGINFO("FrontInMap(0)", FrontInMap(0), 32),
650  REGINFO("FrontInMap(1)", FrontInMap(1), 32),
651  REGINFO("UnivInMap(0)", UnivInMap(0), 32),
652  REGINFO("UnivInMap(1)", UnivInMap(1), 32),
653  REGINFO("RearInMap(12)", RearInMap(12), 32),
654  REGINFO("RearInMap(13)", RearInMap(13), 32),
655  REGINFO("RearInMap(14)", RearInMap(14), 32),
656  REGINFO("RearInMap(15)", RearInMap(15), 32),
657  REGINFO("DataBuffer(0)", DataBuffer(0), 8),
658  REGINFO("DataBuffer(1)", DataBuffer(1), 8),
659  REGINFO("DataBuffer(2)", DataBuffer(2), 8),
660  REGINFO("DataBuffer(3)", DataBuffer(3), 8),
661  REGINFO("DataBuffer(4)", DataBuffer(4), 8),
662  REGINFO("DataBuffer(5)", DataBuffer(5), 8),
663  REGINFO("SeqRamTS(0,0)", SeqRamTS(0,0), 32),
664  REGINFO("SeqRamTS(0,1)", SeqRamTS(0,1), 32),
665  REGINFO("SeqRamTS(0,2)", SeqRamTS(0,2), 32),
666  REGINFO("SeqRamTS(0,3)", SeqRamTS(0,3), 32),
667  REGINFO("SeqRamTS(0,4)", SeqRamTS(0,4), 32),
668  REGINFO("SeqRamEvent(0,0)", SeqRamEvent(0,0), 32),
669  REGINFO("SeqRamEvent(0,1)", SeqRamEvent(0,1), 32),
670  REGINFO("SeqRamEvent(0,2)", SeqRamEvent(0,2), 32),
671  REGINFO("SeqRamEvent(0,3)", SeqRamEvent(0,3), 32),
672  REGINFO("SeqRamEvent(0,4)", SeqRamEvent(0,4), 32),
673  REGINFO("SeqRamTS(1,0)", SeqRamTS(1,0), 32),
674  REGINFO("SeqRamTS(1,1)", SeqRamTS(1,1), 32),
675  REGINFO("SeqRamTS(1,2)", SeqRamTS(1,2), 32),
676  REGINFO("SeqRamTS(1,3)", SeqRamTS(1,3), 32),
677  REGINFO("SeqRamTS(1,4)", SeqRamTS(1,4), 32),
678  REGINFO("SeqRamEvent(1,0)", SeqRamEvent(1,0), 32),
679  REGINFO("SeqRamEvent(1,1)", SeqRamEvent(1,1), 32),
680  REGINFO("SeqRamEvent(1,2)", SeqRamEvent(1,2), 32),
681  REGINFO("SeqRamEvent(1,3)", SeqRamEvent(1,3), 32),
682  REGINFO("SeqRamEvent(1,4)", SeqRamEvent(1,4), 32),
683 #undef REGINFO
684 };
685 
686 
687 static void
688 printregisters(volatile epicsUInt8 *evg) {
689  size_t reg;
690  printf("\n--- Register Dump @%p ---\n", evg);
691 
692  for(reg=0; reg<NELEMENTS(printreg); reg++){
693  switch(printreg[reg].rsize){
694  case 8:
695  printf("%16s: %02x\n", printreg[reg].label,
696  ioread8(evg+printreg[reg].offset));
697  break;
698  case 16:
699  printf("%16s: %04x\n", printreg[reg].label,
700  nat_ioread16(evg+printreg[reg].offset));
701  break;
702  case 32:
703  printf("%16s: %08x\n", printreg[reg].label,
704  nat_ioread32(evg+printreg[reg].offset));
705  break;
706  }
707  }
708 }
709 
710 static bool
711 reportCard(mrf::Object* obj, void* arg) {
712  int *level=(int*)arg;
713  evgMrm *evg=dynamic_cast<evgMrm*>(obj);
714  if(!evg)
715  return true;
716 
717  printf("EVG: %s \n", evg->getId().c_str());
718  printf("\tFPGA Version: %s\n", evg->getFwVersionStr().c_str());
719 
720  const bus_configuration *bus = evg->getBusConfiguration();
721  if(bus->busType == busType_vme){
722  struct VMECSRID vmeDev;
723  vmeDev.board = 0; vmeDev.revision = 0; vmeDev.vendor = 0;
724  volatile unsigned char* csrAddr = devCSRTestSlot(vmeEvgIDs, bus->vme.slot, &vmeDev);
725  if(csrAddr){
726  epicsUInt32 ader = CSRRead32(csrAddr + CSR_FN_ADER(1));
727  printf("\tVME configured slot: %d\n", bus->vme.slot);
728  printf("\tVME configured A24 address 0x%08x\n", bus->vme.address);
729  printf("\tVME ADER: base address=0x%x\taddress modifier=0x%x\n", ader>>8, (ader&0xFF)>>2);
730  printf("\tVME IRQ Level %d (configured to %d)\n", CSRRead8(csrAddr + MRF_UCSR_DEFAULT + UCSR_IRQ_LEVEL), bus->vme.irqLevel);
731  printf("\tVME IRQ Vector %d (configured to %d)\n", CSRRead8(csrAddr + MRF_UCSR_DEFAULT + UCSR_IRQ_VECTOR), bus->vme.irqVector);
732  if(*level>1) printf("\tVME card vendor: 0x%08x\n", vmeDev.vendor);
733  if(*level>1) printf("\tVME card board: 0x%08x\n", vmeDev.board);
734  if(*level>1) printf("\tVME card revision: 0x%08x\n", vmeDev.revision);
735  if(*level>1) printf("\tVME CSR address: %p\n", csrAddr);
736  }else{
737  printf("\tCard not detected in configured slot %d\n", bus->vme.slot);
738  }
739  }
740  else if(bus->busType == busType_pci){
741  const epicsPCIDevice *pciDev = bus->pci.dev;
742  printf("\tPCI configured bus: 0x%08x\n", pciDev->bus);
743  printf("\tPCI configured device: 0x%08x\n", pciDev->device);
744  printf("\tPCI configured function: 0x%08x\n", pciDev->function);
745  printf("\tPCI in slot: %s\n", pciDev->slot ? pciDev->slot : "<N/A>");
746  printf("\tPCI IRQ: %u\n", pciDev->irq);
747 
748  }else{
749  printf("\tUnknown bus type\n");
750  }
751 
752  evg->show(*level);
753 
754  if(*level >= 2)
755  printregisters(evg->getRegAddr());
756 
757  printf("\n");
758  return true;
759 }
760 
761 static long
762 report(int level) {
763  printf("=== Begin MRF EVG support ===\n");
764  mrf::Object::visitObjects(&reportCard, (void*)&level);
765  printf("=== End MRF EVG support ===\n");
766  return 0;
767 }
768 extern "C"{
769 static
770 drvet drvEvgMrm = {
771  2,
772  (DRVSUPFUN)report,
773  NULL
774 };
775 epicsExportAddress (drvet, drvEvgMrm);
776 }
std::string getFwVersionStr() const
Definition: evgMrm.cpp:228
enum busType busType
#define PCI_DEVICE_ID_MRF_MTCA_EVM_300
Definition: uio_mrf.c:67
#define BITCLR(ord, len, base, offset, mask)
Definition: mrfBitOps.h:26
static void isr_vme(void *)
Definition: evgMrm.cpp:299
#define REGINFO(label, name, size)
#define LE_WRITE16(base, offset, value)
Definition: mrfCommonIO.h:199
#define READ32(base, offset)
Definition: mrfCommonIO.h:114
void show(int lvl)
Definition: evgMrm.cpp:434
#define LAS0BRD
Definition: mrf.h:41
unsigned numUnivInp
Definition: evgMrm.h:63
Definition: evrdump.c:37
#define BE_WRITE32(base, offset, value)
Definition: mrfCommonIO.h:170
#define EVG_REGMAP_SIZE
Definition: evgRegMap.h:242
#define PCI_VENDOR_ID_PLX
Definition: plx9030.h:37
#define MRF_VME_EVM_BID
Definition: mrfcsr.h:20
volatile epicsUInt8 * getRegAddr() const
Definition: evgMrm.cpp:219
#define PCI_VENDOR_ID_XILINX
Definition: mrmpci.h:14
INLINE epicsUInt8 ioread8(volatile void *addr)
Definition: mrfIoOpsDef.h:20
INLINE epicsUInt32 nat_ioread32(volatile void *addr)
Definition: mrfIoOpsDef.h:48
Base object inspection.
Definition: object.h:378
#define MRF_UCSR_DEFAULT
Definition: evgInit.h:11
#define UCSR_IRQ_LEVEL
Definition: mrfcsr.h:59
#define MRF_BID_SERIES_MASK
Definition: mrfcsr.h:31
#define U32_FPGAVersion
Definition: evgRegMap.h:102
#define PCI_DEVICE_ID_MRF_CPCIEVG300
Definition: mrmpci.h:49
char * allocSNPrintf(size_t N, const char *fmt,...)
Definition: mrfCommon.cpp:59
#define MRF_VME_EVG_BID
Definition: mrfcsr.h:17
static Object * getObject(const std::string &name)
Definition: object.cpp:107
static void visitObjects(bool(*)(Object *, void *), void *)
Definition: object.cpp:150
#define BITCLR32(base, offset, mask)
Definition: mrfCommonIO.h:129
epicsExportRegistrar(evgMrmRegistrar)
epicsStatus mrmEvgSetupPCI(const char *id, const char *spec, int d, int f)
Definition: evgInit.cpp:365
#define PCI_DEVICE_ID_XILINX_DEV
Definition: uio_mrf.c:48
#define PCI_VENDOR_ID_MRF
Definition: uio_mrf.c:41
INLINE epicsUInt16 nat_ioread16(volatile void *addr)
Definition: mrfIoOpsDef.h:34
#define FPGAVersion
Definition: mrf.h:133
const bus_configuration * getBusConfiguration()
Definition: evgMrm.cpp:429
DEVSUPFUN report
epicsExportAddress(drvet, drvEvgMrm)
struct configuration_pci pci
void enableIRQ()
Definition: evgMrm.cpp:192
#define EVG_IRQ_ENABLE
Definition: evgRegMap.h:51
const epicsPCIDevice * dev
#define LAS0BRD_ENDIAN
Definition: plx9030.h:24
#define FPGAVersion_TYPE_SHIFT
Definition: evgRegMap.h:107
#define MRF_VME_IEEE_OUI
Definition: mrfcsr.h:15
#define INTCSR_INT1_Polarity
Definition: plx9030.h:29
#define PCI_SUBDEVICE_ID_MRF_PXIEVG_220
Definition: uio_mrf.c:58
#define EVG_MIE_ENABLE
Definition: evgRegMap.h:64
#define NAT_WRITE32(base, offset, value)
Definition: mrfCommonIO.h:148
#define INTCSR
Definition: mrf.h:46
#define BITSET(ord, len, base, offset, mask)
Definition: mrfBitOps.h:21
const std::string getId() const
Definition: evgMrm.cpp:214
#define UCSR_IRQ_VECTOR
Definition: mrfcsr.h:60
void checkVersion(volatile epicsUInt8 *base, const MRFVersion &required, const MRFVersion &recommended)
Definition: evgInit.cpp:165
#define MRF_SERIES_230
Definition: mrfCommon.h:156
static void isr_pci(void *)
Definition: evgMrm.cpp:280
unsigned numFrontInp
Definition: evgMrm.h:63
const char * model
Definition: evgMrm.h:62
#define WRITE32(base, offset, value)
Definition: mrfCommonIO.h:119
epicsStatus mrmEvgSetupVME(const char *id, epicsInt32 slot, epicsUInt32 vmeAddress, epicsInt32 irqLevel, epicsInt32 irqVector)
Definition: evgInit.cpp:191
#define PCI_DEVICE_ID_MRF_PXIEVG230
Definition: mrmpci.h:45
#define PCI_DEVICE_ID_PLX_9030
Definition: uio_mrf.c:50
Definition: evgMrm.h:56
#define INTCSR_INT1_Enable
Definition: plx9030.h:28
#define INTCSR_PCI_Enable
Definition: plx9030.h:34
#define FPGAVersion_TYPE_MASK
Definition: evgRegMap.h:104
MRFVersion version() const
Definition: evgMrm.cpp:223
unsigned numRearInp
Definition: evgMrm.h:63