static long getIoIntInfo(int cmd, dbCommon *pr, IOSCANPVT *iopvt) { devInt32Pvt *pPvt = (devInt32Pvt *)pr->dpvt; asynStatus status; const char *sizeString; /* If initCommon failed then pPvt->pint32 is NULL, return error */ if (!pPvt->pint32) return -1; if (cmd == 0) { /* Add to scan list. Register interrupts */ asynPrint(pPvt->pasynUser, ASYN_TRACE_FLOW, "%s devAsynInt32::getIoIntInfo registering interrupt\n", pr->name); if (!pPvt->ringBuffer) { DBENTRY *pdbentry = dbAllocEntry(pdbbase); pPvt->ringBufferSize = DEFAULT_RING_BUFFER_SIZE; status = dbFindRecord(pdbentry, pr->name); if (status) asynPrint(pPvt->pasynUser, ASYN_TRACE_ERROR, "%s devAsynInt32::getIoIntInfo error finding record\n", pr->name); sizeString = dbGetInfo(pdbentry, "FIFO"); if (sizeString) pPvt->ringBufferSize = atoi(sizeString); pPvt->ringBuffer = epicsRingBytesCreate(pPvt->ringBufferSize*sizeof(epicsInt32)); if (!pPvt->ringBuffer) asynPrint(pPvt->pasynUser, ASYN_TRACE_ERROR, "%s devAsynInt32::getIoIntInfo error creating ring buffer\n", pr->name); else asynPrint(pPvt->pasynUser, ASYN_TRACE_FLOW, "%s devAsynInt32::getIoIntInfo created ring buffer, size=%d\n", pr->name, pPvt->ringBufferSize); } status = pPvt->pint32->registerInterruptUser( pPvt->int32Pvt,pPvt->pasynUser, pPvt->interruptCallback,pPvt,&pPvt->registrarPvt); if(status!=asynSuccess) { printf("%s devAsynInt32 registerInterruptUser %s\n", pr->name,pPvt->pasynUser->errorMessage); } } else { asynPrint(pPvt->pasynUser, ASYN_TRACE_FLOW, "%s devAsynInt32::getIoIntInfo cancelling interrupt\n", pr->name); status = pPvt->pint32->cancelInterruptUser(pPvt->int32Pvt, pPvt->pasynUser,pPvt->registrarPvt); if(status!=asynSuccess) { printf("%s devAsynInt32 cancelInterruptUser %s\n", pr->name,pPvt->pasynUser->errorMessage); } } *iopvt = pPvt->ioScanPvt; return 0; }
/** Constructor for the drvQuadEM class. * Calls constructor for the asynPortDriver base class. * \param[in] portName The name of the asyn port driver to be created. * \param[in] numParams The number of driver-specific parameters for the derived class * \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. */ drvQuadEM::drvQuadEM(const char *portName, int numParams, int ringBufferSize) : asynNDArrayDriver(portName, QE_MAX_DATA+1, /* maxAddr */ NUM_QE_PARAMS + numParams, 0, 0, /* maxBuffers, maxMemory, no limits */ asynInt32Mask | asynInt32ArrayMask | asynFloat64Mask | asynGenericPointerMask | asynDrvUserMask, /* Interface mask */ asynInt32Mask | asynInt32ArrayMask | asynFloat64Mask | asynGenericPointerMask, /* Interrupt mask */ ASYN_CANBLOCK | ASYN_MULTIDEVICE, /* asynFlags. This driver blocks it is multi-device */ 1, /* Autoconnect */ 0, /* Default priority */ 0) /* Default stack size*/ { int i; int status; const char *functionName = "drvQuadEM"; asynUser *pasynUser; createParam(P_AcquireString, asynParamInt32, &P_Acquire); createParam(P_AcquireModeString, asynParamInt32, &P_AcquireMode); createParam(P_CurrentOffsetString, asynParamFloat64, &P_CurrentOffset); createParam(P_CurrentScaleString, asynParamFloat64, &P_CurrentScale); createParam(P_PositionOffsetString, asynParamFloat64, &P_PositionOffset); createParam(P_PositionScaleString, asynParamFloat64, &P_PositionScale); createParam(P_GeometryString, asynParamInt32, &P_Geometry); createParam(P_DoubleDataString, asynParamFloat64, &P_DoubleData); createParam(P_IntArrayDataString, asynParamInt32Array, &P_IntArrayData); createParam(P_RingOverflowsString, asynParamInt32, &P_RingOverflows); createParam(P_ReadDataString, asynParamInt32, &P_ReadData); createParam(P_PingPongString, asynParamInt32, &P_PingPong); createParam(P_IntegrationTimeString, asynParamFloat64, &P_IntegrationTime); createParam(P_SampleTimeString, asynParamFloat64, &P_SampleTime); createParam(P_RangeString, asynParamInt32, &P_Range); createParam(P_ResetString, asynParamInt32, &P_Reset); createParam(P_TriggerModeString, asynParamInt32, &P_TriggerMode); createParam(P_NumChannelsString, asynParamInt32, &P_NumChannels); createParam(P_BiasStateString, asynParamInt32, &P_BiasState); createParam(P_BiasVoltageString, asynParamFloat64, &P_BiasVoltage); createParam(P_BiasInterlockString, asynParamInt32, &P_BiasInterlock); createParam(P_HVSReadbackString, asynParamInt32, &P_HVSReadback); createParam(P_HVVReadbackString, asynParamFloat64, &P_HVVReadback); createParam(P_HVIReadbackString, asynParamFloat64, &P_HVIReadback); createParam(P_TemperatureString, asynParamFloat64, &P_Temperature); createParam(P_ReadStatusString, asynParamInt32, &P_ReadStatus); createParam(P_ResolutionString, asynParamInt32, &P_Resolution); createParam(P_ValuesPerReadString, asynParamInt32, &P_ValuesPerRead); createParam(P_NumAcquireString, asynParamInt32, &P_NumAcquire); createParam(P_NumAcquiredString, asynParamInt32, &P_NumAcquired); createParam(P_ReadFormatString, asynParamInt32, &P_ReadFormat); createParam(P_AveragingTimeString, asynParamFloat64, &P_AveragingTime); createParam(P_NumAverageString, asynParamInt32, &P_NumAverage); createParam(P_NumAveragedString, asynParamInt32, &P_NumAveraged); createParam(P_ModelString, asynParamInt32, &P_Model); createParam(P_FirmwareString, asynParamOctet, &P_Firmware); setIntegerParam(P_Acquire, 0); setIntegerParam(P_RingOverflows, 0); setIntegerParam(P_PingPong, 0); setDoubleParam(P_IntegrationTime, 0.); setIntegerParam(P_Range, 0); setIntegerParam(P_TriggerMode, 0); setIntegerParam(P_NumChannels, 4); numChannels_ = 4; setIntegerParam(P_BiasState, 0); setDoubleParam(P_BiasVoltage, 0.); setIntegerParam(P_Resolution, 16); setIntegerParam(P_ValuesPerRead, 1); setIntegerParam(P_ReadFormat, 0); for (i=0; i<QE_MAX_DATA; i++) { setDoubleParam(i, P_DoubleData, 0.0); } valuesPerRead_ = 1; if (ringBufferSize <= 0) ringBufferSize = QE_DEFAULT_RING_BUFFER_SIZE; ringBuffer_ = epicsRingBytesCreate(ringBufferSize * QE_MAX_DATA * sizeof(epicsFloat64)); ringEvent_ = epicsEventCreate(epicsEventEmpty); /* Create the thread that does callbacks when the ring buffer has numAverage samples */ status = (asynStatus)(epicsThreadCreate("drvQuadEMCallbackTask", epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackMedium), (EPICSTHREADFUNC)::callbackTaskC, this) == NULL); if (status) { printf("%s:%s: epicsThreadCreate failure, status=%d\n", driverName, functionName, status); return; } // This driver supports QE_MAX_DATA+1 addresses = 0-11 with autoConnect=1. But there are only records // connected to addresses 0-3, so addresses 4-11 never show as "connected" since nothing ever calls // pasynManager->queueRequest. So we do an exceptionConnect to each address so asynManager will show // them as connected. Note that this is NOT necessary for the driver to function correctly, the // NDPlugins will still get called even for addresses that are not "connected". It is just to // avoid confusion. for (i=0; i<QE_MAX_DATA+1; i++) { pasynUser = pasynManager->createAsynUser(0,0); pasynManager->connectDevice(pasynUser, portName, i); pasynManager->exceptionConnect(pasynUser); } epicsAtExit(exitHandlerC, this); }