コード例 #1
0
ファイル: devScaler_VS.c プロジェクト: A2-Collaboration/epics
/**************************************************
* scalerEndOfGateISRSetup()
***************************************************/
STATIC int scalerEndOfGateISRSetup(int card)
{
	long status;
	volatile char *addr;
	volatile uint16 u16;

	Debug(5, "scalerEndOfGateISRSetup: Entry, card #%d\n", card);
	if (card >= scalerVS_total_cards) return(ERROR);
	addr = scalerVS_state[card]->localAddr;

	status = devConnectInterruptVME(vs_InterruptVector + card,
		(void *) &scalerEndOfGateISR, (void *)card);
	if (!RTN_SUCCESS(status)) {
		errPrintf(status, __FILE__, __LINE__, "Can't connect to vector %d\n",
			  vs_InterruptVector + card);
		return (ERROR);
	}

	/* write interrupt level to hardware, and tell EPICS to enable that level */
	u16 = readReg16(addr,IRQ_SETUP_OFFSET) & 0x0ff;
	/* OR in level for end-of-gate interrupt */
	writeReg16(addr,IRQ_SETUP_OFFSET, u16 | (vs_InterruptLevel << 8));
	status = devEnableInterruptLevelVME(vs_InterruptLevel);
	if (!RTN_SUCCESS(status)) {
		errPrintf(status, __FILE__, __LINE__,
			  "Can't enable enterrupt level %d\n", vs_InterruptLevel);
		return (ERROR);
	}
	Debug(5, "scalerEndOfGateISRSetup: Wrote interrupt level, %d, to hardware\n",
	      vs_InterruptLevel);

	/* Write interrupt vector to hardware */
	writeReg16(addr,IRQ_3_GATE_VECTOR_OFFSET, (uint16)(vs_InterruptVector + card));
	Debug(5, "scalerEndOfGateISRSetup: Wrote interrupt vector, %d, to hardware\n",
	      vs_InterruptVector + card);

	Debug(5, "scalerEndOfGateISRSetup: Read interrupt vector, %d, from hardware\n",
	      readReg16(addr,IRQ_3_GATE_VECTOR_OFFSET) & 0x0ff);

	Debug(5, "scalerEndOfGateISRSetup: Exit, card #%d\n", card);
	return (OK);
}
コード例 #2
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 **)&registers_);

  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 *) &registers_->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;
}
コード例 #3
0
IpUnidig::IpUnidig(const char *portName, int carrier, int slot, int msecPoll, int intVec, int risingMask, int fallingMask)
  :asynPortDriver(portName,1,NUM_IPUNIDIG_PARAMS,
                  asynInt32Mask | asynUInt32DigitalMask | asynDrvUserMask,
                  asynUInt32DigitalMask,
                  0,1,0,0),
  risingMask_(risingMask),
  fallingMask_(fallingMask),
  polarityMask_(risingMask)
  
