Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
/***************************************************
* 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);
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
0
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);
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
0
/*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;
}
Ejemplo n.º 9
0
/***************************************************
* 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);
}