14 #include <epicsExit.h> 15 #include <epicsThread.h> 16 #include <epicsStdio.h> 17 #include <epicsString.h> 21 #include <initHooks.h> 32 #define devCSRTestSlot(vmeEvgIDs,slot,info) (NULL) 39 #include <devLibPCI.h> 42 #include <epicsExport.h> 51 static epicsUInt8 vme_level_mask = 0;
54 struct VMECSRID vmeEvgIDs[] = {
137 inithooks(initHookState state) {
140 case initHookAfterInterruptAccept:
141 epicsAtExit(&evgShutdown, NULL);
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);
155 case initHookAtIocRun:
156 epicsAtExit(&evgShutdown, NULL);
165 void checkVersion(
volatile epicsUInt8 *base,
const MRFVersion& required,
166 const MRFVersion& recommended)
175 throw std::runtime_error(
"Address does not correspond to an EVG");
180 std::ostringstream msg;
181 msg<<
"Firmware version >= "<<required<<
" is required\n";
182 throw std::runtime_error(msg.str());
184 }
else if(ver < recommended) {
185 std::cout<<
"Firmware version >= "<<recommended<<
" is recommended, please consider upgrading\n";
194 epicsUInt32 vmeAddress,
196 epicsInt32 irqVector)
198 volatile epicsUInt8* regCpuAddr = 0;
199 struct VMECSRID info;
202 info.board = 0; info.revision = 0; info.vendor = 0;
206 bus.vme.address = vmeAddress;
207 bus.vme.irqLevel = irqLevel;
208 bus.vme.irqVector = irqVector;
212 printf(
"ID %s already in use\n",
id);
217 volatile unsigned char* csrCpuAddr =
218 devCSRTestSlot(vmeEvgIDs,slot,&info);
221 printf(
"No EVG in slot %d\n",slot);
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);
229 epicsUInt32 xxx = CSRRead32(csrCpuAddr + CSR_FN_ADER(1));
231 printf(
"Warning: EVG not in power on state! (%08x)\n", xxx);
234 CSRSetBase(csrCpuAddr, 1, vmeAddress, VME_AM_STD_SUP_DATA);
237 epicsUInt32 temp=CSRRead32((csrCpuAddr) + CSR_FN_ADER(1));
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");
251 int status = devRegisterAddress (
256 (
volatile void **)(
void *)®CpuAddr
260 printf(
"Failed to map VME address %08x\n", vmeAddress);
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");
272 checkVersion(regCpuAddr, MRFVersion(0, 3, 0), MRFVersion(0, 3, 0));
279 evgMrm* evg =
new evgMrm(
id, conf, bus, regCpuAddr, NULL);
281 if(irqLevel > 0 && irqVector >= 0) {
286 printf(
"IRQ Level: %d\nIRQ Vector: %d\n",
292 printf(
"csrCpuAddr : %p\nregCpuAddr : %p\n",csrCpuAddr, regCpuAddr);
296 WRITE32(regCpuAddr, IrqEnable, 0);
299 vme_level_mask |= 1 << ((irqLevel&0x7)-1);
303 printf(
"ERROR:Failed to connect VME IRQ vector %d\n" 312 }
catch(std::exception& e) {
313 printf(
"Error: %s\n",e.what());
320 static char ifaceversion[] =
"/sys/module/mrf/parameters/interfaceversion";
323 bool checkUIOVersion(
int vmin,
int vmax,
int *actual)
328 fd = fopen(ifaceversion,
"r");
330 printf(
"Can't open %s in order to read kernel module interface version. Kernel module not loaded or too old.\n", ifaceversion);
333 if(fscanf(fd,
"%d", &version)!=1) {
335 printf(
"Failed to read %s in order to get the kernel module interface version.\n", ifaceversion);
341 if(version<vmin || version>vmax) {
342 printf(
"Error: Expect MRF kernel module interface version between [%d, %d], found %d.\n", vmin, vmax, version);
350 static bool checkUIOVersion(
int,
int,
int*) {
return false;}
354 static const epicsPCIID
372 std::istringstream strm(spec);
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",
386 printf(
"ID %s already in use\n",
id);
397 if(checkUIOVersion(1,2,&kifacever))
401 const epicsPCIDevice *cur = 0;
402 if (devPCIFindSpec(mrmevgs, spec, &cur, 0)) {
403 printf(
"PCI Device not found\n");
412 printf(
"Device %s %x:%x.%x\n",
id, cur->bus, cur->device,
414 printf(
"Using IRQ %u\n", cur->irq);
417 volatile epicsUInt8 *BAR_plx, *BAR_evg;
419 if (devPCIToLocalAddr(cur, 0, (
volatile void**) (
void *) &BAR_plx, 0)) {
420 printf(
"Failed to map BARs 0\n");
424 printf(
"BAR0 mapped to zero? (%08lx)\n",
425 (
unsigned long) BAR_plx);
429 switch(cur->id.device) {
431 if (devPCIToLocalAddr(cur, 2, (
volatile void**) (
void *) &BAR_evg, 0)) {
432 printf(
"Failed to map BARs 2\n");
436 printf(
"BAR2 mapped to zero? (%08lx)\n",
437 (
unsigned long) BAR_evg);
441 #if EPICS_BYTE_ORDER == EPICS_ENDIAN_BIG 443 #elif EPICS_BYTE_ORDER == EPICS_ENDIAN_LITTLE 459 #if EPICS_BYTE_ORDER == EPICS_ENDIAN_BIG 461 #elif EPICS_BYTE_ORDER == EPICS_ENDIAN_LITTLE 467 printf(
"Unknown/unsupported PCI device 0x%04x\n", (
unsigned)cur->device);
472 checkVersion(BAR_evg, MRFVersion(0, 3, 0), MRFVersion(0, 8, 0));
476 WRITE32(BAR_evg, IrqEnable, 0);
481 conf = &conf_cpci_evg_300;
482 }
else switch(cur->id.sub_device) {
493 MRFVersion ver(evg->
version());
495 #if !defined(__linux__) && !defined(_WIN32) 500 if(ver>=MRFVersion(0, 8, 0)) {
505 if(ver>=MRFVersion(0, 8, 0) && kifacever>=2) {
511 }
else if(ver<MRFVersion(0, 8, 0)) {
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");
517 printf(
" Also upgrade the linux kernel module to interface version 2.");
518 }
else if(ver>=MRFVersion(0, 8, 0) && kifacever<2) {
520 throw std::runtime_error(
"FW version 8 for this device requires a linux kernel module w/ interface version 2");
522 throw std::logic_error(
"logic error in FW/kernel module compatibility check.");
524 if(devPCIEnableInterrupt(cur)) {
525 printf(
"Failed to enable interrupt\n");
532 if ((ret=devPCIConnectInterrupt(cur, &
evgMrm::isr_pci, (
void*) evg, 0))!=0) {
534 errSymLookup(ret, buf,
sizeof(buf));
535 printf(
"ERROR:Failed to connect PCI interrupt. err (%d) %s\n", ret, buf);
539 printf(
"PCI interrupt connected!\n");
544 }
catch (std::exception& e) {
545 printf(
"Error: %s\n", e.what());
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)",
555 static const iocshArg mrmEvgSetupVMEArg4 = {
"IRQ Vector 0-255", iocshArgInt };
556 static const iocshArg *
const mrmEvgSetupVMEArgs[5] = { &mrmEvgSetupVMEArg0,
560 &mrmEvgSetupVMEArg4 };
562 static const iocshFuncDef mrmEvgSetupVMEFuncDef = {
"mrmEvgSetupVME", 5,
563 mrmEvgSetupVMEArgs };
566 mrmEvgSetupVMECallFunc(
const iocshArgBuf *
args) {
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 };
579 static const iocshArg *
const mrmEvgSetupPCIArgs[4] = { &mrmEvgSetupPCIArg0,
580 &mrmEvgSetupPCIArg1, &mrmEvgSetupPCIArg2, &mrmEvgSetupPCIArg3 };
582 static const iocshFuncDef mrmEvgSetupPCIFuncDef = {
"mrmEvgSetupPCI", 4,
583 mrmEvgSetupPCIArgs };
585 static void mrmEvgSetupPCICallFunc(
const iocshArgBuf *args) {
586 mrmEvgSetupPCI(args[0].sval, args[1].sval, args[2].ival, args[3].ival);
591 static void evgMrmRegistrar() {
592 initHookRegister(&inithooks);
593 iocshRegister(&mrmEvgSetupVMEFuncDef, mrmEvgSetupVMECallFunc);
594 iocshRegister(&mrmEvgSetupPCIFuncDef, mrmEvgSetupPCICallFunc);
609 #define REGINFO(label, name, size) {label, U##size##_##name, size} 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),
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),
688 printregisters(
volatile epicsUInt8 *evg) {
690 printf(
"\n--- Register Dump @%p ---\n", evg);
692 for(reg=0; reg<NELEMENTS(printreg); reg++){
693 switch(printreg[reg].rsize){
695 printf(
"%16s: %02x\n", printreg[reg].label,
696 ioread8(evg+printreg[reg].offset));
699 printf(
"%16s: %04x\n", printreg[reg].label,
703 printf(
"%16s: %08x\n", printreg[reg].label,
712 int *level=(
int*)arg;
717 printf(
"EVG: %s \n", evg->
getId().c_str());
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);
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);
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);
737 printf(
"\tCard not detected in configured slot %d\n", bus->vme.slot);
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);
749 printf(
"\tUnknown bus type\n");
763 printf(
"=== Begin MRF EVG support ===\n");
765 printf(
"=== End MRF EVG support ===\n");
std::string getFwVersionStr() const
#define PCI_DEVICE_ID_MRF_MTCA_EVM_300
#define BITCLR(ord, len, base, offset, mask)
static void isr_vme(void *)
#define REGINFO(label, name, size)
#define LE_WRITE16(base, offset, value)
#define READ32(base, offset)
#define BE_WRITE32(base, offset, value)
#define PCI_VENDOR_ID_PLX
volatile epicsUInt8 * getRegAddr() const
#define PCI_VENDOR_ID_XILINX
INLINE epicsUInt8 ioread8(volatile void *addr)
INLINE epicsUInt32 nat_ioread32(volatile void *addr)
#define MRF_BID_SERIES_MASK
#define PCI_DEVICE_ID_MRF_CPCIEVG300
char * allocSNPrintf(size_t N, const char *fmt,...)
static Object * getObject(const std::string &name)
static void visitObjects(bool(*)(Object *, void *), void *)
#define BITCLR32(base, offset, mask)
epicsExportRegistrar(evgMrmRegistrar)
epicsStatus mrmEvgSetupPCI(const char *id, const char *spec, int d, int f)
#define PCI_DEVICE_ID_XILINX_DEV
#define PCI_VENDOR_ID_MRF
INLINE epicsUInt16 nat_ioread16(volatile void *addr)
const bus_configuration * getBusConfiguration()
epicsExportAddress(drvet, drvEvgMrm)
struct configuration_pci pci
const epicsPCIDevice * dev
#define FPGAVersion_TYPE_SHIFT
#define INTCSR_INT1_Polarity
#define PCI_SUBDEVICE_ID_MRF_PXIEVG_220
#define NAT_WRITE32(base, offset, value)
#define BITSET(ord, len, base, offset, mask)
const std::string getId() const
void checkVersion(volatile epicsUInt8 *base, const MRFVersion &required, const MRFVersion &recommended)
static void isr_pci(void *)
#define WRITE32(base, offset, value)
epicsStatus mrmEvgSetupVME(const char *id, epicsInt32 slot, epicsUInt32 vmeAddress, epicsInt32 irqLevel, epicsInt32 irqVector)
#define PCI_DEVICE_ID_MRF_PXIEVG230
#define PCI_DEVICE_ID_PLX_9030
#define INTCSR_INT1_Enable
#define INTCSR_PCI_Enable
#define FPGAVersion_TYPE_MASK
MRFVersion version() const