19 #include <epicsString.h> 20 #include <epicsStdio.h> 23 #include <initHooks.h> 24 #include <epicsExit.h> 27 #include <devLibPCI.h> 29 #include <epicsInterrupt.h> 30 #include <epicsThread.h> 38 #include <epicsExport.h> 53 #define strtok_r(strToken,strDelimit,lasts ) (*(lasts) = strtok((strToken),(strDelimit))) 60 static epicsUInt8 vme_level_mask = 0;
62 static const epicsPCIID mrmevrs[] = {
86 static const struct VMECSRID vmeevrs[] = {
235 #define REGINFO(label, name, size) {label, U##size##_##name, size} 236 REGINFO(
"Version", FWVersion, 32),
237 REGINFO(
"Control", Control, 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),
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)
279 printregisters(
volatile epicsUInt8 *evr,epicsUInt32 len)
283 printf(
"EVR register dump\n");
284 for(reg=0; reg<NELEMENTS(printreg); reg++){
286 if(printreg[reg].offset+printreg[reg].rsize/8 > len)
289 switch(printreg[reg].rsize){
291 printf(
"%9s: %02x\n",
293 ioread8(evr+printreg[reg].offset));
296 printf(
"%9s: %04x\n",
301 printf(
"%9s: %08x\n",
312 int *level=(
int*)raw;
317 printf(
"EVR: %s\n",obj->
name().c_str());
320 printf(
"\tClock: %.6f MHz\n",evr->
clock()*1e-6);
324 struct VMECSRID vmeDev;
325 volatile unsigned char* csrAddr = devCSRTestSlot(vmeevrs, bus->vme.slot, &vmeDev);
327 epicsUInt32 ader = CSRRead32(csrAddr + CSR_FN_ADER(2));
328 size_t user_offset=CSRRead24(csrAddr+CR_BEG_UCSR);
331 user_offset= (( user_offset & 0x00ff0000 ) >> 16 ) |
332 (( user_offset & 0x0000ff00 ) ) |
333 (( user_offset & 0x000000ff ) << 16 );
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);
345 printf(
"\tCard not detected in configured slot %d\n", bus->vme.slot);
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);
357 printf(
"\tUnknown bus type\n");
363 if(*level>=1 && evr->
sfp.get()){
364 evr->
sfp->updateNow();
373 printf(
"=== Begin MRF EVR support ===\n");
375 printf(
"=== End MRF EVR support ===\n");
380 void checkVersion(
volatile epicsUInt8 *base,
unsigned int required,
unsigned int recommended)
382 epicsUInt32 v =
READ32(base, FWVersion);
384 printf(
"FWVersion 0x%08x\n", v);
390 throw std::runtime_error(
"Firmware does not correspond to an EVR");
394 printf(
"Found version %u\n", ver);
397 printf(
"Firmware version >=%u is required\n", required);
398 throw std::runtime_error(
"Firmware version not supported");
400 }
else if(ver<recommended) {
401 printf(
"Firmware version >=%u is recommended, please consider upgrading\n", recommended);
406 static char ifaceversion[] =
"/sys/module/mrf/parameters/interfaceversion";
409 bool checkUIOVersion(
int vmin,
int vmax,
int *actual)
414 fd = fopen(ifaceversion,
"r");
416 printf(
"Can't open %s in order to read kernel module interface version. Kernel module not loaded or too old.\n", ifaceversion);
419 if(fscanf(fd,
"%d", &version)!=1) {
421 printf(
"Failed to read %s in order to get the kernel module interface version.\n", ifaceversion);
427 if(version<vmin || version>vmax) {
428 printf(
"Error: Expect MRF kernel module interface version between [%d, %d], found %d.\n", vmin, vmax, version);
436 static bool checkUIOVersion(
int,
int,
int*) {
return false;}
448 printf(
"Object ID %s already in use\n",
id);
459 if(checkUIOVersion(1,2,&kifacever))
462 const epicsPCIDevice *cur=0;
464 if( devPCIFindSpec(mrmevrs, pcispec, &cur,0) ){
465 printf(
"PCI Device not found on %s\n",
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);
476 switch(cur->id.sub_device) {
484 switch (cur->id.device) {
492 printf(
"Unknown PCI EVR variant, making assumptions...\n");
493 conf = &cpci_evr_unknown;
496 volatile epicsUInt8 *plx = 0, *evr = 0;
497 epicsUInt32 evrlen = 0;
499 if(devPCIToLocalAddr(cur,0,(
volatile void**)(
void *)&evr,DEVLIB_MAP_UIO1TO1))
501 printf(
"PCI error: Failed to map BAR 0\n");
505 printf(
"PCI error: BAR 0 mapped to zero? (%08lx)\n", (
unsigned long)evr);
508 if( devPCIBarLen(cur,0,&evrlen) ) {
509 printf(
"PCI error: Can't find BAR #0 length\n");
513 switch(cur->id.device) {
518 if(devPCIToLocalAddr(cur,2,(
volatile void**)(
void *)&evr,DEVLIB_MAP_UIO1TO1))
520 printf(
"PCI error: Failed to map BAR 2\n");
524 printf(
"PCI error: BAR 2 mapped to zero? (%08lx)\n", (
unsigned long)evr);
527 if( devPCIBarLen(cur,0,&evrlen) ) {
528 printf(
"PCI error: Can't find BAR #0 length\n");
534 switch(cur->id.device) {
536 printf(
"Setup PLX PCI 9030\n");
541 #if EPICS_BYTE_ORDER == EPICS_ENDIAN_BIG 543 #elif EPICS_BYTE_ORDER == EPICS_ENDIAN_LITTLE 561 #if EPICS_BYTE_ORDER == EPICS_ENDIAN_BIG 563 #elif EPICS_BYTE_ORDER == EPICS_ENDIAN_LITTLE 588 #if EPICS_BYTE_ORDER == EPICS_ENDIAN_LITTLE 600 printf(
"Unknown PCI bridge %04x\n", cur->id.device);
616 receiver->isrLinuxPvt = (
void*)cur;
620 printf(
"Failed to install ISR\n");
629 if(receiver->
version()>=MRFVersion(0, 0xa)) {
634 if(receiver->
version()>=MRFVersion(0, 0xa) && kifacever>=2) {
641 }
else if(receiver->
version()<MRFVersion(0, 0xa)) {
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");
647 printf(
" Also upgrade the linux kernel module to interface version 2.");
648 }
else if(receiver->
version()>=MRFVersion(0, 0xa) && kifacever<2) {
650 throw std::runtime_error(
"FW version 0xA for this device requires a linux kernel module w/ interface version 2");
652 throw std::logic_error(
"logic error in FW/kernel module compatibility check.");
656 printf(
"Enabling interrupts\n");
657 if(devPCIEnableInterrupt(cur)) {
658 printf(
"Failed to enable interrupt\n");
664 }
catch(std::exception& e) {
665 printf(
"Error: %s\n",e.what());
672 printRamEvt(
EVRMRM *evr,
int evt,
int ram)
686 printf(
"Event 0x%02x %3d ",evt,evt);
687 printf(
"%08x %08x %08x %08x\n",map[0],map[1],map[2],map[3]);
727 case initHookAfterInterruptAccept:
729 epicsAtExit(&evrShutdown, NULL);
733 for(lvl=1; lvl<=7; ++lvl)
735 if (vme_level_mask&(1<<(lvl-1))) {
736 if(devEnableInterruptLevelVME(lvl))
738 printf(
"Failed to enable interrupt level %d\n",lvl);
766 printf(
"ID %s already in use\n",
id);
770 struct VMECSRID info;
772 volatile unsigned char* csr=devCSRTestSlot(vmeevrs,slot,&info);
774 printf(
"No EVR in slot %d\n",slot);
778 printf(
"Setting up EVR in VME Slot %d\n",slot);
780 printf(
"Found vendor: %08x board: %08x rev.: %08x\n",
781 info.vendor, info.board, info.revision);
793 CSRSetBase(csr, 2, base, VME_AM_EXT_SUP_DATA);
796 epicsUInt32 temp=CSRRead32((csr) + CSR_FN_ADER(2));
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");
804 volatile unsigned char* evr;
809 if(devRegisterAddress(Description, atVMEA32, base,
EVR_REGMAP_SIZE, (
volatile void**)(
void *)&evr))
811 printf(
"Failed to map address %08x\n",base);
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");
824 size_t user_offset=CSRRead24(csr+CR_BEG_UCSR);
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;
836 if(level>0 && vector>=0) {
840 printf(
"Using IRQ %d:%2d\n",
851 vme_level_mask|=1<<(level-1);
855 printf(
"Failed to connection VME IRQ %d\n",vector&0xff);
863 }
catch(std::exception& e) {
864 printf(
"Error: %s\n",e.what());
875 throw std::runtime_error(
"Object not found");
878 throw std::runtime_error(
"Not a MRM EVR");
880 printf(
"Print ram #%d\n",ram);
883 printRamEvt(card,evt,ram);
886 for(evt=0;evt<=255;evt++){
887 printRamEvt(card,evt,ram);
889 }
catch(std::exception& e) {
890 printf(
"Error: %s\n",e.what());
926 char *events=events_iocsh ? epicsStrDup(events_iocsh) : 0;
930 throw std::runtime_error(
"Object not found");
933 throw std::runtime_error(
"Not a MRM EVR");
935 if(!events || strlen(events)==0) {
937 printf(
"Events forwarded: ");
938 for(
unsigned int i=1; i<256; i++) {
950 const char sep[]=
", ";
953 for(
char *tok=strtok_r(events, sep, &save);
955 tok = strtok_r(0, sep, &save)
958 if(strcmp(tok,
"-all")==0) {
959 for(
unsigned int i=1; i<256; i++)
962 }
else if(strcmp(tok,
"all")==0) {
963 for(
unsigned int i=1; i<256; i++)
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);
984 }
catch(std::exception& e) {
985 printf(
"Error: %s\n",e.what());
997 throw std::runtime_error(
"Object not found");
1000 throw std::runtime_error(
"Not a MRM EVR");
1009 }
catch(std::exception& e) {
1010 printf(
"Error: %s\n",e.what());
struct configuration_vme vme
#define BITSET32(base, offset, mask)
virtual bool specialMapped(epicsUInt32 code, epicsUInt32 func) const OVERRIDE FINAL
#define FWVersion_type_mask
#define BITCLR(ord, len, base, offset, mask)
void mrmEvrLoopback(const char *id, int rxLoopback, int txLoopback)
#define LE_WRITE16(base, offset, value)
#define READ32(base, offset)
virtual double clock() const OVERRIDE FINAL
volatile unsigned char *const base
#define PCI_DEVICE_ID_MRF_PMCEVR_230
void mrmEvrInithooks(initHookState state)
#define REGINFO(label, name, size)
long mrmEvrReport(int level)
#define PCI_DEVICE_ID_MRF_EVRMTCA300
static void isr_pci(void *)
static void isr_vme(void *)
#define BE_WRITE32(base, offset, value)
#define PCI_VENDOR_ID_LATTICE
#define PCI_VENDOR_ID_PLX
Modular Register Map Event Receivers.
#define PCI_DEVICE_ID_MRF_PXIEVR_230
void mrmEvrSetupPCI(const char *id, const char *pcispec)
#define PCI_VENDOR_ID_XILINX
INLINE epicsUInt8 ioread8(volatile void *addr)
INLINE epicsUInt32 nat_ioread32(volatile void *addr)
virtual void specialSetMap(epicsUInt32 code, epicsUInt32 func, bool) OVERRIDE FINAL
#define MRF_BID_SERIES_MASK
char * allocSNPrintf(size_t N, const char *fmt,...)
static Object * getObject(const std::string &name)
static void visitObjects(bool(*)(Object *, void *), void *)
#define PCI_DEVICE_ID_XILINX_DEV
#define PCI_VENDOR_ID_MRF
INLINE epicsUInt16 nat_ioread16(volatile void *addr)
#define MRF_VME_EVR_RF_BID
#define PCI_DEVICE_ID_EC_30
#define NAT_READ32(base, offset)
void mrmEvrDumpMap(const char *id, int evt, int ram)
struct configuration_pci pci
#define FWVersion_ver_shift
void mrmEvrSetupVME(const char *id, int slot, int base, int level, int vector)
#define FWVersion_type_shift
std::string versionStr() const
const epicsPCIDevice * dev
void mrmEvrForward(const char *id, const char *events_iocsh)
Setup Event forwarding to downstream link.
const std::string & name() const
#define PCI_DEVICE_ID_MRF_EVRTG_300E
#define PCI_DEVICE_ID_MRF_EVRTG_300
#define INTCSR_INT1_Polarity
bus_configuration * getBusConfiguration()
std::string formFactorStr()
#define NAT_WRITE32(base, offset, value)
virtual MRFVersion version() const OVERRIDE FINAL
Firmware Version.
#define BITSET(ord, len, base, offset, mask)
#define PCI_SUBDEVICE_ID_PCIE_EVR_300
void checkVersion(volatile epicsUInt8 *base, const MRFVersion &required, const MRFVersion &recommended)
#define FWVersion_ver_mask
epicsUInt32 fpgaFirmware()
#define WRITE32(base, offset, value)
#define PCI_DEVICE_ID_PLX_9056
#define INTCSR9056_LCL_Enable
#define PCI_DEVICE_ID_PLX_9030
#define INTCSR_INT1_Enable
#define INTCSR_PCI_Enable
#define INTCSR9056_PCI_Enable
#define PCI_DEVICE_ID_MRF_CPCIEVR300