epicsUInt32 checkVersion(volatile epicsUInt8 *base, unsigned int required) { #ifndef __linux__ epicsUInt32 junk; if(devReadProbe(sizeof(junk), (volatile void*)(base+U32_FWVersion), (void*)&junk)) { throw std::runtime_error("Failed to read from MRM registers (but could read CSR registers)\n"); } #endif epicsUInt32 type, ver; epicsUInt32 v = READ32(base, FWVersion); epicsPrintf("FPGA version: %08x\n", v); type = v >> FWVersion_type_shift; if(type != 0x2){ errlogPrintf("Found type %x which does not correspond to EVG type 0x2.\n", type); return 0; } ver = v & FWVersion_ver_mask; if(ver < required) { errlogPrintf("Firmware version >= %x is required got %x\n", required,ver); return 0; } return ver; }
int ipcCheckId ( ipac_idProm_t *id ) { epicsUInt16 word; if (id == NULL) { return S_IPAC_badDriver; } if (devReadProbe(sizeof(word), (void *)&id->asciiI, (char *)&word)) { return S_IPAC_noModule; } if ((word & 0xff) != 'I') { return S_IPAC_noIpacId; } /* * The Format-1 check is deliberately de-optimized to fix a problem with * IP modules which can't handle back-to-back accesses that compilers * may generate if the "IPAC" ID is tested in a single if () statement. * Format-2 modules should be Ok though. */ if ((id->asciiP & 0xff) != 'P') { /* Format-2 ID Prom? */ ipac_idProm2_t *id2 = (ipac_idProm2_t *) id; if (id2->asciiVI == ('V' << 8 | 'I') && id2->asciiTA == ('T' << 8 | 'A') && id2->ascii4_ == ('4' << 8 | ' ') ) { return OK; } return S_IPAC_noIpacId; } if ((id->asciiA & 0xff) != 'A') { return S_IPAC_noIpacId; } word = id->asciiC & 0xff; if ((word != 'C') && (word != 'H')) { return S_IPAC_noIpacId; } return OK; }
void xycom220setup(int id,int base) { xy220 *card=malloc(sizeof(xy220)); epicsUInt8 junk; volatile epicsUInt8 **ba; if(!card){ printf("Allocation failed\n"); return; } card->id=id; card->base_addr=base; ba=&card->base; if(devBusToLocalAddr(atVMEA16, card->base_addr, (volatile void **)ba)){ printf("Failed to map %lx for card %x\n",(unsigned long)card->base,id); free(card); return; } if(devReadProbe(1, card->base+U8_XY220_ID, &junk)){ printf("Failed to read %lx for card %x\n",(unsigned long)(card->base+U8_XY220_ID),id); free(card); return; } WRITE16(card->base, XY220_CSR, X220_CSR_RST); WRITE16(card->base, XY220_CSR, X220_CSR_RED|X220_CSR_GRN); card->guard=epicsMutexMustCreate(); if(dbg220>0) printf("%d mapped %lx as %lx\n",id,(unsigned long)card->base,(unsigned long)card->base); ellAdd(&xy220s,&card->node); 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); }
/*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; }
void xycom566setup( int id, int cbase, int dbase, int level, int vec, int bipol ){ xy566 *card; volatile epicsUInt8 **cb; volatile epicsUInt16 **db; epicsUInt16 junk; if(cbase<0 || cbase>0xffff){ printf("config (A16) out of range\n"); return; } if(dbase<0 || dbase>0xffffff){ printf("data (A24) out of range\n"); return; } if(level<0 || level>7){ printf("Level out of range (0->7)\n"); return; } if(vec<0 || vec>0xff){ printf("Vector out of range (0->255)\n"); return; } card=get566(id); if(!!card){ printf("ID %d already exists\n",id); return; } card=malloc(sizeof(xy566)); if(!card){ printf("Out of memory!\n"); return; } memset(&card->dlen,0,sizeof(card->dlen)); memset(&card->cb_irq,0,sizeof(card->cb_irq)); card->id=id; card->fail=0; card->clk_div=0; /* stc uninitialized */ card->use_seq_clk=0; ellInit(&card->seq_ctor); if(!bipol) card->nchan=32; else card->nchan=16; card->ivec=vec; card->base_addr=cbase; card->data_addr=dbase; cb=&card->base; db=&card->data_base; if(devBusToLocalAddr(atVMEA16, card->base_addr, (volatile void **)cb)){ printf("Failed to map A16 %lx for card %x\n", (unsigned long)card->base_addr,id); free(card); return; } if(devBusToLocalAddr(atVMEA24, card->data_addr, (volatile void **)db)){ printf("Failed to map A24 %lx for card %x\n", (unsigned long)card->data_base,id); free(card); return; } if(devReadProbe(2, card->base+U16_XY566_CSR, &junk)){ printf("Failed to read A16 %lx for card %x\n", (unsigned long)(card->base+U16_XY566_CSR),id); free(card); return; } if(devReadProbe(2, card->data_base, &junk)){ printf("Failed to read A24 %lx for card %x\n", (unsigned long)(card->data_base),id); free(card); return; } WRITE16(card->base, XY566_CSR, XY566_CSR_RST); /* Reset */ /* turn on green and red to indicate init start */ WRITE16(card->base, XY566_CSR, XY566_CSR_GRN); WRITE16(card->base, XY566_RAM, 0); WRITE8(card->base, XY566_SEQ, 0); card->guard=epicsMutexMustCreate(); scanIoInit(&card->seq_irq); callbackSetCallback(xycom566isrcb, &card->cb_irq); callbackSetPriority(priorityHigh, &card->cb_irq); callbackSetUser(card, &card->cb_irq); WRITE8(card->base, XY566_VEC, vec); devEnableInterruptLevelVME(level); assert(devConnectInterruptVME(vec, xycom566isr, card)==0); /* Configure card * Mode: continuous sequence (default) * 16 bit conversion (default) * sequence controller disable (will be enabled during drvsup init) */ WRITE16(card->base, XY566_CSR, XY566_CSR_GRN); ellAdd(&xy566s,&card->node); }
/** 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; }
/*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); }