/*Constructor */ drvSIS3801::drvSIS3801(const char *portName, int baseAddress, int interruptVector, int interruptLevel, int maxChans, int maxSignals) : drvSIS38XX(portName, maxChans, maxSignals) { int status; epicsUInt32 controlStatusReg; epicsUInt32 moduleID; static const char* functionName="SIS3801"; setIntegerParam(SIS38XXModel_, MODEL_SIS3801); /* Call devLib to get the system address that corresponds to the VME * base address of the board. */ status = devRegisterAddress("drvSIS3801", SIS3801_ADDRESS_TYPE, (size_t)baseAddress, SIS3801_BOARD_SIZE, (volatile void **)®isters_); if (status) { asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: %s, Can't register VME address %p\n", driverName, functionName, portName, baseAddress); return; } asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: Registered VME address: 0x%lX to local address: %p size: 0x%X\n", driverName, functionName, (long)baseAddress, registers_, SIS3801_BOARD_SIZE); /* Probe VME bus to see if card is there */ status = devReadProbe(4, (char *) ®isters_->csr_reg, (char *) &controlStatusReg); if (status) { asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: devReadProbe failure = %d\n", driverName, functionName, status); return; } /* Get the module info from the card */ moduleID = (registers_->irq_reg & 0xFFFF0000) >> 16; asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: module ID=%x\n", driverName, functionName, moduleID); firmwareVersion_ = (registers_->irq_reg & 0x0000F000) >> 12; setIntegerParam(SIS38XXFirmware_, firmwareVersion_); asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: firmware=%d\n", driverName, functionName, firmwareVersion_); // Create the mutex used to lock access to the FIFO fifoLockId_ = epicsMutexCreate(); /* Reset card */ asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: resetting port %s\n", driverName, functionName, portName); registers_->key_reset_reg = 1; /* Clear FIFO */ asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: clearing FIFO\n", driverName, functionName); resetFIFO(); setControlStatusReg(); /* Initialize board in MCS mode */ setAcquireMode(ACQUIRE_MODE_MCS); /* Set number of readout channels to maxSignals * Assumes that the lower channels will be used first, and the only unused * channels will be at the upper end of the channel range. * Create a mask with zeros in the rightmost maxSignals bits, * 1 in all higher order bits. */ registers_->copy_disable_reg = 0xffffffff<<maxSignals_; asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: setting copy disable register=0x%08x\n", driverName, functionName, 0xffffffff<<maxSignals_); /* Set up the interrupt service routine */ asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: interruptServiceRoutine pointer %p\n", driverName, functionName, intFuncC); status = devConnectInterruptVME(interruptVector, intFuncC, this); if (status) { asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: Can't connect to vector % d\n", driverName, functionName, interruptVector); return; } asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: Connected interrupt vector: %d\n\n", driverName, functionName, interruptVector); /* Write interrupt level to hardware */ asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: irq before setting IntLevel= 0x%x\n", driverName, functionName, registers_->irq_reg); registers_->irq_reg |= (interruptLevel << 8); asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: irq after setting IntLevel= 0x%x\n", driverName, functionName, registers_->irq_reg); registers_->irq_reg |= interruptVector; asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "m%s:%s: irq config register after setting interrupt vector = 0x%08x\n", driverName, functionName, registers_->irq_reg); /* Create the thread that reads the FIFO */ if (epicsThreadCreate("SIS3801FIFOThread", epicsThreadPriorityLow, epicsThreadGetStackSize(epicsThreadStackMedium), (EPICSTHREADFUNC)readFIFOThreadC, this) == NULL) { asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: epicsThreadCreate failure\n", driverName, functionName); return; } else asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: epicsThreadCreate success\n", driverName, functionName); erase(); /* Enable interrupts in hardware */ asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: irq before enabling interrupts= 0x%08x\n", driverName, functionName, registers_->irq_reg); enableInterrupts(); /* Enable interrupt level in EPICS */ status = devEnableInterruptLevel(intVME, interruptLevel); if (status) { asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: Can't enable enterrupt level %d\n", driverName, functionName, interruptLevel); return; } exists_ = true; return; }
/*************************************************** * initialize all software and hardware * scaler_init() ****************************************************/ STATIC long scaler_init(int after) { volatile char *localAddr; unsigned long status; void *baseAddr; int card, i; uint32 probeValue = 0; Debug(2,"scaler_init(): entry, after = %d\n", after); if (after || (vsc_num_cards == 0)) return(0); /* allocate scaler_state structures, array of pointers */ if (scaler_state == NULL) { scaler_state = (struct scaler_state **) calloc(1, vsc_num_cards * sizeof(struct scaler_state *)); scaler_total_cards=0; for (card=0; card<vsc_num_cards; card++) { scaler_state[card] = (struct scaler_state *) calloc(1, sizeof(struct scaler_state)); } } /* Check out the hardware. */ for (card=0; card<vsc_num_cards; card++) { baseAddr = (void *)(vsc_addrs + card*CARD_ADDRESS_SPACE); /* Can we reserve the required block of VME address space? */ status = devRegisterAddress(__FILE__, atVMEA32, (size_t)baseAddr, CARD_ADDRESS_SPACE, (volatile void **)&localAddr); if (!RTN_SUCCESS(status)) { errPrintf(status, __FILE__, __LINE__, "Can't register 0x%x-byte block at address %p\n", CARD_ADDRESS_SPACE, baseAddr); return (ERROR); } if (devReadProbe(4,(volatile void *)(localAddr+DATA_0_OFFSET),(void*)&probeValue)) { printf("no VSC card at %p\n",localAddr); return(0); } /* Declare victory. */ Debug(2,"scaler_init: we own 256 bytes starting at %p\n",localAddr); scaler_state[card]->localAddr = localAddr; scaler_total_cards++; /* reset this card */ writeReg16(localAddr,RESET_OFFSET,0); /* get this card's identification */ scaler_state[card]->ident = readReg16(localAddr,REV_SERIAL_NO_OFFSET); Debug(3,"scaler_init: Serial # = %d\n", scaler_state[card]->ident); scaler_state[card]->card_exists = 1; /* get this card's type (8 or 16 channels?) */ Debug(2,"scaler_init:Base Address=0x%8.8x\n",(int)baseAddr); Debug(2,"scaler_init:Local Address=0x%8.8x\n",(int)localAddr); scaler_state[card]->num_channels = readReg16(localAddr,MODULE_TYPE_OFFSET) & 0x18; Debug(3,"scaler_init: nchan = %d\n", scaler_state[card]->num_channels); if (scaler_state[card]->num_channels < 8) { scaler_state[card]->card_exists = 0; continue; } for (i=0; i<MAX_SCALER_CHANNELS; i++) { scaler_state[card]->preset[i] = 0; } } Debug(3,"scaler_init: Total cards = %d\n\n",scaler_total_cards); #ifdef vxWorks if (epicsAtExit(scaler_shutdown, 0) < 0) epicsPrintf ("scaler_init: epicsAtExit() failed\n"); #endif Debug(3, "%s", "scaler_init: scalers initialized\n"); return(0); }
LOCAL int initialise ( const char *cardParams, void **pprivate, epicsUInt16 carrier ) { int params, status, mSize = 0; epicsUInt32 ioBase, mOrig = 0, mBase, mEnd, addr; volatile void *ptr; char *ioPtr, *mPtr = NULL; int space, slot; private_t *private; static const int offset[IO_SPACES][SLOTS] = { { PROM_A, PROM_B, PROM_C, PROM_D }, { REGS_A, REGS_B, REGS_C, REGS_D } }; if (cardParams == NULL || strlen(cardParams) == 0) { /* No params or empty string, use manufacturers default settings */ ioBase = 0x6000; mBase = 0xd0000000; params = 2; /* Pretend, mBase is in A32 space */ } else { params = sscanf(cardParams, "%i,%i,%i", &ioBase, &mBase, &mSize); if (params < 1 || params > 3 || ioBase > 0xfc00 || ioBase & 0x03ff || (params == 2 && mBase & 0x01ffffff) || (params == 3 && mBase & 0xff01ffff) || mSize < 0 || mSize > 2048 || mSize & 63) { return S_IPAC_badAddress; } } if (devRegisterAddress("VIPC616", atVMEA16, ioBase, EXTENT, &ptr)) { return S_IPAC_badAddress; } ioPtr = (char *) ptr; /* ioPtr points to ioBase in A16 space */ if (params == 1) { /* No memory, just the A16 I/O space */ mSize = 0; status = OK; } else if (params == 2) { /* A32 space, 8Mb allocated per module */ mSize = 8 << 20; status = devRegisterAddress("VIPC616", atVMEA32, mBase, mSize * SLOTS, &ptr); mPtr = (char *) ptr; /* mPtr points to mBase in A32 space */ mOrig = mBase; } else { /* A24 space, module size given, some slots may be hidden */ mSize = mSize << 10; /* Convert size from K to Bytes */ mEnd = (mBase & ~(mSize * SLOTS - 1)) + mSize * SLOTS; if (mSize) { status = devRegisterAddress("VIPC616", atVMEA24, mBase, mEnd - mBase, &ptr); mPtr = (char *) ptr; /* mPtr points to mBase in A24 space */ mOrig = mBase & ~(mSize * SLOTS - 1); } else { status = 0; } } if (status) { return S_IPAC_badAddress; } private = malloc(sizeof (private_t));
void omsMAXv::initialize(const char* portName, int numAxes, int cardNo, const char* initString, int prio, int stackSz, unsigned int vmeAddr, int intrVector, int level, epicsAddressType vmeAddrType, int paramCount) { const char* functionName = "initialize"; long status; void* probeAddr; Debug(32, "omsMAXv::initialize: start initialize\n" ); controllerType = epicsStrDup("MAXv"); // TODO check if cardNo has already been used this->cardNo = cardNo; if(cardNo < 0 || cardNo >= MAXv_NUM_CARDS){ printf("invalid cardNo: %d", cardNo); return; } epicsUInt8 *startAddr; epicsUInt8 *endAddr; epicsUInt32 boardAddrSize = 0; if (vmeAddrType == atVMEA16) boardAddrSize = 0x1000; else if (vmeAddrType == atVMEA24) boardAddrSize = 0x10000; else if (vmeAddrType == atVMEA32) boardAddrSize = 0x1000000; // if vmeAddr == 1 Setup/Config is used and not Config2 if (vmeAddr == 1) probeAddr = baseAddress + (cardNo * boardAddrSize); else probeAddr = (void*) vmeAddr; startAddr = (epicsUInt8 *) probeAddr; endAddr = startAddr + boardAddrSize; Debug(64, "motor_init: devNoResponseProbe() on addr %p\n", probeAddr); /* Scan memory space to assure card id */ while (startAddr < endAddr) { status = devNoResponseProbe(vmeAddrType, (size_t) startAddr, 2); if (status != S_dev_addressOverlap) { errlogPrintf("%s:%s:%s: Card NOT found in specified address range! \n", driverName, functionName, portName); enabled = false; return; } startAddr += (boardAddrSize / 10); } status = devRegisterAddress(controllerType, vmeAddrType, (size_t) probeAddr, boardAddrSize, (volatile void **) &pmotor); Debug(64, "motor_init: devRegisterAddress() status = %d\n", (int) status); if (status) { errlogPrintf("%s:%s:%s: Can't register address 0x%lx \n", driverName, functionName, portName, (long unsigned int) probeAddr); return; } Debug(64, "motor_init: pmotor = %p\n", pmotor); int loopCount=15; while (loopCount && (pmotor->firmware_status.Bits.initializing == 1)){ Debug(1, "MAXv port %s still initializing; status = 0x%x\n", portName, (unsigned int) pmotor->firmware_status.All); epicsThreadSleep(0.2); --loopCount; } Debug(64, "motor_init: check if card is ready\n"); if (pmotor->firmware_status.Bits.running == 0) errlogPrintf("MAXv port %s is NOT running; status = 0x%x\n", portName, (unsigned int) pmotor->firmware_status.All); Debug(64, "motor_init: init card\n"); FIRMWARE_STATUS fwStatus; fwStatus.All = pmotor->firmware_status.All; Debug(64, "motor_init: firmware status register: 0x%x\n", fwStatus.All); pmotor->IACK_vector = intrVector; pmotor->status1_flag.All = 0xFFFFFFFF; pmotor->status2_flag = 0xFFFFFFFF; /* Disable all interrupts */ pmotor->status1_irq_enable.All = 0; pmotor->status2_irq_enable = 0; Debug(64, "motor_init: clear all interrupt\n"); //sendOnly("IC"); Debug(64, "motor_init: firmware version\n"); /* get FirmwareVersion */ if(getFirmwareVersion() != asynSuccess) { errlogPrintf("%s:%s:%s: unable to talk to controller card %d\n", driverName, functionName, portName, cardNo); return; } if (fwMinor < 30 ){ errlogPrintf("%s:%s:%s: This Controllers Firmware Version %d.%d is not supported, version 1.30 or higher is mandatory\n", driverName, functionName, portName, fwMajor, fwMinor); } Debug(64, "motor_init: send init string\n"); if( Init(initString, 1) != asynSuccess) { errlogPrintf("%s:%s:%s: unable to send initstring to controller card %d\n", driverName, functionName, portName, cardNo); return; } useWatchdog = true; if (watchdogOK()) { Debug(64, "motor_init: enable interrupts ( vector=%d, level=%d) \n", intrVector, level); /* Enable interrupt-when-done if selected */ if (intrVector) motorIsrSetup((unsigned int)intrVector, level); } else return; if (epicsAtExit(&omsMAXv::resetOnExit, this)) errlogPrintf("%s:%s:%s: card %d, unable to register exit function\n", driverName, functionName, portName, cardNo); return; }
int ni1014Config(char *portNameA,char *portNameB, int base, int vector, int level, int priority, int noAutoConnect) { niport *pniportArray[2] = {0,0}; int size; int indPort,nports; long status; if(nloopsPerMicrosecond==0) initAuxmrWait(); nports = (portNameB==0 || strlen(portNameB)==0) ? 1 : 2; for(indPort=0; indPort<nports; indPort++) { niport *pniport; size = sizeof(niport); size += (indPort==0) ? strlen(portNameA) : strlen(portNameB); size += 1; pniport = callocMustSucceed(size,sizeof(char),"ni1014Config"); pniportArray[indPort] = pniport; pniport->portName = (char *)(pniport+1); strcpy(pniport->portName,((indPort==0) ? portNameA : portNameB)); pniport->base = base; pniport->vector = vector; pniport->level = level; pniport->eos = -1; pniport->waitForInterrupt = epicsEventMustCreate(epicsEventEmpty); callbackSetCallback(srqCallback,&pniport->callback); callbackSetUser(pniport,&pniport->callback); status = devRegisterAddress("drvNi1014", atVMEA16, pniport->base, PORT_REGISTER_SIZE/2,(volatile void **)&pniport->registers); if(status) { printf("%s ni1014Config devRegisterAddress failed\n",pniport->portName); return(-1); } /* attach the interrupt handler routines */ status = devConnectInterrupt(intVME,pniport->vector, ni1014,(void *)pniport); if(status) { errMessage(status,"ni1014: devConnectInterrupt"); return -1; } status = devConnectInterrupt(intVME,pniport->vector+1, ni1014Err,(void *)pniport); if(status) { errMessage(status,"ni1014: devConnectInterrupt"); return -1; } status = devEnableInterruptLevel(intVME,pniport->level); if(status) { errMessage(status,"ni1014: devEnableInterruptLevel"); return -1; } pniport->isPortA = (indPort==0) ? 1 : 0; pniport->asynGpibPvt = pasynGpib->registerPort(pniport->portName, ASYN_MULTIDEVICE|ASYN_CANBLOCK, !noAutoConnect,&gpibPort,pniport,priority,0); base = base + PORT_REGISTER_SIZE; vector += 2; } return 0; }
/** Constructor for the drvAPS_EM class. * Calls the constructor for the drvQuadEM base class. * \param[in] portName The name of the asyn port driver to be created. * \param[in] baseAddr A24 base address of the VME card * \param[in] fiberChannel Address [0-3] of the fiber channel connected to the electrometer * \param[in] unidigName Name of asynPort for the Ip-Unidig driver if it is being used to generate interrupts * \param[in] unidigChan Channel number [0-23] of the Ip-Unidig connected to the APS_EM pulse output, if Ip-Unidig is being used. * \param[in] unidigDrvInfo The drvInfo field for the data callback of the ipUnidig driver. * If not specified then asynUser->reason=0 is used. * \param[in] ringBufferSize The number of samples to hold in the input ring buffer. * This should be large enough to hold all the samples between reads of the * device, e.g. 1 ms SampleTime and 1 second read rate = 1000 samples. * If 0 then default of 2048 is used. */ drvAPS_EM::drvAPS_EM(const char *portName, unsigned short *baseAddr, int fiberChannel, const char *unidigName, int unidigChan, char *unidigDrvInfo, int ringBufferSize) : drvQuadEM(portName, 0, ringBufferSize), unidigChan_(unidigChan), pUInt32DigitalPvt_(NULL), pUInt32RegistrarPvt_(NULL) { asynInterface *pasynInterface; asynDrvUser *pdrvUser; unsigned long probeVal; epicsUInt32 mask; asynStatus status; static const char *functionName = "drvAPS_EM"; readingsAveraged_ = 0; if ((unidigName != 0) && (strlen(unidigName) != 0) && (strcmp(unidigName, "0") != 0)) { /* Create asynUser */ pUInt32DAsynUser_ = pasynManager->createAsynUser(0, 0); /* Connect to device */ status = pasynManager->connectDevice(pUInt32DAsynUser_, unidigName, unidigChan_); if (status != asynSuccess) { errlogPrintf("initQuadEM: connectDevice failed for ipUnidig\n"); goto error; } /* Get the asynUInt32DigitalCallback interface */ pasynInterface = pasynManager->findInterface(pUInt32DAsynUser_, asynUInt32DigitalType, 1); if (!pasynInterface) { errlogPrintf("%s:%s:, find asynUInt32Digital interface failed\n", driverName, functionName); goto error; } pUInt32Digital_ = (asynUInt32Digital *)pasynInterface->pinterface; pUInt32DigitalPvt_ = pasynInterface->drvPvt; /* If the drvInfo is specified then call drvUserCreate, else assume asynUser->reason=0 */ if (unidigDrvInfo) { pasynInterface = pasynManager->findInterface(pUInt32DAsynUser_, asynDrvUserType, 1); if (!pasynInterface) { errlogPrintf("%s:%s:, find asynDrvUser interface failed\n", driverName, functionName); goto error; } pdrvUser = (asynDrvUser *)pasynInterface->pinterface; status = pdrvUser->create(pasynInterface->drvPvt, pUInt32DAsynUser_, unidigDrvInfo, NULL, 0); if (status != asynSuccess) { errlogPrintf("%s:%s: drvUser->create failed for ipUnidig\n", driverName, functionName); goto error; } } else { pUInt32DAsynUser_->reason = 0; } } if ((fiberChannel >= 4) || (fiberChannel < 0)) { errlogPrintf("%s:%s:: Invalid channel # %d \n", driverName, functionName, fiberChannel); goto error; } if (baseAddr >= (unsigned short *)MAX_A24_ADDRESS) { errlogPrintf("%s:%s:: Invalid Module Address %p \n", driverName, functionName, baseAddr); goto error; } /* The channel # goes in bits 5 and 6 */ baseAddr = (unsigned short *)((int)baseAddr | ((fiberChannel << 5) & 0x60)); if (devRegisterAddress("APS_EM", atVMEA24, (int)baseAddr, 16, (volatile void**)&baseAddress_) != 0) { baseAddress_ = NULL; errlogPrintf("%s:%s: A24 Address map failed\n", driverName, functionName); goto error; } if (devReadProbe(4, (char *)baseAddress_, (char *)&probeVal) != 0 ) { errlogPrintf("%s:%s:: devReadProbe failed for address %p\n", driverName, functionName, baseAddress_); baseAddress_ = NULL; goto error; } if (pUInt32DigitalPvt_ == NULL) { if (epicsThreadCreate("APS_EMPoller", epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackMedium), (EPICSTHREADFUNC)pollerThreadC, this) == NULL) { errlogPrintf("%s:%s: quadEMPoller epicsThreadCreate failure\n", driverName, functionName); goto error; } } else { /* Make sure interrupts are enabled on the falling edge of the * quadEM output pulse */ pUInt32Digital_->getInterrupt(pUInt32DigitalPvt_, pUInt32DAsynUser_, &mask, interruptOnOneToZero); mask |= 1 << unidigChan_; pUInt32Digital_->setInterrupt(pUInt32DigitalPvt_, pUInt32DAsynUser_, mask, interruptOnOneToZero); } /* Set the model */ setIntegerParam(P_Model, QE_ModelAPS_EM); /* Set the range, ping-pong and integration time to reasonable defaults */ setRange(0); setPingPong(0); setIntegrationTime(0.001); /* Send the initial settings to the board to get it talking to the * electometer. These settings will be overridden by the database values * when the database initializes */ reset(); /* Calling readStatus() will compute the sampleTime, which must be done before iocInit * or fast feedback won't work. */ readStatus(); error: return; }
epicsStatus mrmEvgSetupVME ( const char* id, // Card Identifier epicsInt32 slot, // VME slot epicsUInt32 vmeAddress, // Desired VME address in A24 space epicsInt32 irqLevel, // Desired interrupt level epicsInt32 irqVector, // Desired interrupt vector number bool ignoreVersion) // Ignore errors due to firmware checks { volatile epicsUInt8* regCpuAddr = 0; volatile epicsUInt8* regCpuAddr2 = 0; //function 2 of regmap (fanout/concentrator specifics) struct VMECSRID info; deviceInfoT deviceInfo; info.board = 0; info.revision = 0; info.vendor = 0; deviceInfo.bus.busType = busType_vme; deviceInfo.bus.vme.slot = slot; deviceInfo.bus.vme.address = vmeAddress; deviceInfo.bus.vme.irqLevel = irqLevel; deviceInfo.bus.vme.irqVector = irqVector; deviceInfo.series = series_unknown; int status; // a variable to hold function return statuses try { if(mrf::Object::getObject(id)){ errlogPrintf("ID %s already in use\n",id); return -1; } volatile unsigned char* csrCpuAddr; // csrCpuAddr is VME-CSR space CPU address for the board csrCpuAddr = //devCSRProbeSlot(slot); devCSRTestSlot(vmeEvgIDs,slot,&info); //FIXME: add support for EVM id if(!csrCpuAddr) { errlogPrintf("No EVG in slot %d\n",slot); return -1; } epicsPrintf("##### Setting up MRF EVG in VME Slot %d #####\n",slot); epicsPrintf("Found Vendor: %08x\nBoard: %08x\nRevision: %08x\n", info.vendor, info.board, info.revision); epicsUInt32 xxx = CSRRead32(csrCpuAddr + CSR_FN_ADER(1)); if(xxx) epicsPrintf("Warning: EVG not in power on state! (%08x)\n", xxx); /*Setting the base address of Register Map on VME Board (EVG)*/ CSRSetBase(csrCpuAddr, 1, vmeAddress, VME_AM_STD_SUP_DATA); { epicsUInt32 temp=CSRRead32((csrCpuAddr) + CSR_FN_ADER(1)); if(temp != CSRADER((epicsUInt32)vmeAddress,VME_AM_STD_SUP_DATA)) { errlogPrintf("Failed to set CSR Base address in ADER1. Check VME bus and card firmware version.\n"); return -1; } } /* Create a static string for the card description (needed by vxWorks) */ char *Description = allocSNPrintf(40, "EVG-%d '%s' slot %d", info.board & MRF_BID_SERIES_MASK, id, slot); /*Register VME address and get corresponding CPU address */ status = devRegisterAddress ( Description, // Event Generator card description atVMEA24, // A24 Address space vmeAddress, // Physical address of register space EVG_REGMAP_SIZE, // Size of card's register space (volatile void **)(void *)®CpuAddr // Local address of card's register map ); if(status) { errlogPrintf("Failed to map VME address %08x\n", vmeAddress); return -1; } epicsUInt32 version = checkVersion(regCpuAddr, 0x3); epicsPrintf("Firmware version: %08x\n", version); if(version == 0){ if(ignoreVersion) { epicsPrintf("Ignoring version error.\n"); } else { return -1; } } /* Set the base address of Register Map for function 2, if we have the right firmware version */ if(version >= EVG_FCT_MIN_FIRMWARE) { deviceInfo.series = series_300; CSRSetBase(csrCpuAddr, 2, vmeAddress+EVG_REGMAP_SIZE, VME_AM_STD_SUP_DATA); { epicsUInt32 temp=CSRRead32((csrCpuAddr) + CSR_FN_ADER(2)); if(temp != CSRADER((epicsUInt32)vmeAddress+EVG_REGMAP_SIZE,VME_AM_STD_SUP_DATA)) { epicsPrintf("Failed to set CSR Base address in ADER2 for FCT register mapping. Check VME bus and card firmware version.\n"); return -1; } } /* Create a static string for the card description (needed by vxWorks) */ char *Description = allocSNPrintf(40, "EVG-%d FOUT'%s' slot %d", info.board & MRF_BID_SERIES_MASK, id, slot); status = devRegisterAddress ( Description, // Event Generator card description atVMEA24, // A24 Address space vmeAddress+EVG_REGMAP_SIZE, // Physical address of register space EVG_REGMAP_SIZE*2, // Size of card's register space (volatile void **)(void *)®CpuAddr2 // Local address of card's register map ); if(status) { errlogPrintf("Failed to map VME address %08x for FCT mapping\n", vmeAddress); return -1; } } else { deviceInfo.series = series_230; } evgMrm* evg = new evgMrm(id, deviceInfo, regCpuAddr, regCpuAddr2, NULL); if(irqLevel > 0 && irqVector >= 0) { /*Configure the Interrupt level and vector on the EVG board*/ CSRWrite8(csrCpuAddr + UCSR_DEFAULT_OFFSET + UCSR_IRQ_LEVEL, irqLevel&0x7); CSRWrite8(csrCpuAddr + UCSR_DEFAULT_OFFSET + UCSR_IRQ_VECTOR, irqVector&0xff); epicsPrintf("IRQ Level: %d\nIRQ Vector: %d\n", CSRRead8(csrCpuAddr + UCSR_DEFAULT_OFFSET + UCSR_IRQ_LEVEL), CSRRead8(csrCpuAddr + UCSR_DEFAULT_OFFSET + UCSR_IRQ_VECTOR) ); epicsPrintf("csrCpuAddr : %p\nregCpuAddr : %p\nreCpuAddr2 : %p\n",csrCpuAddr, regCpuAddr, regCpuAddr2); /*Disable the interrupts and enable them at the end of iocInit via initHooks*/ WRITE32(regCpuAddr, IrqFlag, READ32(regCpuAddr, IrqFlag)); WRITE32(regCpuAddr, IrqEnable, 0); // VME IRQ level will be enabled later during iocInit() vme_level_mask |= 1 << ((irqLevel&0x7)-1); /*Connect Interrupt handler to vector*/ if(devConnectInterruptVME(irqVector & 0xff, &evgMrm::isr_vme, evg)){ errlogPrintf("ERROR:Failed to connect VME IRQ vector %d\n" ,irqVector&0xff); delete evg; return -1; } } } catch(std::exception& e) { errlogPrintf("Error: %s\n",e.what()); errlogFlush(); return -1; } errlogFlush(); return 0; } //mrmEvgSetupVME
/*Constructor */ drvSIS3820::drvSIS3820(const char *portName, int baseAddress, int interruptVector, int interruptLevel, int maxChans, int maxSignals, bool useDma, int fifoBufferWords) : drvSIS38XX(portName, maxChans, maxSignals), useDma_(useDma) { int status; epicsUInt32 controlStatusReg; epicsUInt32 moduleID; static const char* functionName="SIS3820"; setIntegerParam(SIS38XXModel_, MODEL_SIS3820); /* Call devLib to get the system address that corresponds to the VME * base address of the board. */ status = devRegisterAddress("drvSIS3820", SIS3820_ADDRESS_TYPE, (size_t)baseAddress, SIS3820_BOARD_SIZE, (volatile void **)®isters_); if (status) { asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: %s, Can't register VME address 0x%x\n", driverName, functionName, portName, baseAddress); return; } asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: Registered VME address: 0x%x to local address: %p size: 0x%X\n", driverName, functionName, baseAddress, registers_, SIS3820_BOARD_SIZE); /* Call devLib to get the system address that corresponds to the VME * FIFO address of the board. */ fifoBaseVME_ = (epicsUInt32 *)(baseAddress + SIS3820_FIFO_BASE); status = devRegisterAddress("drvSIS3820", SIS3820_ADDRESS_TYPE, (size_t)fifoBaseVME_, SIS3820_FIFO_BYTE_SIZE, (volatile void **)&fifoBaseCPU_); if (status) { asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: %s, Can't register FIFO address 0x%x\n", driverName, functionName, portName, baseAddress + SIS3820_FIFO_BASE); return; } asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: Registered VME FIFO address: %p to local address: %p size: 0x%X\n", driverName, functionName, fifoBaseVME_, fifoBaseCPU_, SIS3820_FIFO_BYTE_SIZE); /* Probe VME bus to see if card is there */ status = devReadProbe(4, (char *) &(registers_->control_status_reg), (char *) &controlStatusReg); if (status) { asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: devReadProbe failure for address %p = %d\n", driverName, functionName, ®isters_->control_status_reg, status); return; } /* Get the module info from the card */ moduleID = (registers_->moduleID_reg & 0xFFFF0000) >> 16; asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: module ID=%x\n", driverName, functionName, moduleID); firmwareVersion_ = registers_->moduleID_reg & 0x0000FFFF; setIntegerParam(SIS38XXFirmware_, firmwareVersion_); asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: firmware=%d\n", driverName, functionName, firmwareVersion_); // Allocate FIFO readout buffer // fifoBufferWords input argument is in words, must be less than SIS3820_FIFO_WORD_SIZE if (fifoBufferWords == 0) fifoBufferWords = SIS3820_FIFO_WORD_SIZE; if (fifoBufferWords > SIS3820_FIFO_WORD_SIZE) fifoBufferWords = SIS3820_FIFO_WORD_SIZE; fifoBufferWords_ = fifoBufferWords; #ifdef vxWorks fifoBuffer_ = (epicsUInt32*) memalign(8, fifoBufferWords_*sizeof(epicsUInt32)); #else void *ptr; status = posix_memalign(&ptr, 8, fifoBufferWords_*sizeof(epicsUInt32)); if(status != 0) { printf("Error: posix_memalign status = %d\n", status); } fifoBuffer_ = (epicsUInt32*)ptr; #endif if (fifoBuffer_ == NULL) { asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: posix_memalign failure for fifoBuffer_ = %d\n", driverName, functionName, status); return; } dmaDoneEventId_ = epicsEventCreate(epicsEventEmpty); // Create the DMA ID if (useDma_) { dmaId_ = sysDmaCreate(dmaCallbackC, (void*)this); if (dmaId_ == 0 || (int)dmaId_ == -1) { asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: sysDmaCreate failed, errno=%d. Disabling use of DMA.\n", driverName, functionName, errno); useDma_ = false; } } /* Reset card */ asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: resetting port %s\n", driverName, functionName, portName); registers_->key_reset_reg = 1; /* Clear FIFO */ asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: clearing FIFO\n", driverName, functionName); resetFIFO(); // Disable 25MHz test pulses and test mode registers_->control_status_reg = CTRL_COUNTER_TEST_25MHZ_DISABLE; registers_->control_status_reg = CTRL_COUNTER_TEST_MODE_DISABLE; /* Set up the interrupt service routine */ asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: interruptServiceRoutine pointer %p\n", driverName, functionName, intFuncC); status = devConnectInterruptVME(interruptVector, intFuncC, this); if (status) { asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: Can't connect to vector % d\n", driverName, functionName, interruptVector); return; } asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: Connected interrupt vector: %d\n\n", driverName, functionName, interruptVector); /* Write interrupt level to hardware */ registers_->irq_config_reg &= ~SIS3820_IRQ_LEVEL_MASK; registers_->irq_config_reg |= (interruptLevel << 8); asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: irq after setting IntLevel= 0x%x\n", driverName, functionName, registers_->irq_config_reg); /* Write interrupt vector to hardware */ registers_->irq_config_reg &= ~SIS3820_IRQ_VECTOR_MASK; registers_->irq_config_reg |= interruptVector; asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: irq = 0x%08x\n", driverName, functionName, registers_->irq_config_reg); /* Initialize board in MCS mode. This will also set the initial value of the operation mode register. */ setAcquireMode(ACQUIRE_MODE_MCS); /* Create the thread that reads the FIFO */ if (epicsThreadCreate("SIS3820FIFOThread", epicsThreadPriorityLow, epicsThreadGetStackSize(epicsThreadStackMedium), (EPICSTHREADFUNC)readFIFOThreadC, this) == NULL) { asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: epicsThreadCreate failure\n", driverName, functionName); return; } else asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: epicsThreadCreate success\n", driverName, functionName); erase(); /* Enable interrupts in hardware */ asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: irq before enabling interrupts= 0x%08x\n", driverName, functionName, registers_->irq_config_reg); registers_->irq_config_reg |= SIS3820_IRQ_ENABLE; /* Enable interrupt level in EPICS */ status = devEnableInterruptLevel(intVME, interruptLevel); if (status) { asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: Can't enable enterrupt level %d\n", driverName, functionName, interruptLevel); return; } exists_ = true; return; }
/*************************************************** * initialize all software and hardware * scalerVS_init() ****************************************************/ STATIC long scalerVS_init(int after) { volatile char *localAddr; unsigned long status; char *baseAddr; int card, card_type; uint32 probeValue = 0; Debug(2,"scalerVS_init(): entry, after = %d\n", after); if (after || (vs_num_cards == 0)) return(0); /* allocate scalerVS_state structures, array of pointers */ if (scalerVS_state == NULL) { scalerVS_state = (struct scalerVS_state **) calloc(1, vs_num_cards * sizeof(struct scalerVS_state *)); scalerVS_total_cards=0; for (card=0; card<vs_num_cards; card++) { scalerVS_state[card] = (struct scalerVS_state *) calloc(1, sizeof(struct scalerVS_state)); } } /* Check out the hardware. */ for (card=0; card<vs_num_cards; card++) { baseAddr = (char *)(vs_addrs + card*CARD_ADDRESS_SPACE); /* Can we reserve the required block of VME address space? */ status = devRegisterAddress(__FILE__, atVMEA16, (size_t)baseAddr, CARD_ADDRESS_SPACE, (volatile void **)&localAddr); if (!RTN_SUCCESS(status)) { errPrintf(status, __FILE__, __LINE__, "Can't register 2048-byte block in VME A16 at address %p\n", baseAddr); return (ERROR); } if (devReadProbe(4,(volatile void *)(localAddr+READ_XFER_REG_OFFSET),(void*)&probeValue)) { printf("scalerVS_init: no VSxx card at %p\n",localAddr); return(0); } /* Declare victory. */ Debug(2,"scalerVS_init: we own 2048 bytes in VME A16 starting at %p\n", localAddr); scalerVS_state[card]->localAddr = localAddr; scalerVS_total_cards++; /* reset this card */ /* any write to this address causes reset */ writeReg16(localAddr,MASTER_RESET_OFFSET,0); /* get this card's type and serial number */ scalerVS_state[card]->ident = readReg16(localAddr,ID_OFFSET); Debug(3,"scalerVS_init: Serial # = %d\n", scalerVS_state[card]->ident & 0x3FF); /* get this card's type */ card_type = scalerVS_state[card]->ident >> 10; if ((card_type > 22) || (card_type < 16)) { errPrintf(status, __FILE__, __LINE__, "unrecognized module\n"); scalerVS_state[card]->num_channels = 0; scalerVS_state[card]->card_exists = 0; /* * Something's wrong with this card, but we still count it in scalerVS_total_cards. * A bad card retains its address space; otherwise we can't talk to the next one. */ } else { scalerVS_state[card]->num_channels = VS_module_types[card_type-16].num_channels; scalerVS_state[card]->card_exists = 1; } Debug(3,"scalerVS_init: nchan = %d\n", scalerVS_state[card]->num_channels); } Debug(3,"scalerVS_init: Total cards = %d\n\n",scalerVS_total_cards); #ifdef vxWorks if (epicsAtExit(scalerVS_shutdown, 0) < 0) epicsPrintf ("scalerVS_init: epicsAtExit() failed\n"); #endif Debug(3,"%s", "scalerVS_init: scalers initialized\n"); return(0); }