{
  //static const char *functionName = "IpUnidig";
  ipac_idProm_t *id;
  epicsUInt16 *base;

  /* Default of 100 msec for backwards compatibility with old version */
  if (msecPoll == 0) msecPoll = 100;
  pollTime_ = msecPoll / 1000.;
  messagesSent_ = 0;
  messagesFailed_ = 0;
  rebooting_ = 0;
  forceCallback_ = 0;
  oldBits_ = 0;
  msgQId_ = epicsMessageQueueCreate(MAX_MESSAGES, sizeof(ipUnidigMessage));

  if (ipmCheck(carrier, slot)) {
    errlogPrintf("IpUnidig: bad carrier or slot\n");
  }
  id = (ipac_idProm_t *) ipmBaseAddr(carrier, slot, ipac_addrID);
  base = (epicsUInt16 *) ipmBaseAddr(carrier, slot, ipac_addrIO);
  baseAddress_ = base;

  manufacturer_ = id->manufacturerId & 0xff;
  model_ = id->modelId & 0xff;
  switch (manufacturer_) {
  case GREENSPRING_ID:
    switch (model_) {
      case UNIDIG_E:
      case UNIDIG:
      case UNIDIG_D:
      case UNIDIG_O_24IO:
      case UNIDIG_HV_16I8O:
      case UNIDIG_E48:
      case UNIDIG_I_O_24I:
      case UNIDIG_I_E:
      case UNIDIG_I:
      case UNIDIG_I_D:
      case UNIDIG_I_O_24IO:
      case UNIDIG_I_HV_16I8O:
      case UNIDIG_O_12I12O:
      case UNIDIG_I_O_12I12O:
      case UNIDIG_O_24I:
      case UNIDIG_HV_8I16O:
      case UNIDIG_I_HV_8I16O:
        break;
      default:
        errlogPrintf("IpUnidig model 0x%x not supported\n",model_);
        break;
    }
    break;

  case SYSTRAN_ID:
    if(model_ != SYSTRAN_DIO316I) {
      errlogPrintf("IpUnidig model 0x%x not Systran DIO316I\n",model_);
    }
    break;
       
  case SBS_ID:
    if(model_ != SBS_IPOPTOIO8) {
      errlogPrintf("IpUnidig model 0x%x not SBS IP-OPTOIO-8\n",model_);
    }
    break;
     
  default: 
    errlogPrintf("IpUnidig manufacturer 0x%x not supported\n", manufacturer_);
    break;
  }

  /* Set up the register pointers.  Set the defaults for most modules */
  /* Define registers in units of 16-bit words */
  regs_.outputRegisterLow        = base;
  regs_.outputRegisterHigh       = base + 0x1;
  regs_.inputRegisterLow         = base + 0x2;
  regs_.inputRegisterHigh        = base + 0x3;
  regs_.outputEnableLow          = base + 0x8;
  regs_.outputEnableHigh         = base + 0x5;
  regs_.controlRegister0         = base + 0x6;
  regs_.intVecRegister           = base + 0x8;
  regs_.intEnableRegisterLow     = base + 0x9;
  regs_.intEnableRegisterHigh    = base + 0xa;
  regs_.intPolarityRegisterLow   = base + 0xb;
  regs_.intPolarityRegisterHigh  = base + 0xc;
  regs_.intClearRegisterLow      = base + 0xd;
  regs_.intClearRegisterHigh     = base + 0xe;
  regs_.intPendingRegisterLow    = base + 0xd;
  regs_.intPendingRegisterHigh   = base + 0xe;
  regs_.DACRegister              = base + 0xe;
    
  /* Set things up for specific models which need to be treated differently */
  switch (manufacturer_) {
    case GREENSPRING_ID: 
      switch (model_) {
        case UNIDIG_O_24IO:
        case UNIDIG_O_12I12O:
        case UNIDIG_I_O_24IO:
        case UNIDIG_I_O_12I12O:
          /* Enable outputs */
          *regs_.controlRegister0 |= 0x4;
          break;
        case UNIDIG_HV_16I8O:
        case UNIDIG_I_HV_16I8O:
          /*  These modules don't allow access to outputRegisterLow */
          regs_.outputRegisterLow = NULL;
          /* Set the comparator DAC for 2.5 volts.  Each bit is 15 mV. */
          *regs_.DACRegister = 2500/15;
          break;
      }
      break;
    case SYSTRAN_ID:
      switch (model_) {
        case SYSTRAN_DIO316I:
          /* Different register layout */
          regs_.outputRegisterLow  = base;
          regs_.outputRegisterHigh = base + 0x1;
          regs_.inputRegisterLow   = base + 0x2;
          regs_.inputRegisterHigh  = NULL;
          regs_.controlRegister0   = base + 0x3;
          regs_.controlRegister1   = base + 0x4;
          /* Enable outputs for ports 0-3 */
          *regs_.controlRegister0  |= 0xf;
          /* Set direction of ports 0-1 to be output */
          *regs_.controlRegister1  |= 0x3;
          break;
      }
      break;
    case SBS_ID:
      switch (model_) {
        case SBS_IPOPTOIO8:
          /* Different register layout */
          memset(&regs_, 0, sizeof(regs_));
          regs_.inputRegisterLow   = base + 1;
          regs_.outputRegisterLow  = base + 2;
          regs_.controlRegister0   = base + 3;
          *regs_.controlRegister0 = 0x00;   /* Start state machine reset */
          *regs_.controlRegister0 = 0x01;   /* ....   */
          *regs_.controlRegister0 = 0x00;   /* State machine in state 0 */
          *regs_.controlRegister0 = 0x2B;   /* Select Port B DDR */
          *regs_.controlRegister0 = 0xFF;   /* All Port B bits are inputs */
          *regs_.controlRegister0 = 0x2A;   /* Select Port B DPPR */
          *regs_.controlRegister0 = 0xFF;   /* All Port B bits inverted */
          *regs_.controlRegister0 = 0x01;   /* Select MCCR */
          *regs_.controlRegister0 = 0x84;   /* Enable ports A and B */
           break;
      }
      break;
  }
  switch (model_) {
    case UNIDIG_I_O_24I:
    case UNIDIG_I_E:
    case UNIDIG_I:
    case UNIDIG_I_D:
    case UNIDIG_I_O_24IO:
    case UNIDIG_I_HV_16I8O:
    case UNIDIG_I_O_12I12O:
    case UNIDIG_I_HV_8I16O:
      supportsInterrupts_ = 1;
      break;
    default:
      supportsInterrupts_ = 0;
      break;
  }

  /* Create the asynPortDriver parameter for the data */
  createParam(digitalInputString,  asynParamUInt32Digital, &digitalInputParam_); 
  createParam(digitalOutputString, asynParamUInt32Digital, &digitalOutputParam_); 
  createParam(DACOutputString,     asynParamInt32,         &DACOutputParam_); 

  // We use this to call readUInt32Digital, which needs the correct reason
  pasynUserSelf->reason = digitalInputParam_;
  
  // Set the values of rising mask and falling mask in the parameter library, just for reporting purposes
  asynPortDriver::setUInt32DigitalInterrupt(digitalInputParam_, risingMask_, interruptOnZeroToOne);
  asynPortDriver::setUInt32DigitalInterrupt(digitalInputParam_, fallingMask_, interruptOnOneToZero);
   
  /* Start the thread to poll and handle interrupt callbacks to 
   * device support */
  epicsThreadCreate("ipUnidig",
                    epicsThreadPriorityHigh,
                    epicsThreadGetStackSize(epicsThreadStackBig),
                    (EPICSTHREADFUNC)pollerThreadC,
                    this);

  /* If the interrupt vector is zero, don't bother with interrupts, 
   * since the user probably didn't pass this
   * parameter to IpUnidig::init().  This is an optional parameter added
   * after initial release. */
  if (supportsInterrupts_ && (intVec !=0)) {
    /* Interrupt support */
    /* Write to the interrupt polarity and enable registers */
    *regs_.intVecRegister = intVec;
    if (devConnectInterruptVME(intVec, intFuncC, (void *)this)) {
      errlogPrintf("ipUnidig interrupt connect failure\n");
    }
    *regs_.intPolarityRegisterLow  = (epicsUInt16)polarityMask_;
    *regs_.intPolarityRegisterHigh = (epicsUInt16)(polarityMask_ >> 16);
    writeIntEnableRegs();

    /* Enable IPAC module interrupts and set module status. */
    ipmIrqCmd(carrier, slot, 0, ipac_irqEnable);
    ipmIrqCmd(carrier, slot, 0, ipac_statActive);
  }
コード例 #4
0
ファイル: drv566.c プロジェクト: mdavidsaver/xycomioc
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);
}
コード例 #5
0
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 *)&regCpuAddr  // 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 *)&regCpuAddr2 // 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
コード例 #6
0
ファイル: drvSIS3820.cpp プロジェクト: keenanlang/mca
/*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 **)&registers_);

  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, &registers_->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;
}