mrfioc2  2.3.0
drvemSetup.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  * Author: Michael Davidsaver <mdavidsaver@gmail.com>
10  */
11 
12 #include <cstdio>
13 #include <cstring>
14 
15 #include <stdexcept>
16 #include <sstream>
17 #include <map>
18 
19 #include <epicsString.h>
20 #include <epicsStdio.h> /* redirects stdout/err */
21 #include <drvSup.h>
22 #include <iocsh.h>
23 #include <initHooks.h>
24 #include <epicsExit.h>
25 #include <errlog.h>
26 
27 #include <devLibPCI.h>
28 #include <devcsr.h>
29 #include <epicsInterrupt.h>
30 #include <epicsThread.h>
31 #include <mrfCommonIO.h>
32 #include <mrfBitOps.h>
33 
34 #include "drvem.h"
35 #include "mrfcsr.h"
36 #include "mrmpci.h"
37 
38 #include <epicsExport.h>
39 
40 #include "drvemIocsh.h"
41 
42 // for htons() et al.
43 #ifdef _WIN32
44  #include <Winsock2.h>
45 #endif
46 
47 #include "evrRegMap.h"
48 #include "plx9030.h"
49 #include "plx9056.h"
50 #include "latticeEC30.h"
51 
52 #ifdef _WIN32
53  #define strtok_r(strToken,strDelimit,lasts ) (*(lasts) = strtok((strToken),(strDelimit)))
54 #endif
55 
56 /* Bit mask used to communicate which VME interrupt levels
57  * are used. Bits are set by mrmEvrSetupVME(). Levels are
58  * enabled later during iocInit.
59  */
60 static epicsUInt8 vme_level_mask = 0;
61 
62 static const epicsPCIID mrmevrs[] = {
63  /* PMC-EVR-230 */
64  DEVPCI_SUBDEVICE_SUBVENDOR(PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_PLX,
66  /* PXI-EVR-230 */
67  ,DEVPCI_SUBDEVICE_SUBVENDOR(PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_PLX,
69  /* cPCI-EVRTG-300 */
70  ,DEVPCI_SUBDEVICE_SUBVENDOR(PCI_DEVICE_ID_PLX_9056, PCI_VENDOR_ID_PLX,
72  /* cPCI-EVRTG-300E ?? PCIe-EVR-300 */
73  ,DEVPCI_SUBDEVICE_SUBVENDOR(PCI_DEVICE_ID_EC_30, PCI_VENDOR_ID_LATTICE,
75  /* cPCI-EVR-300 */
76  ,DEVPCI_DEVICE_VENDOR(PCI_DEVICE_ID_MRF_CPCIEVR300, PCI_VENDOR_ID_MRF)
77  /* mTCA-EVR-300 */
78  ,DEVPCI_SUBDEVICE_SUBVENDOR(PCI_DEVICE_ID_XILINX_DEV, PCI_VENDOR_ID_XILINX,
80  /* PCIe-EVR-300DC */
81  ,DEVPCI_SUBDEVICE_SUBVENDOR(PCI_DEVICE_ID_XILINX_DEV, PCI_VENDOR_ID_XILINX,
83  ,DEVPCI_END
84 };
85 
86 static const struct VMECSRID vmeevrs[] = {
87  // VME-EVR-230 and VME-EVRRF-230
89  ,VMECSR_END
90 };
91 
92 static const EVRMRM::Config cpci_evr_230 = {
93  "cPCI-EVR-230",
94  10, // pulse generators
95  3, // prescalers
96  0, // FP outputs
97  4, // FPUV outputs
98  0, // RB outputs
99  0, // Backplane outputs
100  2, // FP Delay outputs
101  0, // CML/GTX outputs
103  2, // FP inputs
104 };
105 
106 static const EVRMRM::Config pmc_evr_230 = {
107  "PMC-EVR-230",
108  10, // pulse generators
109  3, // prescalers
110  3, // FP outputs
111  0, // FPUV outputs
112  10, // RB outputs
113  0, // Backplane outputs
114  0, // FP Delay outputs
115  0, // CML/GTX outputs
117  1, // FP inputs
118 };
119 
120 static const EVRMRM::Config pcie_evr_230 = {
121  "PCIe-EVR-230",
122  10, // pulse generators
123  3, // prescalers
124  0, // FP outputs
125  16, // FPUV outputs
126  0, // RB outputs
127  0, // Backplane outputs
128  0, // FP Delay outputs
129  0, // CML/GTX outputs
131  0, // FP inputs
132 };
133 
134 static const EVRMRM::Config vme_evrrf_230 = { // no way to distinguish RF and non-RF variants
135  "VME-EVRRF-230",
136  16, // pulse generators
137  3, // prescalers
138  8, // FP outputs
139  4, // FPUV outputs
140  16, // RB outputs
141  0, // Backplane outputs
142  2, // FP Delay outputs
143  3, // CML/GTX outputs
145  2, // FP inputs
146 };
147 
148 static const EVRMRM::Config cpci_evrtg_300 = {
149  "cPCI-EVRTG-300",
150  10, // pulse generators
151  3, // prescalers
152  0, // FP outputs
153  4, // FPUV outputs
154  0, // RB outputs
155  0, // Backplane outputs
156  0, // FP Delay outputs
157  4, // CML/GTX outputs
159  0, // FP inputs
160 };
161 
162 static const EVRMRM::Config cpci_evr_300 = {
163  "cPCI-EVR-300",
164  14, // pulse generators
165  3, // prescalers
166  0, // FP outputs
167  12, // FPUV outputs
168  0, // RB outputs
169  0, // Backplane outputs
170  0, // FP Delay outputs
171  4, // CML/GTX outputs
173  2, // FP inputs
174 };
175 
176 static const EVRMRM::Config mtca_evr_300 = {
177  "mTCA-EVR-300",
178  16, // pulse generators
179  8, // prescalers
180  4, // FP outputs
181  0, // FPUV outputs (really 2, handled specially)
182  16, // RB outputs (via external IFB)
183  8, // Backplane outputs
184  2, // FP Delay outputs
185  0, // CML/GTX outputs
192  32, // FP, Univ, BP inputs
193 };
194 
195 static const EVRMRM::Config pcie_evr_300 = {
196  "PCIe-EVR-300DC",
197  16, // pulse generators
198  8, // prescalers
199  0, // FP outputs
200  16, // FPUV outputs (via external IFB)
201  0, // RB outputs
202  0, // Backplane outputs
203  0, // FP Delay outputs
204  0, // CML/GTX outputs
210  24, // FP, Univ inputs
211 };
212 
213 static const EVRMRM::Config cpci_evr_unknown = {
214  "cPCI-EVR-???",
215  10, // pulse generators
216  3, // prescalers
217  1, // FP outputs
218  2, // FPUV outputs
219  1, // RB outputs
220  1, // Backplane outputs
221  1, // FP Delay outputs
222  1, // CML/GTX outputs
224  1, // FP inputs
225 };
226 
227 static
228 const
229 struct printreg
230 {
231  const char *label;
232  epicsUInt32 offset;
233  int rsize;
234 } printreg[] = {
235 #define REGINFO(label, name, size) {label, U##size##_##name, size}
236 REGINFO("Version", FWVersion, 32),
237 REGINFO("Control", Control, 32),
238 REGINFO("Status", Status, 32),
239 REGINFO("IRQ Flag",IRQFlag, 32),
240 REGINFO("IRQ Ena", IRQEnable, 32),
241 REGINFO("PCIMIE", PCI_MIE, 32),
242 REGINFO("IRQPlsmap",IRQPulseMap, 32),
243 REGINFO("DBufCtrl",DataBufCtrl, 32),
244 REGINFO("DBufTxCt",DataTxCtrl, 32),
245 REGINFO("CountPS", CounterPS, 32),
246 REGINFO("USecDiv", USecDiv, 32),
247 REGINFO("ClkCtrl", ClkCtrl, 32),
248 REGINFO("LogSts", LogStatus, 32),
249 REGINFO("TSSec",TSSec, 32),
250 REGINFO("TSEvt",TSEvt, 32),
251 REGINFO("TSSecLath",TSSecLatch, 32),
252 REGINFO("TSEvtLath",TSEvtLatch, 32),
253 REGINFO("FracDiv", FracDiv, 32),
254 REGINFO("Scaler0",Scaler(0),32),
255 REGINFO("Pul0Ctrl",PulserCtrl(0),32),
256 REGINFO("Pul0Scal",PulserScal(0),32),
257 REGINFO("Pul0Dely",PulserDely(0),32),
258 REGINFO("Pul0Wdth",PulserWdth(0),32),
259 REGINFO("FP01MAP",OutputMapFP(0),32),
260 REGINFO("FPU01MAP",OutputMapFPUniv(0),32),
261 REGINFO("RB01MAP",OutputMapRB(0),32),
262 REGINFO("FPIN0",InputMapFP(0),32),
263 REGINFO("CML4Low",OutputCMLLow(0),32),
264 REGINFO("CML4Rise",OutputCMLRise(0),32),
265 REGINFO("CML4High",OutputCMLHigh(0),32),
266 REGINFO("CML4Fall",OutputCMLFall(0),32),
267 REGINFO("CML4Ena",OutputCMLEna(0),32),
268 REGINFO("CML4Cnt",OutputCMLCount(0),32),
269 REGINFO("CML4Len",OutputCMLPatLength(0),32),
270 REGINFO("CML4Pat0",OutputCMLPat(0,0),32),
271 REGINFO("CML4Pat1",OutputCMLPat(0,1),32),
272 REGINFO("TXBuf0-3",DataTx(0),32),
273 REGINFO("RXBuf0-3",DataRx(0),32)
274 #undef REGINFO
275 };
276 
277 static
278 void
279 printregisters(volatile epicsUInt8 *evr,epicsUInt32 len)
280 {
281  size_t reg;
282 
283  printf("EVR register dump\n");
284  for(reg=0; reg<NELEMENTS(printreg); reg++){
285 
286  if(printreg[reg].offset+printreg[reg].rsize/8 > len)
287  continue;
288 
289  switch(printreg[reg].rsize){
290  case 8:
291  printf("%9s: %02x\n",
292  printreg[reg].label,
293  ioread8(evr+printreg[reg].offset));
294  break;
295  case 16:
296  printf("%9s: %04x\n",
297  printreg[reg].label,
298  nat_ioread16(evr+printreg[reg].offset));
299  break;
300  case 32:
301  printf("%9s: %08x\n",
302  printreg[reg].label,
303  nat_ioread32(evr+printreg[reg].offset));
304  break;
305  }
306  }
307 }
308 
309 static
310 bool reportCard(mrf::Object* obj, void* raw)
311 {
312  int *level=(int*)raw;
313  EVRMRM *evr=dynamic_cast<EVRMRM*>(obj);
314  if(!evr)
315  return true;
316 
317  printf("EVR: %s\n",obj->name().c_str());
318  printf("\tFPGA Version: %08x (firmware: %s)\n", evr->fpgaFirmware(), evr->versionStr().c_str());
319  printf("\tForm factor: %s\n", evr->formFactorStr().c_str());
320  printf("\tClock: %.6f MHz\n",evr->clock()*1e-6);
321 
323  if(bus->busType == busType_vme){
324  struct VMECSRID vmeDev;
325  volatile unsigned char* csrAddr = devCSRTestSlot(vmeevrs, bus->vme.slot, &vmeDev);
326  if(csrAddr){
327  epicsUInt32 ader = CSRRead32(csrAddr + CSR_FN_ADER(2));
328  size_t user_offset=CSRRead24(csrAddr+CR_BEG_UCSR);
329  // Currently that value read from the UCSR pointer is
330  // actually little endian.
331  user_offset= (( user_offset & 0x00ff0000 ) >> 16 ) |
332  (( user_offset & 0x0000ff00 ) ) |
333  (( user_offset & 0x000000ff ) << 16 );
334 
335  printf("\tVME configured slot: %d\n", bus->vme.slot);
336  printf("\tVME configured A24 address 0x%08x\n", bus->vme.address);
337  printf("\tVME ADER: base address=0x%x\taddress modifier=0x%x\n", ader>>8, (ader&0xFF)>>2);
338  printf("\tVME IRQ Level %d (configured to %d)\n", CSRRead8(csrAddr + user_offset + UCSR_IRQ_LEVEL), bus->vme.irqLevel);
339  printf("\tVME IRQ Vector %d (configured to %d)\n", CSRRead8(csrAddr + user_offset + UCSR_IRQ_VECTOR), bus->vme.irqVector);
340  if(*level>1) printf("\tVME card vendor: 0x%08x\n", vmeDev.vendor);
341  if(*level>1) printf("\tVME card board: 0x%08x\n", vmeDev.board);
342  if(*level>1) printf("\tVME card revision: 0x%08x\n", vmeDev.revision);
343  if(*level>1) printf("\tVME CSR address: %p\n", csrAddr);
344  }else{
345  printf("\tCard not detected in configured slot %d\n", bus->vme.slot);
346  }
347  }
348  else if(bus->busType == busType_pci){
349  const epicsPCIDevice *pciDev = bus->pci.dev;
350  printf("\tPCI configured bus: 0x%08x\n", pciDev->bus);
351  printf("\tPCI configured device: 0x%08x\n", pciDev->device);
352  printf("\tPCI configured function: 0x%08x\n", pciDev->function);
353  printf("\tPCI in slot: %s\n", pciDev->slot ? pciDev->slot : "<N/A>");
354  printf("\tPCI IRQ: %u\n", pciDev->irq);
355 
356  }else{
357  printf("\tUnknown bus type\n");
358  }
359 
360  if(*level>=2){
361  printregisters(evr->base, evr->baselen);
362  }
363  if(*level>=1 && evr->sfp.get()){
364  evr->sfp->updateNow();
365  evr->sfp->report();
366  }
367 
368  return true;
369 }
370 
371 long mrmEvrReport(int level)
372 {
373  printf("=== Begin MRF EVR support ===\n");
374  mrf::Object::visitObjects(&reportCard, (void*)&level);
375  printf("=== End MRF EVR support ===\n");
376  return 0;
377 }
378 
379 static
380 void checkVersion(volatile epicsUInt8 *base, unsigned int required, unsigned int recommended)
381 {
382  epicsUInt32 v = READ32(base, FWVersion);
383 
384  printf("FWVersion 0x%08x\n", v);
385 
386  epicsUInt32 evr=v&FWVersion_type_mask;
387  evr>>=FWVersion_type_shift;
388 
389  if(evr!=0x1)
390  throw std::runtime_error("Firmware does not correspond to an EVR");
391 
392  epicsUInt32 ver=(v&FWVersion_ver_mask)>>FWVersion_ver_shift;
393 
394  printf("Found version %u\n", ver);
395 
396  if(ver<required) {
397  printf("Firmware version >=%u is required\n", required);
398  throw std::runtime_error("Firmware version not supported");
399 
400  } else if(ver<recommended) {
401  printf("Firmware version >=%u is recommended, please consider upgrading\n", recommended);
402  }
403 }
404 
405 #ifdef __linux__
406 static char ifaceversion[] = "/sys/module/mrf/parameters/interfaceversion";
407 /* Check the interface version of the kernel module to ensure compatibility */
408 static
409 bool checkUIOVersion(int vmin, int vmax, int *actual)
410 {
411  FILE *fd;
412  int version = -1;
413 
414  fd = fopen(ifaceversion, "r");
415  if(!fd) {
416  printf("Can't open %s in order to read kernel module interface version. Kernel module not loaded or too old.\n", ifaceversion);
417  return true;
418  }
419  if(fscanf(fd, "%d", &version)!=1) {
420  fclose(fd);
421  printf("Failed to read %s in order to get the kernel module interface version.\n", ifaceversion);
422  return true;
423  }
424  fclose(fd);
425 
426  // Interface versions are *not* expected to be backwords or forwards compatible.
427  if(version<vmin || version>vmax) {
428  printf("Error: Expect MRF kernel module interface version between [%d, %d], found %d.\n", vmin, vmax, version);
429  return true;
430  }
431  if(actual)
432  *actual = version;
433  return false;
434 }
435 #else
436 static bool checkUIOVersion(int,int,int*) {return false;}
437 #endif
438 
439 void
440 mrmEvrSetupPCI(const char* id,const char* pcispec)
441 {
442 try {
443  bus_configuration bus;
444 
445  bus.busType = busType_pci;
446 
447  if(mrf::Object::getObject(id)){
448  printf("Object ID %s already in use\n",id);
449  return;
450  }
451 
452  /* Linux only
453  * kernel driver interface version.
454  * 0 - Broken
455  * 1 - Use of irqcontrol callback to avoid races for plx pci bridges
456  * 2 - Use of new PCI master enable register to avoid races for soft pci bridges
457  */
458  int kifacever = -1;
459  if(checkUIOVersion(1,2,&kifacever))
460  return;
461 
462  const epicsPCIDevice *cur=0;
463 
464  if( devPCIFindSpec(mrmevrs, pcispec, &cur,0) ){
465  printf("PCI Device not found on %s\n",
466  pcispec);
467  return;
468  }
469 
470  printf("Device %s %x:%x.%x slot=%s\n",id,cur->bus,cur->device,cur->function,cur->slot);
471  printf("Using IRQ %u\n",cur->irq);
472 
473  bus.pci.dev = cur;
474 
475  const EVRMRM::Config *conf = NULL;
476  switch(cur->id.sub_device) {
477  case PCI_DEVICE_ID_MRF_PMCEVR_230: conf = &pmc_evr_230; break;
478  case PCI_DEVICE_ID_MRF_PXIEVR_230: conf = &cpci_evr_230; break;
479  case PCI_DEVICE_ID_MRF_EVRTG_300: conf = &cpci_evrtg_300; break;
480  case PCI_DEVICE_ID_MRF_CPCIEVR300: conf = &cpci_evr_300; break;
481  case PCI_DEVICE_ID_MRF_EVRMTCA300: conf = &mtca_evr_300; break;
482  // ambiguity
483  case PCI_DEVICE_ID_MRF_EVRTG_300E: // aka PCI_SUBDEVICE_ID_PCIE_EVR_300
484  switch (cur->id.device) {
485  case PCI_DEVICE_ID_EC_30: conf = &cpci_evrtg_300; break;
486  case PCI_DEVICE_ID_XILINX_DEV: conf = &pcie_evr_300; break;
487  }
488  break;
489  }
490 
491  if(!conf) {
492  printf("Unknown PCI EVR variant, making assumptions...\n");
493  conf = &cpci_evr_unknown;
494  }
495 
496  volatile epicsUInt8 *plx = 0, *evr = 0;
497  epicsUInt32 evrlen = 0;
498 
499  if(devPCIToLocalAddr(cur,0,(volatile void**)(void *)&evr,DEVLIB_MAP_UIO1TO1))
500  {
501  printf("PCI error: Failed to map BAR 0\n");
502  return;
503  }
504  if(!evr){
505  printf("PCI error: BAR 0 mapped to zero? (%08lx)\n", (unsigned long)evr);
506  return;
507  }
508  if( devPCIBarLen(cur,0,&evrlen) ) {
509  printf("PCI error: Can't find BAR #0 length\n");
510  return;
511  }
512 
513  switch(cur->id.device) {
516  plx = evr;
517 
518  if(devPCIToLocalAddr(cur,2,(volatile void**)(void *)&evr,DEVLIB_MAP_UIO1TO1))
519  {
520  printf("PCI error: Failed to map BAR 2\n");
521  return;
522  }
523  if(!evr){
524  printf("PCI error: BAR 2 mapped to zero? (%08lx)\n", (unsigned long)evr);
525  return;
526  }
527  if( devPCIBarLen(cur,0,&evrlen) ) {
528  printf("PCI error: Can't find BAR #0 length\n");
529  return;
530  }
531  }
532 
533  // handle various PCI to local bus bridges
534  switch(cur->id.device) {
536  printf("Setup PLX PCI 9030\n");
537  /* Use the PLX device on the EVR to swap access on
538  * little endian systems so we don't have no worry about
539  * byte order :)
540  */
541 #if EPICS_BYTE_ORDER == EPICS_ENDIAN_BIG
542  BITSET(LE,32, plx, LAS0BRD, LAS0BRD_ENDIAN);
543 #elif EPICS_BYTE_ORDER == EPICS_ENDIAN_LITTLE
544  BITCLR(LE,32, plx, LAS0BRD, LAS0BRD_ENDIAN);
545 #endif
546 
547  // Disable interrupts on device
548 
549  NAT_WRITE32(evr, IRQEnable, 0);
550 
551 #ifndef __linux__
552  /* Enable active high interrupt1 through the PLX to the PCI bus.
553  */
557 #endif
558  break;
559 
561 #if EPICS_BYTE_ORDER == EPICS_ENDIAN_BIG
562  BITSET(LE,8, plx, BIGEND9056, BIGEND9056_BIG);
563 #elif EPICS_BYTE_ORDER == EPICS_ENDIAN_LITTLE
564  BITCLR(LE,8, plx, BIGEND9056, BIGEND9056_BIG);
565 #endif
566 
567  // Disable interrupts on device
568 
569  NAT_WRITE32(evr, IRQEnable, 0);
570 
571 #ifndef __linux__
573 #endif
574  break;
575 
576  case PCI_DEVICE_ID_EC_30:
579  /* the endianness the 300 series devices w/o PLX bridge
580  * is a little tricky to setup. byte order swapping is controlled
581  * through the EVR's Control register and access to this register
582  * is subject to byte order swapping...
583  */
584 
585  // Disable EVR and set byte order to big endian
586  NAT_WRITE32(evr, Control, 0);
587  // Enable byte order swapping if necessary
588 #if EPICS_BYTE_ORDER == EPICS_ENDIAN_LITTLE
589  BE_WRITE32(evr, Control, 0x02000000);
590 #endif
591 
592  // Disable interrupts on device
593  NAT_WRITE32(evr, IRQEnable, 0);
594 
595 #ifndef __linux__
597 #endif
598  break;
599  default:
600  printf("Unknown PCI bridge %04x\n", cur->id.device);
601  return;
602  }
603 
604  checkVersion(evr, 3, 6);
605 
606  // Acknowledge missed interrupts
607  //TODO: This avoids a spurious FIFO Full
608  NAT_WRITE32(evr, IRQFlag, NAT_READ32(evr, IRQFlag));
609 
610  // Install ISR
611 
612  EVRMRM *receiver=new EVRMRM(id,bus,conf,evr,evrlen);
613 
614  void *arg=receiver;
615 #ifdef __linux__
616  receiver->isrLinuxPvt = (void*)cur;
617 #endif
618 
619  if(devPCIConnectInterrupt(cur, &EVRMRM::isr_pci, arg, 0)){
620  printf("Failed to install ISR\n");
621  delete receiver;
622  return;
623  }else{
624  // Interrupts will be enabled during iocInit()
625  }
626 
627 
628 #ifndef __linux__
629  if(receiver->version()>=MRFVersion(0, 0xa)) {
630  // RTOS doesn't need this, so always enable
631  WRITE32(evr, PCI_MIE, EVG_MIE_ENABLE);
632  }
633 #else
634  if(receiver->version()>=MRFVersion(0, 0xa) && kifacever>=2) {
635  // PCI master enable supported by firmware and kernel module.
636  // the kernel will set this bit when devPCIEnableInterrupt() is called
637  } else if(cur->id.device==PCI_DEVICE_ID_PLX_9030 ||
638  cur->id.device==PCI_DEVICE_ID_PLX_9056) {
639  // PLX based devices don't need special handling
640  WRITE32(evr, PCI_MIE, EVG_MIE_ENABLE);
641  } else if(receiver->version()<MRFVersion(0, 0xa)) {
642  // old firmware and (maybe) old kernel module.
643  // this will still work, so just complain
644  printf("Warning: this configuration of FW and SW is known to have race conditions in interrupt handling.\n"
645  " Please consider upgrading to FW version 0xA.\n");
646  if(kifacever<2)
647  printf(" Also upgrade the linux kernel module to interface version 2.");
648  } else if(receiver->version()>=MRFVersion(0, 0xa) && kifacever<2) {
649  // New firmware w/ old kernel module, this won't work
650  throw std::runtime_error("FW version 0xA for this device requires a linux kernel module w/ interface version 2");
651  } else {
652  throw std::logic_error("logic error in FW/kernel module compatibility check.");
653  }
654 
655  /* ask the kernel module to enable interrupts */
656  printf("Enabling interrupts\n");
657  if(devPCIEnableInterrupt(cur)) {
658  printf("Failed to enable interrupt\n");
659  delete receiver;
660  return;
661  }
662 #endif
663 
664 } catch(std::exception& e) {
665  printf("Error: %s\n",e.what());
666 }
667  errlogFlush();
668 }
669 
670 static
671 void
672 printRamEvt(EVRMRM *evr,int evt,int ram)
673 {
674  if(evt<0 || evt>255)
675  return;
676  if(ram<0 || ram>1)
677  return;
678 
679  epicsUInt32 map[4];
680 
681  map[0]=NAT_READ32(evr->base, MappingRam(ram,evt,Internal));
682  map[1]=NAT_READ32(evr->base, MappingRam(ram,evt,Trigger));
683  map[2]=NAT_READ32(evr->base, MappingRam(ram,evt,Set));
684  map[3]=NAT_READ32(evr->base, MappingRam(ram,evt,Reset));
685 
686  printf("Event 0x%02x %3d ",evt,evt);
687  printf("%08x %08x %08x %08x\n",map[0],map[1],map[2],map[3]);
688 }
689 
690 static
691 bool
692 enableIRQ(mrf::Object* obj, void*)
693 {
694  EVRMRM *mrm=dynamic_cast<EVRMRM*>(obj);
695  if(!mrm)
696  return true;
697 
698  mrm->enableIRQ();
699 
700  return true;
701 }
702 
703 static
704 bool
705 disableIRQ(mrf::Object* obj, void*)
706 {
707  EVRMRM *mrm=dynamic_cast<EVRMRM*>(obj);
708  if(!mrm)
709  return true;
710 
711  WRITE32(mrm->base, IRQEnable, 0);
712  return true;
713 }
714 
715 static
716 void
717 evrShutdown(void*)
718 {
719  mrf::Object::visitObjects(&disableIRQ,0);
720 }
721 
722 void mrmEvrInithooks(initHookState state)
723 {
724  epicsUInt8 lvl;
725  switch(state)
726  {
727  case initHookAfterInterruptAccept:
728  // Register hook to disable interrupts on IOC shutdown
729  epicsAtExit(&evrShutdown, NULL);
730  // First enable interrupts for each EVR
731  mrf::Object::visitObjects(&enableIRQ,0);
732  // Then enable all used levels
733  for(lvl=1; lvl<=7; ++lvl)
734  {
735  if (vme_level_mask&(1<<(lvl-1))) {
736  if(devEnableInterruptLevelVME(lvl))
737  {
738  printf("Failed to enable interrupt level %d\n",lvl);
739  return;
740  }
741  }
742 
743  }
744 
745  break;
746  default:
747  break;
748  }
749 }
750 
751 
752 void
753 mrmEvrSetupVME(const char* id,int slot,int base,int level, int vector)
754 {
755 try {
756  bus_configuration bus;
757  const EVRMRM::Config *conf = &vme_evrrf_230;
758 
759  bus.busType = busType_vme;
760  bus.vme.slot = slot;
761  bus.vme.address = base;
762  bus.vme.irqLevel = level;
763  bus.vme.irqVector = vector;
764 
765  if(mrf::Object::getObject(id)){
766  printf("ID %s already in use\n",id);
767  return;
768  }
769 
770  struct VMECSRID info;
771 
772  volatile unsigned char* csr=devCSRTestSlot(vmeevrs,slot,&info);
773  if(!csr){
774  printf("No EVR in slot %d\n",slot);
775  return;
776  }
777 
778  printf("Setting up EVR in VME Slot %d\n",slot);
779 
780  printf("Found vendor: %08x board: %08x rev.: %08x\n",
781  info.vendor, info.board, info.revision);
782 
783  // Set base address
784 
785  /* Use function 0 for 16-bit addressing (length 0x00800 bytes)
786  * and function 1 for 24-bit addressing (length 0x10000 bytes)
787  * and function 2 for 32-bit addressing (length 0x40000 bytes)
788  *
789  * All expose the same registers, but not all registers are
790  * visible through functions 0 or 1.
791  */
792 
793  CSRSetBase(csr, 2, base, VME_AM_EXT_SUP_DATA);
794 
795  {
796  epicsUInt32 temp=CSRRead32((csr) + CSR_FN_ADER(2));
797 
798  if(temp != CSRADER((epicsUInt32)base,VME_AM_EXT_SUP_DATA)) {
799  printf("Failed to set CSR Base address in ADER2. Check VME bus and card firmware version.\n");
800  return;
801  }
802  }
803 
804  volatile unsigned char* evr;
805  char *Description = allocSNPrintf(40, "EVR-%d '%s' slot %d",
806  info.board & MRF_BID_SERIES_MASK,
807  id, slot);
808 
809  if(devRegisterAddress(Description, atVMEA32, base, EVR_REGMAP_SIZE, (volatile void**)(void *)&evr))
810  {
811  printf("Failed to map address %08x\n",base);
812  return;
813  }
814 
815  epicsUInt32 junk;
816  if(devReadProbe(sizeof(junk), (volatile void*)(evr+U32_FWVersion), (void*)&junk)) {
817  printf("Failed to read from MRM registers (but could read CSR registers)\n");
818  return;
819  }
820 
821  checkVersion(evr, 4, 5);
822 
823  // Read offset from start of CSR to start of user (card specific) CSR.
824  size_t user_offset=CSRRead24(csr+CR_BEG_UCSR);
825  // Currently that value read from the UCSR pointer is
826  // actually little endian.
827  user_offset= (( user_offset & 0x00ff0000 ) >> 16 ) |
828  (( user_offset & 0x0000ff00 ) ) |
829  (( user_offset & 0x000000ff ) << 16 );
830  volatile unsigned char* user_csr=csr+user_offset;
831 
832  NAT_WRITE32(evr, IRQEnable, 0); // Disable interrupts
833 
834  EVRMRM *receiver=new EVRMRM(id, bus, conf, evr, EVR_REGMAP_SIZE);
835 
836  if(level>0 && vector>=0) {
837  CSRWrite8(user_csr+UCSR_IRQ_LEVEL, level&0x7);
838  CSRWrite8(user_csr+UCSR_IRQ_VECTOR, vector&0xff);
839 
840  printf("Using IRQ %d:%2d\n",
841  CSRRead8(user_csr+UCSR_IRQ_LEVEL),
842  CSRRead8(user_csr+UCSR_IRQ_VECTOR)
843  );
844 
845  // Acknowledge missed interrupts
846  //TODO: This avoids a spurious FIFO Full
847  NAT_WRITE32(evr, IRQFlag, NAT_READ32(evr, IRQFlag));
848 
849  level&=0x7;
850  // VME IRQ level will be enabled later during iocInit()
851  vme_level_mask|=1<<(level-1);
852 
853  if(devConnectInterruptVME(vector&0xff, &EVRMRM::isr_vme, receiver))
854  {
855  printf("Failed to connection VME IRQ %d\n",vector&0xff);
856  delete receiver;
857  return;
858  }
859 
860  // Interrupts will be enabled during iocInit()
861  }
862 
863 } catch(std::exception& e) {
864  printf("Error: %s\n",e.what());
865 }
866  errlogFlush();
867 }
868 
869 void
870 mrmEvrDumpMap(const char* id,int evt,int ram)
871 {
872 try {
874  if(!obj)
875  throw std::runtime_error("Object not found");
876  EVRMRM *card=dynamic_cast<EVRMRM*>(obj);
877  if(!card)
878  throw std::runtime_error("Not a MRM EVR");
879 
880  printf("Print ram #%d\n",ram);
881  if(evt>=0){
882  // Print a single event
883  printRamEvt(card,evt,ram);
884  return;
885  }
886  for(evt=0;evt<=255;evt++){
887  printRamEvt(card,evt,ram);
888  }
889 } catch(std::exception& e) {
890  printf("Error: %s\n",e.what());
891 }
892 }
893 
923 void
924 mrmEvrForward(const char* id, const char* events_iocsh)
925 {
926  char *events=events_iocsh ? epicsStrDup(events_iocsh) : 0;
927 try {
929  if(!obj)
930  throw std::runtime_error("Object not found");
931  EVRMRM *card=dynamic_cast<EVRMRM*>(obj);
932  if(!card)
933  throw std::runtime_error("Not a MRM EVR");
934 
935  if(!events || strlen(events)==0) {
936  // Just print current mappings
937  printf("Events forwarded: ");
938  for(unsigned int i=1; i<256; i++) {
939  if(card->specialMapped(i, ActionEvtFwd)) {
940  printf("%d ", i);
941  }
942  }
943  printf("\n");
944  free(events);
945  return;
946  }
947 
948  // update mappings
949 
950  const char sep[]=", ";
951  char *save=0;
952 
953  for(char *tok=strtok_r(events, sep, &save);
954  tok!=NULL;
955  tok = strtok_r(0, sep, &save)
956  )
957  {
958  if(strcmp(tok, "-all")==0) {
959  for(unsigned int i=1; i<256; i++)
960  card->specialSetMap(i, ActionEvtFwd, false);
961 
962  } else if(strcmp(tok, "all")==0) {
963  for(unsigned int i=1; i<256; i++)
964  card->specialSetMap(i, ActionEvtFwd, true);
965 
966  } else {
967  char *end=0;
968  long e=strtol(tok, &end, 0);
969  if(*end || e==LONG_MAX || e==LONG_MIN) {
970  printf("Unable to parse event spec '%s'\n", tok);
971  } else if(e>255 || e<-255 || e==0) {
972  printf("Invalid event %ld\n", e);
973  } else if(e>0) {
974  card->specialSetMap(e, ActionEvtFwd, true);
975  } else if(e<0) {
976  card->specialSetMap(-e, ActionEvtFwd, false);
977  }
978 
979  }
980  }
981 
982 
983  free(events);
984 } catch(std::exception& e) {
985  printf("Error: %s\n",e.what());
986  free(events);
987 }
988 }
989 
990 
991 void
992 mrmEvrLoopback(const char* id, int rxLoopback, int txLoopback)
993 {
994 try {
996  if(!obj)
997  throw std::runtime_error("Object not found");
998  EVRMRM *card=dynamic_cast<EVRMRM*>(obj);
999  if(!card){
1000  throw std::runtime_error("Not a MRM EVR");
1001  }
1002 
1003  epicsUInt32 control = NAT_READ32(card->base,Control);
1004  control &= ~(Control_txloop|Control_rxloop);
1005  if (rxLoopback) control |= Control_rxloop;
1006  if (txLoopback) control |= Control_txloop;
1007  NAT_WRITE32(card->base,Control, control);
1008 
1009 } catch(std::exception& e) {
1010  printf("Error: %s\n",e.what());
1011 }
1012 }
struct configuration_vme vme
enum busType busType
#define BITSET32(base, offset, mask)
Definition: mrfCommonIO.h:124
virtual bool specialMapped(epicsUInt32 code, epicsUInt32 func) const OVERRIDE FINAL
Definition: drvem.cpp:505
#define FWVersion_type_mask
Definition: evrRegMap.h:137
#define BITCLR(ord, len, base, offset, mask)
Definition: mrfBitOps.h:26
void mrmEvrLoopback(const char *id, int rxLoopback, int txLoopback)
Definition: drvemSetup.cpp:992
#define LE_WRITE16(base, offset, value)
Definition: mrfCommonIO.h:199
#define READ32(base, offset)
Definition: mrfCommonIO.h:114
virtual double clock() const OVERRIDE FINAL
Definition: drvem.h:141
volatile unsigned char *const base
Definition: drvem.h:223
#define IRQ_PCIee
Definition: mrf.h:119
#define PCI_DEVICE_ID_MRF_PMCEVR_230
Definition: mrmpci.h:33
void mrmEvrInithooks(initHookState state)
Definition: drvemSetup.cpp:722
#define REGINFO(label, name, size)
long mrmEvrReport(int level)
Definition: drvemSetup.cpp:371
#define U32_FWVersion
Definition: evrRegMap.h:136
#define IRQEnable
Definition: mrf.h:115
#define PCI_DEVICE_ID_MRF_EVRMTCA300
Definition: uio_mrf.c:74
#define LAS0BRD
Definition: mrf.h:41
static void isr_pci(void *)
Definition: drvem.cpp:1107
#define Control_rxloop
Definition: evrRegMap.h:60
static void isr_vme(void *)
Definition: drvem.cpp:1121
#define BE_WRITE32(base, offset, value)
Definition: mrfCommonIO.h:170
#define PCI_VENDOR_ID_LATTICE
Definition: uio_mrf.c:44
#define PCI_VENDOR_ID_PLX
Definition: plx9030.h:37
Modular Register Map Event Receivers.
Definition: drvem.h:86
#define PCI_DEVICE_ID_MRF_PXIEVR_230
Definition: mrmpci.h:34
void mrmEvrSetupPCI(const char *id, const char *pcispec)
Definition: drvemSetup.cpp:440
#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
#define BIGEND9056
Definition: mrf.h:74
virtual void specialSetMap(epicsUInt32 code, epicsUInt32 func, bool) OVERRIDE FINAL
Definition: drvem.cpp:524
void enableIRQ(void)
Definition: drvem.cpp:1090
Base object inspection.
Definition: object.h:378
#define UCSR_IRQ_LEVEL
Definition: mrfcsr.h:59
#define MRF_BID_SERIES_MASK
Definition: mrfcsr.h:31
char * allocSNPrintf(size_t N, const char *fmt,...)
Definition: mrfCommon.cpp:59
static Object * getObject(const std::string &name)
Definition: object.cpp:107
#define Control_txloop
Definition: evrRegMap.h:58
static void visitObjects(bool(*)(Object *, void *), void *)
Definition: object.cpp:150
#define BIGEND9056_BIG
Definition: plx9056.h:21
#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 MRF_VME_EVR_RF_BID
Definition: mrfcsr.h:19
#define PCI_DEVICE_ID_EC_30
Definition: uio_mrf.c:46
#define NAT_READ32(base, offset)
Definition: mrfCommonIO.h:145
void mrmEvrDumpMap(const char *id, int evt, int ram)
Definition: drvemSetup.cpp:870
#define IRQFlag
Definition: mrf.h:106
struct configuration_pci pci
#define FWVersion_ver_shift
Definition: evrRegMap.h:142
void mrmEvrSetupVME(const char *id, int slot, int base, int level, int vector)
Definition: drvemSetup.cpp:753
#define FWVersion_type_shift
Definition: evrRegMap.h:138
std::string versionStr() const
Definition: evr.cpp:38
const epicsPCIDevice * dev
void mrmEvrForward(const char *id, const char *events_iocsh)
Setup Event forwarding to downstream link.
Definition: drvemSetup.cpp:924
#define LAS0BRD_ENDIAN
Definition: plx9030.h:24
#define INTCSR9056
Definition: mrf.h:77
const std::string & name() const
Definition: object.h:393
#define PCI_DEVICE_ID_MRF_EVRTG_300E
Definition: mrmpci.h:36
#define PCI_DEVICE_ID_MRF_EVRTG_300
Definition: mrmpci.h:35
#define ActionEvtFwd
Definition: evrRegMap.h:365
#define MRF_VME_IEEE_OUI
Definition: mrfcsr.h:15
#define EVR_REGMAP_SIZE
Definition: evrRegMap.h:380
#define INTCSR_INT1_Polarity
Definition: plx9030.h:29
bus_configuration * getBusConfiguration()
Definition: evr.cpp:49
std::string formFactorStr()
Definition: drvem.cpp:430
#define EVG_MIE_ENABLE
Definition: evgRegMap.h:64
#define NAT_WRITE32(base, offset, value)
Definition: mrfCommonIO.h:148
virtual MRFVersion version() const OVERRIDE FINAL
Firmware Version.
Definition: drvem.cpp:415
#define INTCSR
Definition: mrf.h:46
#define BITSET(ord, len, base, offset, mask)
Definition: mrfBitOps.h:21
#define PCI_SUBDEVICE_ID_PCIE_EVR_300
Definition: uio_mrf.c:64
#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
#define FWVersion_ver_mask
Definition: evrRegMap.h:141
epicsUInt32 fpgaFirmware()
Definition: drvem.cpp:411
#define WRITE32(base, offset, value)
Definition: mrfCommonIO.h:119
mrf::auto_ptr< SFP > sfp
Definition: drvem.h:227
#define PCI_DEVICE_ID_PLX_9056
Definition: uio_mrf.c:51
epicsUInt32 baselen
Definition: drvem.h:224
#define INTCSR9056_LCL_Enable
Definition: plx9056.h:25
#define PCI_DEVICE_ID_PLX_9030
Definition: uio_mrf.c:50
#define INTCSR_INT1_Enable
Definition: plx9030.h:28
#define INTCSR_PCI_Enable
Definition: plx9030.h:34
#define INTCSR9056_PCI_Enable
Definition: plx9056.h:24
#define PCI_DEVICE_ID_MRF_CPCIEVR300
Definition: mrmpci.h:50